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']
39 # Maximum feature description string length
42 # Figures, tables and code-blocks automatically numbered if they have caption
53 # Latex directives to be included directly in the latex/pdf docs.
54 custom_latex_preamble = r"""
55 \usepackage{textalpha}
56 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
62 # Configuration for the latex/pdf docs.
64 'papersize': 'a4paper',
67 'classoptions': ',openany,oneside',
68 'babel': '\\usepackage[english]{babel}',
69 # customize Latex formatting
70 'preamble': custom_latex_preamble
74 # Override the default Latex formatter in order to modify the
75 # code/verbatim blocks.
76 class CustomLatexFormatter(LatexFormatter):
77 def __init__(self, **options):
78 super(CustomLatexFormatter, self).__init__(**options)
79 # Use the second smallest font size for code/verbatim blocks.
80 self.verboptions = r'formatcom=\footnotesize'
82 # Replace the default latex formatter.
83 PygmentsBridge.latex_formatter = CustomLatexFormatter
85 # Configuration for man pages
86 man_pages = [("testpmd_app_ug/run_app", "testpmd",
87 "tests for dpdk pmds", "", 1),
88 ("tools/pdump", "dpdk-pdump",
89 "enable packet capture on dpdk ports", "", 1),
90 ("tools/proc_info", "dpdk-procinfo",
91 "access dpdk port stats and memory info", "", 1),
92 ("tools/pmdinfo", "dpdk-pmdinfo",
93 "dump a PMDs hardware support info", "", 1),
94 ("tools/devbind", "dpdk-devbind",
95 "check device status and bind/unbind them from drivers", "", 8)]
98 # ####### :numref: fallback ########
99 # The following hook functions add some simple handling for the :numref:
100 # directive for Sphinx versions prior to 1.3.1. The functions replace the
101 # :numref: reference with a link to the target (for all Sphinx doc types).
102 # It doesn't try to label figures/tables.
103 def numref_role(reftype, rawtext, text, lineno, inliner):
105 Add a Sphinx role to handle numref references. Note, we can't convert
106 the link here because the doctree isn't build and the target information
109 # Add an identifier to distinguish numref from other references.
110 newnode = nodes.reference('',
112 refuri='_local_numref_#%s' % text,
117 def process_numref(app, doctree, from_docname):
119 Process the numref nodes once the doctree has been built and prior to
120 writing the files. The processing involves replacing the numref with a
121 link plus text to indicate if it is a Figure or Table link.
124 # Iterate over the reference nodes in the doctree.
125 for node in doctree.traverse(nodes.reference):
126 target = node.get('refuri', '')
128 # Look for numref nodes.
129 if target.startswith('_local_numref_#'):
130 target = target.replace('_local_numref_#', '')
132 # Get the target label and link information from the Sphinx env.
133 data = app.builder.env.domains['std'].data
134 docname, label, _ = data['labels'].get(target, ('', '', ''))
135 relative_url = app.builder.get_relative_uri(from_docname, docname)
137 # Add a text label to the link.
138 if target.startswith('figure'):
140 elif target.startswith('table'):
145 # New reference node with the updated link information.
146 newnode = nodes.reference('',
148 refuri='%s#%s' % (relative_url, label),
150 node.replace_self(newnode)
153 def generate_overview_table(output_filename, table_id, section, table_name, title):
155 Function to generate the Overview Table from the ini files that define
156 the features for each driver.
158 The default features for the table and their order is defined by the
162 # Default warning string.
163 warning = 'Warning generate_overview_table()'
165 # Get the default features and order from the 'default.ini' file.
166 ini_path = path_join(dirname(output_filename), 'features')
167 config = configparser.ConfigParser()
168 config.optionxform = str
169 config.read(path_join(ini_path, 'default.ini'))
170 default_features = config.items(section)
172 # Create a dict of the valid features to validate the other ini files.
174 max_feature_length = 0
175 for feature in default_features:
177 valid_features[key] = ' '
178 max_feature_length = max(max_feature_length, len(key))
180 # Get a list of driver ini files, excluding 'default.ini'.
181 ini_files = [basename(file) for file in listdir(ini_path)
182 if file.endswith('.ini') and file != 'default.ini']
185 # Build up a list of the table header names from the ini filenames.
187 for ini_filename in ini_files:
188 name = ini_filename[:-4]
189 name = name.replace('_vf', 'vf')
190 pmd_names.append(name)
192 # Pad the table header names.
193 max_header_len = len(max(pmd_names, key=len))
195 for name in pmd_names:
197 pmd, vec = name.split('_')
198 name = '{0:{fill}{align}{width}}vec'.format(pmd,
199 fill='.', align='<', width=max_header_len-3)
201 name = '{0:{fill}{align}{width}}'.format(name,
202 fill=' ', align='<', width=max_header_len)
203 header_names.append(name)
205 # Create a dict of the defined features for each driver from the ini files.
207 for ini_filename in ini_files:
208 config = configparser.ConfigParser()
209 config.optionxform = str
210 config.read(path_join(ini_path, ini_filename))
212 # Initialize the dict with the default.ini value.
213 ini_data[ini_filename] = valid_features.copy()
215 # Check for a valid ini section.
216 if not config.has_section(section):
217 print("{}: File '{}' has no [{}] secton".format(warning,
222 # Check for valid features names.
223 for name, value in config.items(section):
224 if name not in valid_features:
225 print("{}: Unknown feature '{}' in '{}'".format(warning,
231 # Get the first letter only.
232 ini_data[ini_filename][name] = value[0]
234 # Print out the RST Driver Overview table from the ini file data.
235 outfile = open(output_filename, 'w')
236 num_cols = len(header_names)
238 print_table_css(outfile, table_id)
239 print('.. table:: ' + table_name + '\n', file=outfile)
240 print_table_header(outfile, num_cols, header_names, title)
241 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
244 def print_table_header(outfile, num_cols, header_names, title):
245 """ Print the RST table header. The header names are vertical. """
246 print_table_divider(outfile, num_cols)
249 for name in header_names:
250 line += ' ' + name[0]
252 print_table_row(outfile, title, line)
254 for i in range(1, len(header_names[0])):
256 for name in header_names:
257 line += ' ' + name[i]
259 print_table_row(outfile, '', line)
261 print_table_divider(outfile, num_cols)
264 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
265 """ Print out the body of the table. Each row is a NIC feature. """
267 for feature, _ in default_features:
270 for ini_filename in ini_files:
271 line += ' ' + ini_data[ini_filename][feature]
273 print_table_row(outfile, feature, line)
275 print_table_divider(outfile, num_cols)
278 def print_table_row(outfile, feature, line):
279 """ Print a single row of the table with fixed formatting. """
281 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
284 def print_table_divider(outfile, num_cols):
285 """ Print the table divider line. """
287 column_dividers = ['='] * num_cols
288 line += ' '.join(column_dividers)
290 feature = '=' * feature_str_len
292 print_table_row(outfile, feature, line)
295 def print_table_css(outfile, table_id):
309 line-height: inherit;
311 table#idx th, table#idx td {
313 border: solid 1px #ddd;
318 table#idx th, table#idx th p {
320 white-space: pre-wrap;
324 table#idx col:first-child {
327 table#idx th:first-child {
328 vertical-align: bottom;
333 table#idx td, table#idx td p {
336 table#idx td:first-child {
340 table#idx tr:nth-child(2n-1) td {
341 background-color: rgba(210, 210, 210, 0.2);
343 table#idx th:not(:first-child):hover,
344 table#idx td:not(:first-child):hover {
347 table#idx th:not(:first-child):hover::after,
348 table#idx td:not(:first-child):hover::after {
356 background-color: #ffb;
358 table#idx tr:hover td {
359 background-color: #ffb;
363 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
367 table_file = dirname(__file__) + '/nics/overview_table.txt'
368 generate_overview_table(table_file, 1,
370 'Features availability in networking drivers',
372 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
373 generate_overview_table(table_file, 1,
375 'Features availability in crypto drivers',
377 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
378 generate_overview_table(table_file, 2,
380 'Cipher algorithms in crypto drivers',
382 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
383 generate_overview_table(table_file, 3,
385 'Authentication algorithms in crypto drivers',
386 'Authentication algorithm')
387 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
388 generate_overview_table(table_file, 4,
390 'AEAD algorithms in crypto drivers',
392 table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
393 generate_overview_table(table_file, 5,
395 'Asymmetric algorithms in crypto drivers',
396 'Asymmetric algorithm')
397 table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
398 generate_overview_table(table_file, 1,
400 'Features availability in compression drivers',
402 table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
403 generate_overview_table(table_file, 1,
405 'Features availability in regex drivers',
407 table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
408 generate_overview_table(table_file, 1,
410 'Features availability in vDPA drivers',
412 table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
413 generate_overview_table(table_file, 1,
415 'Features availability in bbdev drivers',
418 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
419 print('Upgrade sphinx to version >= 1.3.1 for '
420 'improved Figure/Table number handling.')
421 # Add a role to handle :numref: references.
422 app.add_role('numref', numref_role)
423 # Process the numref references once the doctree has been created.
424 app.connect('doctree-resolved', process_numref)
427 # New function in sphinx 1.8
428 app.add_css_file('css/custom.css')
430 app.add_stylesheet('css/custom.css')