2 # SPDX-License-Identifier: BSD-3-Clause
3 # Copyright(c) 2010-2015 Intel Corporation
5 from docutils import nodes
6 from distutils.version import LooseVersion
7 from sphinx import __version__ as sphinx_version
8 from sphinx.highlighting import PygmentsBridge
9 from pygments.formatters.latex import LatexFormatter
10 from os import listdir
11 from os import environ
12 from os.path import basename
13 from os.path import dirname
14 from os.path import join as path_join
19 import sphinx_rtd_theme
21 html_theme = "sphinx_rtd_theme"
22 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
24 print('Install the sphinx ReadTheDocs theme for improved html documentation '
25 'layout: https://sphinx-rtd-theme.readthedocs.io/')
28 project = 'Data Plane Development Kit'
29 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
30 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
31 html_add_permalinks = ""
32 html_show_copyright = False
33 highlight_language = 'none'
35 release = environ['DPDK_VERSION']
40 # Maximum feature description string length
43 # Figures, tables and code-blocks automatically numbered if they have caption
54 # Latex directives to be included directly in the latex/pdf docs.
55 custom_latex_preamble = r"""
56 \usepackage{textalpha}
57 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
63 # Configuration for the latex/pdf docs.
65 'papersize': 'a4paper',
68 'classoptions': ',openany,oneside',
69 'babel': '\\usepackage[english]{babel}',
70 # customize Latex formatting
71 'preamble': custom_latex_preamble
75 # Override the default Latex formatter in order to modify the
76 # code/verbatim blocks.
77 class CustomLatexFormatter(LatexFormatter):
78 def __init__(self, **options):
79 super(CustomLatexFormatter, self).__init__(**options)
80 # Use the second smallest font size for code/verbatim blocks.
81 self.verboptions = r'formatcom=\footnotesize'
83 # Replace the default latex formatter.
84 PygmentsBridge.latex_formatter = CustomLatexFormatter
86 # Configuration for man pages
87 man_pages = [("testpmd_app_ug/run_app", "testpmd",
88 "tests for dpdk pmds", "", 1),
89 ("tools/pdump", "dpdk-pdump",
90 "enable packet capture on dpdk ports", "", 1),
91 ("tools/proc_info", "dpdk-procinfo",
92 "access dpdk port stats and memory info", "", 1),
93 ("tools/pmdinfo", "dpdk-pmdinfo",
94 "dump a PMDs hardware support info", "", 1),
95 ("tools/devbind", "dpdk-devbind",
96 "check device status and bind/unbind them from drivers", "", 8)]
99 # ####### :numref: fallback ########
100 # The following hook functions add some simple handling for the :numref:
101 # directive for Sphinx versions prior to 1.3.1. The functions replace the
102 # :numref: reference with a link to the target (for all Sphinx doc types).
103 # It doesn't try to label figures/tables.
104 def numref_role(reftype, rawtext, text, lineno, inliner):
106 Add a Sphinx role to handle numref references. Note, we can't convert
107 the link here because the doctree isn't build and the target information
110 # Add an identifier to distinguish numref from other references.
111 newnode = nodes.reference('',
113 refuri='_local_numref_#%s' % text,
118 def process_numref(app, doctree, from_docname):
120 Process the numref nodes once the doctree has been built and prior to
121 writing the files. The processing involves replacing the numref with a
122 link plus text to indicate if it is a Figure or Table link.
125 # Iterate over the reference nodes in the doctree.
126 for node in doctree.traverse(nodes.reference):
127 target = node.get('refuri', '')
129 # Look for numref nodes.
130 if target.startswith('_local_numref_#'):
131 target = target.replace('_local_numref_#', '')
133 # Get the target label and link information from the Sphinx env.
134 data = app.builder.env.domains['std'].data
135 docname, label, _ = data['labels'].get(target, ('', '', ''))
136 relative_url = app.builder.get_relative_uri(from_docname, docname)
138 # Add a text label to the link.
139 if target.startswith('figure'):
141 elif target.startswith('table'):
146 # New reference node with the updated link information.
147 newnode = nodes.reference('',
149 refuri='%s#%s' % (relative_url, label),
151 node.replace_self(newnode)
154 def generate_overview_table(output_filename, table_id, section, table_name, title):
156 Function to generate the Overview Table from the ini files that define
157 the features for each driver.
159 The default features for the table and their order is defined by the
163 # Default warning string.
164 warning = 'Warning generate_overview_table()'
166 # Get the default features and order from the 'default.ini' file.
167 ini_path = path_join(dirname(output_filename), 'features')
168 config = configparser.ConfigParser()
169 config.optionxform = str
170 config.read(path_join(ini_path, 'default.ini'))
171 default_features = config.items(section)
173 # Create a dict of the valid features to validate the other ini files.
175 max_feature_length = 0
176 for feature in default_features:
178 valid_features[key] = ' '
179 max_feature_length = max(max_feature_length, len(key))
181 # Get a list of driver ini files, excluding 'default.ini'.
182 ini_files = [basename(file) for file in listdir(ini_path)
183 if file.endswith('.ini') and file != 'default.ini']
186 # Build up a list of the table header names from the ini filenames.
188 for ini_filename in ini_files:
189 name = ini_filename[:-4]
190 name = name.replace('_vf', 'vf')
191 pmd_names.append(name)
193 # Pad the table header names.
194 max_header_len = len(max(pmd_names, key=len))
196 for name in pmd_names:
198 pmd, vec = name.split('_')
199 name = '{0:{fill}{align}{width}}vec'.format(pmd,
200 fill='.', align='<', width=max_header_len-3)
202 name = '{0:{fill}{align}{width}}'.format(name,
203 fill=' ', align='<', width=max_header_len)
204 header_names.append(name)
206 # Create a dict of the defined features for each driver from the ini files.
208 for ini_filename in ini_files:
209 config = configparser.ConfigParser()
210 config.optionxform = str
211 config.read(path_join(ini_path, ini_filename))
213 # Initialize the dict with the default.ini value.
214 ini_data[ini_filename] = valid_features.copy()
216 # Check for a valid ini section.
217 if not config.has_section(section):
218 print("{}: File '{}' has no [{}] secton".format(warning,
223 # Check for valid features names.
224 for name, value in config.items(section):
225 if name not in valid_features:
226 print("{}: Unknown feature '{}' in '{}'".format(warning,
232 # Get the first letter only.
233 ini_data[ini_filename][name] = value[0]
235 # Print out the RST Driver Overview table from the ini file data.
236 outfile = open(output_filename, 'w')
237 num_cols = len(header_names)
239 print_table_css(outfile, table_id)
240 print('.. table:: ' + table_name + '\n', file=outfile)
241 print_table_header(outfile, num_cols, header_names, title)
242 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
245 def print_table_header(outfile, num_cols, header_names, title):
246 """ Print the RST table header. The header names are vertical. """
247 print_table_divider(outfile, num_cols)
250 for name in header_names:
251 line += ' ' + name[0]
253 print_table_row(outfile, title, line)
255 for i in range(1, len(header_names[0])):
257 for name in header_names:
258 line += ' ' + name[i]
260 print_table_row(outfile, '', line)
262 print_table_divider(outfile, num_cols)
265 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
266 """ Print out the body of the table. Each row is a NIC feature. """
268 for feature, _ in default_features:
271 for ini_filename in ini_files:
272 line += ' ' + ini_data[ini_filename][feature]
274 print_table_row(outfile, feature, line)
276 print_table_divider(outfile, num_cols)
279 def print_table_row(outfile, feature, line):
280 """ Print a single row of the table with fixed formatting. """
282 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
285 def print_table_divider(outfile, num_cols):
286 """ Print the table divider line. """
288 column_dividers = ['='] * num_cols
289 line += ' '.join(column_dividers)
291 feature = '=' * feature_str_len
293 print_table_row(outfile, feature, line)
296 def print_table_css(outfile, table_id):
310 line-height: inherit;
312 table#idx th, table#idx td {
314 border: solid 1px #ddd;
319 table#idx th, table#idx th p {
321 white-space: pre-wrap;
325 table#idx col:first-child {
328 table#idx th:first-child {
329 vertical-align: bottom;
334 table#idx td, table#idx td p {
337 table#idx td:first-child {
341 table#idx tr:nth-child(2n-1) td {
342 background-color: rgba(210, 210, 210, 0.2);
344 table#idx th:not(:first-child):hover,
345 table#idx td:not(:first-child):hover {
348 table#idx th:not(:first-child):hover::after,
349 table#idx td:not(:first-child):hover::after {
357 background-color: #ffb;
359 table#idx tr:hover td {
360 background-color: #ffb;
364 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
368 table_file = dirname(__file__) + '/nics/overview_table.txt'
369 generate_overview_table(table_file, 1,
371 'Features availability in networking drivers',
373 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
374 generate_overview_table(table_file, 1,
376 'Features availability in crypto drivers',
378 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
379 generate_overview_table(table_file, 2,
381 'Cipher algorithms in crypto drivers',
383 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
384 generate_overview_table(table_file, 3,
386 'Authentication algorithms in crypto drivers',
387 'Authentication algorithm')
388 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
389 generate_overview_table(table_file, 4,
391 'AEAD algorithms in crypto drivers',
393 table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
394 generate_overview_table(table_file, 5,
396 'Asymmetric algorithms in crypto drivers',
397 'Asymmetric algorithm')
398 table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
399 generate_overview_table(table_file, 1,
401 'Features availability in compression drivers',
403 table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
404 generate_overview_table(table_file, 1,
406 'Features availability in regex drivers',
408 table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
409 generate_overview_table(table_file, 1,
411 'Features availability in vDPA drivers',
413 table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
414 generate_overview_table(table_file, 1,
416 'Features availability in bbdev drivers',
419 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
420 print('Upgrade sphinx to version >= 1.3.1 for '
421 'improved Figure/Table number handling.')
422 # Add a role to handle :numref: references.
423 app.add_role('numref', numref_role)
424 # Process the numref references once the doctree has been created.
425 app.connect('doctree-resolved', process_numref)
428 # New function in sphinx 1.8
429 app.add_css_file('css/custom.css')
431 app.add_stylesheet('css/custom.css')