1 # SPDX-License-Identifier: BSD-3-Clause
2 # Copyright(c) 2010-2015 Intel Corporation
4 from __future__ import print_function
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
18 import ConfigParser as configparser
24 import sphinx_rtd_theme
26 html_theme = "sphinx_rtd_theme"
27 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
29 print('Install the sphinx ReadTheDocs theme for improved html documentation '
30 'layout: pip install sphinx_rtd_theme')
33 project = 'Data Plane Development Kit'
34 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
35 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
36 html_add_permalinks = ""
37 html_show_copyright = False
38 highlight_language = 'none'
40 release = environ['DPDK_VERSION']
44 # Maximum feature description string length
47 # Figures, tables and code-blocks automatically numbered if they have caption
58 # Latex directives to be included directly in the latex/pdf docs.
59 custom_latex_preamble = r"""
60 \usepackage{textalpha}
61 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
67 # Configuration for the latex/pdf docs.
69 'papersize': 'a4paper',
72 'classoptions': ',openany,oneside',
73 'babel': '\\usepackage[english]{babel}',
74 # customize Latex formatting
75 'preamble': custom_latex_preamble
79 # Override the default Latex formatter in order to modify the
80 # code/verbatim blocks.
81 class CustomLatexFormatter(LatexFormatter):
82 def __init__(self, **options):
83 super(CustomLatexFormatter, self).__init__(**options)
84 # Use the second smallest font size for code/verbatim blocks.
85 self.verboptions = r'formatcom=\footnotesize'
87 # Replace the default latex formatter.
88 PygmentsBridge.latex_formatter = CustomLatexFormatter
90 # Configuration for man pages
91 man_pages = [("testpmd_app_ug/run_app", "testpmd",
92 "tests for dpdk pmds", "", 1),
93 ("tools/pdump", "dpdk-pdump",
94 "enable packet capture on dpdk ports", "", 1),
95 ("tools/proc_info", "dpdk-procinfo",
96 "access dpdk port stats and memory info", "", 1),
97 ("tools/pmdinfo", "dpdk-pmdinfo",
98 "dump a PMDs hardware support info", "", 1),
99 ("tools/devbind", "dpdk-devbind",
100 "check device status and bind/unbind them from drivers", "", 8)]
103 # ####### :numref: fallback ########
104 # The following hook functions add some simple handling for the :numref:
105 # directive for Sphinx versions prior to 1.3.1. The functions replace the
106 # :numref: reference with a link to the target (for all Sphinx doc types).
107 # It doesn't try to label figures/tables.
108 def numref_role(reftype, rawtext, text, lineno, inliner):
110 Add a Sphinx role to handle numref references. Note, we can't convert
111 the link here because the doctree isn't build and the target information
114 # Add an identifier to distinguish numref from other references.
115 newnode = nodes.reference('',
117 refuri='_local_numref_#%s' % text,
122 def process_numref(app, doctree, from_docname):
124 Process the numref nodes once the doctree has been built and prior to
125 writing the files. The processing involves replacing the numref with a
126 link plus text to indicate if it is a Figure or Table link.
129 # Iterate over the reference nodes in the doctree.
130 for node in doctree.traverse(nodes.reference):
131 target = node.get('refuri', '')
133 # Look for numref nodes.
134 if target.startswith('_local_numref_#'):
135 target = target.replace('_local_numref_#', '')
137 # Get the target label and link information from the Sphinx env.
138 data = app.builder.env.domains['std'].data
139 docname, label, _ = data['labels'].get(target, ('', '', ''))
140 relative_url = app.builder.get_relative_uri(from_docname, docname)
142 # Add a text label to the link.
143 if target.startswith('figure'):
145 elif target.startswith('table'):
150 # New reference node with the updated link information.
151 newnode = nodes.reference('',
153 refuri='%s#%s' % (relative_url, label),
155 node.replace_self(newnode)
158 def generate_overview_table(output_filename, table_id, section, table_name, title):
160 Function to generate the Overview Table from the ini files that define
161 the features for each driver.
163 The default features for the table and their order is defined by the
167 # Default warning string.
168 warning = 'Warning generate_overview_table()'
170 # Get the default features and order from the 'default.ini' file.
171 ini_path = path_join(dirname(output_filename), 'features')
172 config = configparser.ConfigParser()
173 config.optionxform = str
174 config.read(path_join(ini_path, 'default.ini'))
175 default_features = config.items(section)
177 # Create a dict of the valid features to validate the other ini files.
179 max_feature_length = 0
180 for feature in default_features:
182 valid_features[key] = ' '
183 max_feature_length = max(max_feature_length, len(key))
185 # Get a list of driver ini files, excluding 'default.ini'.
186 ini_files = [basename(file) for file in listdir(ini_path)
187 if file.endswith('.ini') and file != 'default.ini']
190 # Build up a list of the table header names from the ini filenames.
192 for ini_filename in ini_files:
193 name = ini_filename[:-4]
194 name = name.replace('_vf', 'vf')
195 pmd_names.append(name)
197 # Pad the table header names.
198 max_header_len = len(max(pmd_names, key=len))
200 for name in pmd_names:
202 pmd, vec = name.split('_')
203 name = '{0:{fill}{align}{width}}vec'.format(pmd,
204 fill='.', align='<', width=max_header_len-3)
206 name = '{0:{fill}{align}{width}}'.format(name,
207 fill=' ', align='<', width=max_header_len)
208 header_names.append(name)
210 # Create a dict of the defined features for each driver from the ini files.
212 for ini_filename in ini_files:
213 config = configparser.ConfigParser()
214 config.optionxform = str
215 config.read(path_join(ini_path, ini_filename))
217 # Initialize the dict with the default.ini value.
218 ini_data[ini_filename] = valid_features.copy()
220 # Check for a valid ini section.
221 if not config.has_section(section):
222 print("{}: File '{}' has no [{}] secton".format(warning,
227 # Check for valid features names.
228 for name, value in config.items(section):
229 if name not in valid_features:
230 print("{}: Unknown feature '{}' in '{}'".format(warning,
236 # Get the first letter only.
237 ini_data[ini_filename][name] = value[0]
239 # Print out the RST Driver Overview table from the ini file data.
240 outfile = open(output_filename, 'w')
241 num_cols = len(header_names)
243 print_table_css(outfile, table_id)
244 print('.. table:: ' + table_name + '\n', file=outfile)
245 print_table_header(outfile, num_cols, header_names, title)
246 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
249 def print_table_header(outfile, num_cols, header_names, title):
250 """ Print the RST table header. The header names are vertical. """
251 print_table_divider(outfile, num_cols)
254 for name in header_names:
255 line += ' ' + name[0]
257 print_table_row(outfile, title, line)
259 for i in range(1, len(header_names[0])):
261 for name in header_names:
262 line += ' ' + name[i]
264 print_table_row(outfile, '', line)
266 print_table_divider(outfile, num_cols)
269 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
270 """ Print out the body of the table. Each row is a NIC feature. """
272 for feature, _ in default_features:
275 for ini_filename in ini_files:
276 line += ' ' + ini_data[ini_filename][feature]
278 print_table_row(outfile, feature, line)
280 print_table_divider(outfile, num_cols)
283 def print_table_row(outfile, feature, line):
284 """ Print a single row of the table with fixed formatting. """
286 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
289 def print_table_divider(outfile, num_cols):
290 """ Print the table divider line. """
292 column_dividers = ['='] * num_cols
293 line += ' '.join(column_dividers)
295 feature = '=' * feature_str_len
297 print_table_row(outfile, feature, line)
300 def print_table_css(outfile, table_id):
314 line-height: inherit;
316 table#idx th, table#idx td {
318 border: solid 1px #ddd;
323 table#idx th, table#idx th p {
325 white-space: pre-wrap;
329 table#idx col:first-child {
332 table#idx th:first-child {
333 vertical-align: bottom;
338 table#idx td, table#idx td p {
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',
407 table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
408 generate_overview_table(table_file, 1,
410 'Features availability in regex drivers',
412 table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
413 generate_overview_table(table_file, 1,
415 'Features availability in vDPA drivers',
417 table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
418 generate_overview_table(table_file, 1,
420 'Features availability in bbdev drivers',
423 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
424 print('Upgrade sphinx to version >= 1.3.1 for '
425 'improved Figure/Table number handling.')
426 # Add a role to handle :numref: references.
427 app.add_role('numref', numref_role)
428 # Process the numref references once the doctree has been created.
429 app.connect('doctree-resolved', process_numref)
432 # New function in sphinx 1.8
433 app.add_css_file('css/custom.css')
435 app.add_stylesheet('css/custom.css')