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.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 version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion'])
41 version = version.decode('utf-8').rstrip()
46 # Maximum feature description string length
49 # Figures, tables and code-blocks automatically numbered if they have caption
60 # Latex directives to be included directly in the latex/pdf docs.
61 custom_latex_preamble = r"""
62 \usepackage[utf8]{inputenc}
63 \usepackage[T1]{fontenc}
65 \renewcommand{\familydefault}{\sfdefault}
66 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
69 # Configuration for the latex/pdf docs.
71 'papersize': 'a4paper',
74 'classoptions': ',openany,oneside',
75 'babel': '\\usepackage[english]{babel}',
76 # customize Latex formatting
77 'preamble': custom_latex_preamble
81 # Override the default Latex formatter in order to modify the
82 # code/verbatim blocks.
83 class CustomLatexFormatter(LatexFormatter):
84 def __init__(self, **options):
85 super(CustomLatexFormatter, self).__init__(**options)
86 # Use the second smallest font size for code/verbatim blocks.
87 self.verboptions = r'formatcom=\footnotesize'
89 # Replace the default latex formatter.
90 PygmentsBridge.latex_formatter = CustomLatexFormatter
92 # Configuration for man pages
93 man_pages = [("testpmd_app_ug/run_app", "testpmd",
94 "tests for dpdk pmds", "", 1),
95 ("tools/pdump", "dpdk-pdump",
96 "enable packet capture on dpdk ports", "", 1),
97 ("tools/proc_info", "dpdk-procinfo",
98 "access dpdk port stats and memory info", "", 1),
99 ("tools/pmdinfo", "dpdk-pmdinfo",
100 "dump a PMDs hardware support info", "", 1),
101 ("tools/devbind", "dpdk-devbind",
102 "check device status and bind/unbind them from drivers", "", 8)]
105 # ####### :numref: fallback ########
106 # The following hook functions add some simple handling for the :numref:
107 # directive for Sphinx versions prior to 1.3.1. The functions replace the
108 # :numref: reference with a link to the target (for all Sphinx doc types).
109 # It doesn't try to label figures/tables.
110 def numref_role(reftype, rawtext, text, lineno, inliner):
112 Add a Sphinx role to handle numref references. Note, we can't convert
113 the link here because the doctree isn't build and the target information
116 # Add an identifier to distinguish numref from other references.
117 newnode = nodes.reference('',
119 refuri='_local_numref_#%s' % text,
124 def process_numref(app, doctree, from_docname):
126 Process the numref nodes once the doctree has been built and prior to
127 writing the files. The processing involves replacing the numref with a
128 link plus text to indicate if it is a Figure or Table link.
131 # Iterate over the reference nodes in the doctree.
132 for node in doctree.traverse(nodes.reference):
133 target = node.get('refuri', '')
135 # Look for numref nodes.
136 if target.startswith('_local_numref_#'):
137 target = target.replace('_local_numref_#', '')
139 # Get the target label and link information from the Sphinx env.
140 data = app.builder.env.domains['std'].data
141 docname, label, _ = data['labels'].get(target, ('', '', ''))
142 relative_url = app.builder.get_relative_uri(from_docname, docname)
144 # Add a text label to the link.
145 if target.startswith('figure'):
147 elif target.startswith('table'):
152 # New reference node with the updated link information.
153 newnode = nodes.reference('',
155 refuri='%s#%s' % (relative_url, label),
157 node.replace_self(newnode)
160 def generate_overview_table(output_filename, table_id, section, table_name, title):
162 Function to generate the Overview Table from the ini files that define
163 the features for each driver.
165 The default features for the table and their order is defined by the
169 # Default warning string.
170 warning = 'Warning generate_overview_table()'
172 # Get the default features and order from the 'default.ini' file.
173 ini_path = path_join(dirname(output_filename), 'features')
174 config = configparser.ConfigParser()
175 config.optionxform = str
176 config.read(path_join(ini_path, 'default.ini'))
177 default_features = config.items(section)
179 # Create a dict of the valid features to validate the other ini files.
181 max_feature_length = 0
182 for feature in default_features:
184 valid_features[key] = ' '
185 max_feature_length = max(max_feature_length, len(key))
187 # Get a list of driver ini files, excluding 'default.ini'.
188 ini_files = [basename(file) for file in listdir(ini_path)
189 if file.endswith('.ini') and file != 'default.ini']
192 # Build up a list of the table header names from the ini filenames.
194 for ini_filename in ini_files:
195 name = ini_filename[:-4]
196 name = name.replace('_vf', 'vf')
198 # Pad the table header names to match the existing format.
200 pmd, vec = name.split('_')
201 name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
203 name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
205 header_names.append(name)
207 # Create a dict of the defined features for each driver from the ini files.
209 for ini_filename in ini_files:
210 config = configparser.ConfigParser()
211 config.optionxform = str
212 config.read(path_join(ini_path, ini_filename))
214 # Initialize the dict with the default.ini value.
215 ini_data[ini_filename] = valid_features.copy()
217 # Check for a valid ini section.
218 if not config.has_section(section):
219 print("{}: File '{}' has no [{}] secton".format(warning,
224 # Check for valid features names.
225 for name, value in config.items(section):
226 if name not in valid_features:
227 print("{}: Unknown feature '{}' in '{}'".format(warning,
233 # Get the first letter only.
234 ini_data[ini_filename][name] = value[0]
236 # Print out the RST Driver Overview table from the ini file data.
237 outfile = open(output_filename, 'w')
238 num_cols = len(header_names)
240 print_table_css(outfile, table_id)
241 print('.. table:: ' + table_name + '\n', file=outfile)
242 print_table_header(outfile, num_cols, header_names, title)
243 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
246 def print_table_header(outfile, num_cols, header_names, title):
247 """ Print the RST table header. The header names are vertical. """
248 print_table_divider(outfile, num_cols)
251 for name in header_names:
252 line += ' ' + name[0]
254 print_table_row(outfile, title, line)
256 for i in range(1, 10):
258 for name in header_names:
259 line += ' ' + name[i]
261 print_table_row(outfile, '', line)
263 print_table_divider(outfile, num_cols)
266 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
267 """ Print out the body of the table. Each row is a NIC feature. """
269 for feature, _ in default_features:
272 for ini_filename in ini_files:
273 line += ' ' + ini_data[ini_filename][feature]
275 print_table_row(outfile, feature, line)
277 print_table_divider(outfile, num_cols)
280 def print_table_row(outfile, feature, line):
281 """ Print a single row of the table with fixed formatting. """
283 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
286 def print_table_divider(outfile, num_cols):
287 """ Print the table divider line. """
289 column_dividers = ['='] * num_cols
290 line += ' '.join(column_dividers)
292 feature = '=' * feature_str_len
294 print_table_row(outfile, feature, line)
297 def print_table_css(outfile, table_id):
309 table#idx th, table#idx td {
314 white-space: pre-wrap;
320 table#idx col:first-child {
323 table#idx th:first-child {
324 vertical-align: bottom;
330 table#idx td:first-child {
334 table#idx tr:nth-child(2n-1) td {
335 background-color: rgba(210, 210, 210, 0.2);
337 table#idx th:not(:first-child):hover,
338 table#idx td:not(:first-child):hover {
341 table#idx th:not(:first-child):hover::after,
342 table#idx td:not(:first-child):hover::after {
350 background-color: #ffb;
352 table#idx tr:hover td {
353 background-color: #ffb;
357 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
361 table_file = dirname(__file__) + '/nics/overview_table.txt'
362 generate_overview_table(table_file, 1,
364 'Features availability in networking drivers',
366 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
367 generate_overview_table(table_file, 1,
369 'Features availability in crypto drivers',
371 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
372 generate_overview_table(table_file, 2,
374 'Cipher algorithms in crypto drivers',
376 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
377 generate_overview_table(table_file, 3,
379 'Authentication algorithms in crypto drivers',
380 'Authentication algorithm')
381 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
382 generate_overview_table(table_file, 4,
384 'AEAD algorithms in crypto drivers',
387 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
388 print('Upgrade sphinx to version >= 1.3.1 for '
389 'improved Figure/Table number handling.')
390 # Add a role to handle :numref: references.
391 app.add_role('numref', numref_role)
392 # Process the numref references once the doctree has been created.
393 app.connect('doctree-resolved', process_numref)