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[utf8]{inputenc}
66 \usepackage[T1]{fontenc}
67 \usepackage{textalpha}
69 \renewcommand{\familydefault}{\sfdefault}
70 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
76 # Configuration for the latex/pdf docs.
78 'papersize': 'a4paper',
81 'classoptions': ',openany,oneside',
82 'babel': '\\usepackage[english]{babel}',
83 # customize Latex formatting
84 'preamble': custom_latex_preamble
88 # Override the default Latex formatter in order to modify the
89 # code/verbatim blocks.
90 class CustomLatexFormatter(LatexFormatter):
91 def __init__(self, **options):
92 super(CustomLatexFormatter, self).__init__(**options)
93 # Use the second smallest font size for code/verbatim blocks.
94 self.verboptions = r'formatcom=\footnotesize'
96 # Replace the default latex formatter.
97 PygmentsBridge.latex_formatter = CustomLatexFormatter
99 # Configuration for man pages
100 man_pages = [("testpmd_app_ug/run_app", "testpmd",
101 "tests for dpdk pmds", "", 1),
102 ("tools/pdump", "dpdk-pdump",
103 "enable packet capture on dpdk ports", "", 1),
104 ("tools/proc_info", "dpdk-procinfo",
105 "access dpdk port stats and memory info", "", 1),
106 ("tools/pmdinfo", "dpdk-pmdinfo",
107 "dump a PMDs hardware support info", "", 1),
108 ("tools/devbind", "dpdk-devbind",
109 "check device status and bind/unbind them from drivers", "", 8)]
112 # ####### :numref: fallback ########
113 # The following hook functions add some simple handling for the :numref:
114 # directive for Sphinx versions prior to 1.3.1. The functions replace the
115 # :numref: reference with a link to the target (for all Sphinx doc types).
116 # It doesn't try to label figures/tables.
117 def numref_role(reftype, rawtext, text, lineno, inliner):
119 Add a Sphinx role to handle numref references. Note, we can't convert
120 the link here because the doctree isn't build and the target information
123 # Add an identifier to distinguish numref from other references.
124 newnode = nodes.reference('',
126 refuri='_local_numref_#%s' % text,
131 def process_numref(app, doctree, from_docname):
133 Process the numref nodes once the doctree has been built and prior to
134 writing the files. The processing involves replacing the numref with a
135 link plus text to indicate if it is a Figure or Table link.
138 # Iterate over the reference nodes in the doctree.
139 for node in doctree.traverse(nodes.reference):
140 target = node.get('refuri', '')
142 # Look for numref nodes.
143 if target.startswith('_local_numref_#'):
144 target = target.replace('_local_numref_#', '')
146 # Get the target label and link information from the Sphinx env.
147 data = app.builder.env.domains['std'].data
148 docname, label, _ = data['labels'].get(target, ('', '', ''))
149 relative_url = app.builder.get_relative_uri(from_docname, docname)
151 # Add a text label to the link.
152 if target.startswith('figure'):
154 elif target.startswith('table'):
159 # New reference node with the updated link information.
160 newnode = nodes.reference('',
162 refuri='%s#%s' % (relative_url, label),
164 node.replace_self(newnode)
167 def generate_overview_table(output_filename, table_id, section, table_name, title):
169 Function to generate the Overview Table from the ini files that define
170 the features for each driver.
172 The default features for the table and their order is defined by the
176 # Default warning string.
177 warning = 'Warning generate_overview_table()'
179 # Get the default features and order from the 'default.ini' file.
180 ini_path = path_join(dirname(output_filename), 'features')
181 config = configparser.ConfigParser()
182 config.optionxform = str
183 config.read(path_join(ini_path, 'default.ini'))
184 default_features = config.items(section)
186 # Create a dict of the valid features to validate the other ini files.
188 max_feature_length = 0
189 for feature in default_features:
191 valid_features[key] = ' '
192 max_feature_length = max(max_feature_length, len(key))
194 # Get a list of driver ini files, excluding 'default.ini'.
195 ini_files = [basename(file) for file in listdir(ini_path)
196 if file.endswith('.ini') and file != 'default.ini']
199 # Build up a list of the table header names from the ini filenames.
201 for ini_filename in ini_files:
202 name = ini_filename[:-4]
203 name = name.replace('_vf', 'vf')
204 pmd_names.append(name)
206 # Pad the table header names.
207 max_header_len = len(max(pmd_names, key=len))
209 for name in pmd_names:
211 pmd, vec = name.split('_')
212 name = '{0:{fill}{align}{width}}vec'.format(pmd,
213 fill='.', align='<', width=max_header_len-3)
215 name = '{0:{fill}{align}{width}}'.format(name,
216 fill=' ', align='<', width=max_header_len)
217 header_names.append(name)
219 # Create a dict of the defined features for each driver from the ini files.
221 for ini_filename in ini_files:
222 config = configparser.ConfigParser()
223 config.optionxform = str
224 config.read(path_join(ini_path, ini_filename))
226 # Initialize the dict with the default.ini value.
227 ini_data[ini_filename] = valid_features.copy()
229 # Check for a valid ini section.
230 if not config.has_section(section):
231 print("{}: File '{}' has no [{}] secton".format(warning,
236 # Check for valid features names.
237 for name, value in config.items(section):
238 if name not in valid_features:
239 print("{}: Unknown feature '{}' in '{}'".format(warning,
245 # Get the first letter only.
246 ini_data[ini_filename][name] = value[0]
248 # Print out the RST Driver Overview table from the ini file data.
249 outfile = open(output_filename, 'w')
250 num_cols = len(header_names)
252 print_table_css(outfile, table_id)
253 print('.. table:: ' + table_name + '\n', file=outfile)
254 print_table_header(outfile, num_cols, header_names, title)
255 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
258 def print_table_header(outfile, num_cols, header_names, title):
259 """ Print the RST table header. The header names are vertical. """
260 print_table_divider(outfile, num_cols)
263 for name in header_names:
264 line += ' ' + name[0]
266 print_table_row(outfile, title, line)
268 for i in range(1, len(header_names[0])):
270 for name in header_names:
271 line += ' ' + name[i]
273 print_table_row(outfile, '', line)
275 print_table_divider(outfile, num_cols)
278 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
279 """ Print out the body of the table. Each row is a NIC feature. """
281 for feature, _ in default_features:
284 for ini_filename in ini_files:
285 line += ' ' + ini_data[ini_filename][feature]
287 print_table_row(outfile, feature, line)
289 print_table_divider(outfile, num_cols)
292 def print_table_row(outfile, feature, line):
293 """ Print a single row of the table with fixed formatting. """
295 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
298 def print_table_divider(outfile, num_cols):
299 """ Print the table divider line. """
301 column_dividers = ['='] * num_cols
302 line += ' '.join(column_dividers)
304 feature = '=' * feature_str_len
306 print_table_row(outfile, feature, line)
309 def print_table_css(outfile, table_id):
321 table#idx th, table#idx td {
326 white-space: pre-wrap;
332 table#idx col:first-child {
335 table#idx th:first-child {
336 vertical-align: bottom;
342 table#idx td:first-child {
346 table#idx tr:nth-child(2n-1) td {
347 background-color: rgba(210, 210, 210, 0.2);
349 table#idx th:not(:first-child):hover,
350 table#idx td:not(:first-child):hover {
353 table#idx th:not(:first-child):hover::after,
354 table#idx td:not(:first-child):hover::after {
362 background-color: #ffb;
364 table#idx tr:hover td {
365 background-color: #ffb;
369 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
373 table_file = dirname(__file__) + '/nics/overview_table.txt'
374 generate_overview_table(table_file, 1,
376 'Features availability in networking drivers',
378 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
379 generate_overview_table(table_file, 1,
381 'Features availability in crypto drivers',
383 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
384 generate_overview_table(table_file, 2,
386 'Cipher algorithms in crypto drivers',
388 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
389 generate_overview_table(table_file, 3,
391 'Authentication algorithms in crypto drivers',
392 'Authentication algorithm')
393 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
394 generate_overview_table(table_file, 4,
396 'AEAD algorithms in crypto drivers',
398 table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
399 generate_overview_table(table_file, 5,
401 'Asymmetric algorithms in crypto drivers',
402 'Asymmetric algorithm')
403 table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
404 generate_overview_table(table_file, 1,
406 'Features availability in compression drivers',
409 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
410 print('Upgrade sphinx to version >= 1.3.1 for '
411 'improved Figure/Table number handling.')
412 # Add a role to handle :numref: references.
413 app.add_role('numref', numref_role)
414 # Process the numref references once the doctree has been created.
415 app.connect('doctree-resolved', process_numref)
417 app.add_stylesheet('css/custom.css')