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}
68 \renewcommand{\familydefault}{\sfdefault}
69 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
75 # Configuration for the latex/pdf docs.
77 'papersize': 'a4paper',
80 'classoptions': ',openany,oneside',
81 'babel': '\\usepackage[english]{babel}',
82 # customize Latex formatting
83 'preamble': custom_latex_preamble
87 # Override the default Latex formatter in order to modify the
88 # code/verbatim blocks.
89 class CustomLatexFormatter(LatexFormatter):
90 def __init__(self, **options):
91 super(CustomLatexFormatter, self).__init__(**options)
92 # Use the second smallest font size for code/verbatim blocks.
93 self.verboptions = r'formatcom=\footnotesize'
95 # Replace the default latex formatter.
96 PygmentsBridge.latex_formatter = CustomLatexFormatter
98 # Configuration for man pages
99 man_pages = [("testpmd_app_ug/run_app", "testpmd",
100 "tests for dpdk pmds", "", 1),
101 ("tools/pdump", "dpdk-pdump",
102 "enable packet capture on dpdk ports", "", 1),
103 ("tools/proc_info", "dpdk-procinfo",
104 "access dpdk port stats and memory info", "", 1),
105 ("tools/pmdinfo", "dpdk-pmdinfo",
106 "dump a PMDs hardware support info", "", 1),
107 ("tools/devbind", "dpdk-devbind",
108 "check device status and bind/unbind them from drivers", "", 8)]
111 # ####### :numref: fallback ########
112 # The following hook functions add some simple handling for the :numref:
113 # directive for Sphinx versions prior to 1.3.1. The functions replace the
114 # :numref: reference with a link to the target (for all Sphinx doc types).
115 # It doesn't try to label figures/tables.
116 def numref_role(reftype, rawtext, text, lineno, inliner):
118 Add a Sphinx role to handle numref references. Note, we can't convert
119 the link here because the doctree isn't build and the target information
122 # Add an identifier to distinguish numref from other references.
123 newnode = nodes.reference('',
125 refuri='_local_numref_#%s' % text,
130 def process_numref(app, doctree, from_docname):
132 Process the numref nodes once the doctree has been built and prior to
133 writing the files. The processing involves replacing the numref with a
134 link plus text to indicate if it is a Figure or Table link.
137 # Iterate over the reference nodes in the doctree.
138 for node in doctree.traverse(nodes.reference):
139 target = node.get('refuri', '')
141 # Look for numref nodes.
142 if target.startswith('_local_numref_#'):
143 target = target.replace('_local_numref_#', '')
145 # Get the target label and link information from the Sphinx env.
146 data = app.builder.env.domains['std'].data
147 docname, label, _ = data['labels'].get(target, ('', '', ''))
148 relative_url = app.builder.get_relative_uri(from_docname, docname)
150 # Add a text label to the link.
151 if target.startswith('figure'):
153 elif target.startswith('table'):
158 # New reference node with the updated link information.
159 newnode = nodes.reference('',
161 refuri='%s#%s' % (relative_url, label),
163 node.replace_self(newnode)
166 def generate_overview_table(output_filename, table_id, section, table_name, title):
168 Function to generate the Overview Table from the ini files that define
169 the features for each driver.
171 The default features for the table and their order is defined by the
175 # Default warning string.
176 warning = 'Warning generate_overview_table()'
178 # Get the default features and order from the 'default.ini' file.
179 ini_path = path_join(dirname(output_filename), 'features')
180 config = configparser.ConfigParser()
181 config.optionxform = str
182 config.read(path_join(ini_path, 'default.ini'))
183 default_features = config.items(section)
185 # Create a dict of the valid features to validate the other ini files.
187 max_feature_length = 0
188 for feature in default_features:
190 valid_features[key] = ' '
191 max_feature_length = max(max_feature_length, len(key))
193 # Get a list of driver ini files, excluding 'default.ini'.
194 ini_files = [basename(file) for file in listdir(ini_path)
195 if file.endswith('.ini') and file != 'default.ini']
198 # Build up a list of the table header names from the ini filenames.
200 for ini_filename in ini_files:
201 name = ini_filename[:-4]
202 name = name.replace('_vf', 'vf')
203 pmd_names.append(name)
205 # Pad the table header names.
206 max_header_len = len(max(pmd_names, key=len))
208 for name in pmd_names:
210 pmd, vec = name.split('_')
211 name = '{0:{fill}{align}{width}}vec'.format(pmd,
212 fill='.', align='<', width=max_header_len-3)
214 name = '{0:{fill}{align}{width}}'.format(name,
215 fill=' ', align='<', width=max_header_len)
216 header_names.append(name)
218 # Create a dict of the defined features for each driver from the ini files.
220 for ini_filename in ini_files:
221 config = configparser.ConfigParser()
222 config.optionxform = str
223 config.read(path_join(ini_path, ini_filename))
225 # Initialize the dict with the default.ini value.
226 ini_data[ini_filename] = valid_features.copy()
228 # Check for a valid ini section.
229 if not config.has_section(section):
230 print("{}: File '{}' has no [{}] secton".format(warning,
235 # Check for valid features names.
236 for name, value in config.items(section):
237 if name not in valid_features:
238 print("{}: Unknown feature '{}' in '{}'".format(warning,
244 # Get the first letter only.
245 ini_data[ini_filename][name] = value[0]
247 # Print out the RST Driver Overview table from the ini file data.
248 outfile = open(output_filename, 'w')
249 num_cols = len(header_names)
251 print_table_css(outfile, table_id)
252 print('.. table:: ' + table_name + '\n', file=outfile)
253 print_table_header(outfile, num_cols, header_names, title)
254 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
257 def print_table_header(outfile, num_cols, header_names, title):
258 """ Print the RST table header. The header names are vertical. """
259 print_table_divider(outfile, num_cols)
262 for name in header_names:
263 line += ' ' + name[0]
265 print_table_row(outfile, title, line)
267 for i in range(1, len(header_names[0])):
269 for name in header_names:
270 line += ' ' + name[i]
272 print_table_row(outfile, '', line)
274 print_table_divider(outfile, num_cols)
277 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
278 """ Print out the body of the table. Each row is a NIC feature. """
280 for feature, _ in default_features:
283 for ini_filename in ini_files:
284 line += ' ' + ini_data[ini_filename][feature]
286 print_table_row(outfile, feature, line)
288 print_table_divider(outfile, num_cols)
291 def print_table_row(outfile, feature, line):
292 """ Print a single row of the table with fixed formatting. """
294 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
297 def print_table_divider(outfile, num_cols):
298 """ Print the table divider line. """
300 column_dividers = ['='] * num_cols
301 line += ' '.join(column_dividers)
303 feature = '=' * feature_str_len
305 print_table_row(outfile, feature, line)
308 def print_table_css(outfile, table_id):
320 table#idx th, table#idx td {
325 white-space: pre-wrap;
331 table#idx col:first-child {
334 table#idx th:first-child {
335 vertical-align: bottom;
341 table#idx td:first-child {
345 table#idx tr:nth-child(2n-1) td {
346 background-color: rgba(210, 210, 210, 0.2);
348 table#idx th:not(:first-child):hover,
349 table#idx td:not(:first-child):hover {
352 table#idx th:not(:first-child):hover::after,
353 table#idx td:not(:first-child):hover::after {
361 background-color: #ffb;
363 table#idx tr:hover td {
364 background-color: #ffb;
368 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
372 table_file = dirname(__file__) + '/nics/overview_table.txt'
373 generate_overview_table(table_file, 1,
375 'Features availability in networking drivers',
377 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
378 generate_overview_table(table_file, 1,
380 'Features availability in crypto drivers',
382 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
383 generate_overview_table(table_file, 2,
385 'Cipher algorithms in crypto drivers',
387 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
388 generate_overview_table(table_file, 3,
390 'Authentication algorithms in crypto drivers',
391 'Authentication algorithm')
392 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
393 generate_overview_table(table_file, 4,
395 'AEAD algorithms in crypto drivers',
397 table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
398 generate_overview_table(table_file, 5,
400 'Asymmetric algorithms in crypto drivers',
401 'Asymmetric algorithm')
402 table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
403 generate_overview_table(table_file, 1,
405 'Features availability in compression drivers',
408 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
409 print('Upgrade sphinx to version >= 1.3.1 for '
410 'improved Figure/Table number handling.')
411 # Add a role to handle :numref: references.
412 app.add_role('numref', numref_role)
413 # Process the numref references once the doctree has been created.
414 app.connect('doctree-resolved', process_numref)
416 app.add_stylesheet('css/custom.css')