1 # SPDX-License-Identifier: BSD-3-Clause
2 # Copyright(c) 2010-2015 Intel Corporation
4 from __future__ import print_function
6 from docutils import nodes
7 from distutils.version import LooseVersion
8 from sphinx import __version__ as sphinx_version
9 from sphinx.highlighting import PygmentsBridge
10 from pygments.formatters.latex import LatexFormatter
11 from os import listdir
12 from os import environ
13 from os.path import basename
14 from os.path import dirname
15 from os.path import join as path_join
19 import ConfigParser as configparser
25 import sphinx_rtd_theme
27 html_theme = "sphinx_rtd_theme"
28 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
30 print('Install the sphinx ReadTheDocs theme for improved html documentation '
31 'layout: pip install sphinx_rtd_theme')
34 project = 'Data Plane Development Kit'
35 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
36 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
37 html_add_permalinks = ""
38 html_show_copyright = False
39 highlight_language = 'none'
41 # If MAKEFLAGS is exported by the user, garbage text might end up in version
42 version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion'],
43 env=dict(environ, MAKEFLAGS=""))
44 version = version.decode('utf-8').rstrip()
49 # Maximum feature description string length
52 # Figures, tables and code-blocks automatically numbered if they have caption
63 # Latex directives to be included directly in the latex/pdf docs.
64 custom_latex_preamble = r"""
65 \usepackage{textalpha}
66 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
72 # Configuration for the latex/pdf docs.
74 'papersize': 'a4paper',
77 'classoptions': ',openany,oneside',
78 'babel': '\\usepackage[english]{babel}',
79 # customize Latex formatting
80 'preamble': custom_latex_preamble
84 # Override the default Latex formatter in order to modify the
85 # code/verbatim blocks.
86 class CustomLatexFormatter(LatexFormatter):
87 def __init__(self, **options):
88 super(CustomLatexFormatter, self).__init__(**options)
89 # Use the second smallest font size for code/verbatim blocks.
90 self.verboptions = r'formatcom=\footnotesize'
92 # Replace the default latex formatter.
93 PygmentsBridge.latex_formatter = CustomLatexFormatter
95 # Configuration for man pages
96 man_pages = [("testpmd_app_ug/run_app", "testpmd",
97 "tests for dpdk pmds", "", 1),
98 ("tools/pdump", "dpdk-pdump",
99 "enable packet capture on dpdk ports", "", 1),
100 ("tools/proc_info", "dpdk-procinfo",
101 "access dpdk port stats and memory info", "", 1),
102 ("tools/pmdinfo", "dpdk-pmdinfo",
103 "dump a PMDs hardware support info", "", 1),
104 ("tools/devbind", "dpdk-devbind",
105 "check device status and bind/unbind them from drivers", "", 8)]
108 # ####### :numref: fallback ########
109 # The following hook functions add some simple handling for the :numref:
110 # directive for Sphinx versions prior to 1.3.1. The functions replace the
111 # :numref: reference with a link to the target (for all Sphinx doc types).
112 # It doesn't try to label figures/tables.
113 def numref_role(reftype, rawtext, text, lineno, inliner):
115 Add a Sphinx role to handle numref references. Note, we can't convert
116 the link here because the doctree isn't build and the target information
119 # Add an identifier to distinguish numref from other references.
120 newnode = nodes.reference('',
122 refuri='_local_numref_#%s' % text,
127 def process_numref(app, doctree, from_docname):
129 Process the numref nodes once the doctree has been built and prior to
130 writing the files. The processing involves replacing the numref with a
131 link plus text to indicate if it is a Figure or Table link.
134 # Iterate over the reference nodes in the doctree.
135 for node in doctree.traverse(nodes.reference):
136 target = node.get('refuri', '')
138 # Look for numref nodes.
139 if target.startswith('_local_numref_#'):
140 target = target.replace('_local_numref_#', '')
142 # Get the target label and link information from the Sphinx env.
143 data = app.builder.env.domains['std'].data
144 docname, label, _ = data['labels'].get(target, ('', '', ''))
145 relative_url = app.builder.get_relative_uri(from_docname, docname)
147 # Add a text label to the link.
148 if target.startswith('figure'):
150 elif target.startswith('table'):
155 # New reference node with the updated link information.
156 newnode = nodes.reference('',
158 refuri='%s#%s' % (relative_url, label),
160 node.replace_self(newnode)
163 def generate_overview_table(output_filename, table_id, section, table_name, title):
165 Function to generate the Overview Table from the ini files that define
166 the features for each driver.
168 The default features for the table and their order is defined by the
172 # Default warning string.
173 warning = 'Warning generate_overview_table()'
175 # Get the default features and order from the 'default.ini' file.
176 ini_path = path_join(dirname(output_filename), 'features')
177 config = configparser.ConfigParser()
178 config.optionxform = str
179 config.read(path_join(ini_path, 'default.ini'))
180 default_features = config.items(section)
182 # Create a dict of the valid features to validate the other ini files.
184 max_feature_length = 0
185 for feature in default_features:
187 valid_features[key] = ' '
188 max_feature_length = max(max_feature_length, len(key))
190 # Get a list of driver ini files, excluding 'default.ini'.
191 ini_files = [basename(file) for file in listdir(ini_path)
192 if file.endswith('.ini') and file != 'default.ini']
195 # Build up a list of the table header names from the ini filenames.
197 for ini_filename in ini_files:
198 name = ini_filename[:-4]
199 name = name.replace('_vf', 'vf')
200 pmd_names.append(name)
202 # Pad the table header names.
203 max_header_len = len(max(pmd_names, key=len))
205 for name in pmd_names:
207 pmd, vec = name.split('_')
208 name = '{0:{fill}{align}{width}}vec'.format(pmd,
209 fill='.', align='<', width=max_header_len-3)
211 name = '{0:{fill}{align}{width}}'.format(name,
212 fill=' ', align='<', width=max_header_len)
213 header_names.append(name)
215 # Create a dict of the defined features for each driver from the ini files.
217 for ini_filename in ini_files:
218 config = configparser.ConfigParser()
219 config.optionxform = str
220 config.read(path_join(ini_path, ini_filename))
222 # Initialize the dict with the default.ini value.
223 ini_data[ini_filename] = valid_features.copy()
225 # Check for a valid ini section.
226 if not config.has_section(section):
227 print("{}: File '{}' has no [{}] secton".format(warning,
232 # Check for valid features names.
233 for name, value in config.items(section):
234 if name not in valid_features:
235 print("{}: Unknown feature '{}' in '{}'".format(warning,
241 # Get the first letter only.
242 ini_data[ini_filename][name] = value[0]
244 # Print out the RST Driver Overview table from the ini file data.
245 outfile = open(output_filename, 'w')
246 num_cols = len(header_names)
248 print_table_css(outfile, table_id)
249 print('.. table:: ' + table_name + '\n', file=outfile)
250 print_table_header(outfile, num_cols, header_names, title)
251 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
254 def print_table_header(outfile, num_cols, header_names, title):
255 """ Print the RST table header. The header names are vertical. """
256 print_table_divider(outfile, num_cols)
259 for name in header_names:
260 line += ' ' + name[0]
262 print_table_row(outfile, title, line)
264 for i in range(1, len(header_names[0])):
266 for name in header_names:
267 line += ' ' + name[i]
269 print_table_row(outfile, '', line)
271 print_table_divider(outfile, num_cols)
274 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
275 """ Print out the body of the table. Each row is a NIC feature. """
277 for feature, _ in default_features:
280 for ini_filename in ini_files:
281 line += ' ' + ini_data[ini_filename][feature]
283 print_table_row(outfile, feature, line)
285 print_table_divider(outfile, num_cols)
288 def print_table_row(outfile, feature, line):
289 """ Print a single row of the table with fixed formatting. """
291 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
294 def print_table_divider(outfile, num_cols):
295 """ Print the table divider line. """
297 column_dividers = ['='] * num_cols
298 line += ' '.join(column_dividers)
300 feature = '=' * feature_str_len
302 print_table_row(outfile, feature, line)
305 def print_table_css(outfile, table_id):
317 table#idx th, table#idx td {
322 white-space: pre-wrap;
328 table#idx col:first-child {
331 table#idx th:first-child {
332 vertical-align: bottom;
338 table#idx td:first-child {
342 table#idx tr:nth-child(2n-1) td {
343 background-color: rgba(210, 210, 210, 0.2);
345 table#idx th:not(:first-child):hover,
346 table#idx td:not(:first-child):hover {
349 table#idx th:not(:first-child):hover::after,
350 table#idx td:not(:first-child):hover::after {
358 background-color: #ffb;
360 table#idx tr:hover td {
361 background-color: #ffb;
365 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
369 table_file = dirname(__file__) + '/nics/overview_table.txt'
370 generate_overview_table(table_file, 1,
372 'Features availability in networking drivers',
374 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
375 generate_overview_table(table_file, 1,
377 'Features availability in crypto drivers',
379 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
380 generate_overview_table(table_file, 2,
382 'Cipher algorithms in crypto drivers',
384 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
385 generate_overview_table(table_file, 3,
387 'Authentication algorithms in crypto drivers',
388 'Authentication algorithm')
389 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
390 generate_overview_table(table_file, 4,
392 'AEAD algorithms in crypto drivers',
394 table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
395 generate_overview_table(table_file, 5,
397 'Asymmetric algorithms in crypto drivers',
398 'Asymmetric algorithm')
399 table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
400 generate_overview_table(table_file, 1,
402 'Features availability in compression drivers',
404 table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
405 generate_overview_table(table_file, 1,
407 'Features availability in vDPA drivers',
410 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
411 print('Upgrade sphinx to version >= 1.3.1 for '
412 'improved Figure/Table number handling.')
413 # Add a role to handle :numref: references.
414 app.add_role('numref', numref_role)
415 # Process the numref references once the doctree has been created.
416 app.connect('doctree-resolved', process_numref)
418 app.add_stylesheet('css/custom.css')