2 # Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in
13 # the documentation and/or other materials provided with the
15 # * Neither the name of Intel Corporation nor the names of its
16 # contributors may be used to endorse or promote products derived
17 # from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 from __future__ import print_function
33 from docutils import nodes
34 from distutils.version import LooseVersion
35 from sphinx import __version__ as sphinx_version
36 from sphinx.highlighting import PygmentsBridge
37 from pygments.formatters.latex import LatexFormatter
38 from os import listdir
39 from os.path import basename
40 from os.path import dirname
41 from os.path import join as path_join
45 import ConfigParser as configparser
51 project = 'Data Plane Development Kit'
53 if LooseVersion(sphinx_version) >= LooseVersion('1.3.1'):
54 html_theme = "sphinx_rtd_theme"
55 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
56 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
57 html_add_permalinks = ""
58 html_show_copyright = False
59 highlight_language = 'none'
61 version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion'])
62 version = version.decode('utf-8').rstrip()
67 # Maximum feature description string length
70 # Figures, tables and code-blocks automatically numbered if they have caption
81 # Latex directives to be included directly in the latex/pdf docs.
82 custom_latex_preamble = r"""
83 \usepackage[utf8]{inputenc}
84 \usepackage[T1]{fontenc}
86 \renewcommand{\familydefault}{\sfdefault}
87 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
90 # Configuration for the latex/pdf docs.
92 'papersize': 'a4paper',
95 'classoptions': ',openany,oneside',
96 'babel': '\\usepackage[english]{babel}',
97 # customize Latex formatting
98 'preamble': custom_latex_preamble
102 # Override the default Latex formatter in order to modify the
103 # code/verbatim blocks.
104 class CustomLatexFormatter(LatexFormatter):
105 def __init__(self, **options):
106 super(CustomLatexFormatter, self).__init__(**options)
107 # Use the second smallest font size for code/verbatim blocks.
108 self.verboptions = r'formatcom=\footnotesize'
110 # Replace the default latex formatter.
111 PygmentsBridge.latex_formatter = CustomLatexFormatter
113 # Configuration for man pages
114 man_pages = [("testpmd_app_ug/run_app", "testpmd",
115 "tests for dpdk pmds", "", 1),
116 ("tools/pdump", "dpdk-pdump",
117 "enable packet capture on dpdk ports", "", 1),
118 ("tools/proc_info", "dpdk-procinfo",
119 "access dpdk port stats and memory info", "", 1),
120 ("tools/pmdinfo", "dpdk-pmdinfo",
121 "dump a PMDs hardware support info", "", 1),
122 ("tools/devbind", "dpdk-devbind",
123 "check device status and bind/unbind them from drivers", "", 8)]
126 # ####### :numref: fallback ########
127 # The following hook functions add some simple handling for the :numref:
128 # directive for Sphinx versions prior to 1.3.1. The functions replace the
129 # :numref: reference with a link to the target (for all Sphinx doc types).
130 # It doesn't try to label figures/tables.
131 def numref_role(reftype, rawtext, text, lineno, inliner):
133 Add a Sphinx role to handle numref references. Note, we can't convert
134 the link here because the doctree isn't build and the target information
137 # Add an identifier to distinguish numref from other references.
138 newnode = nodes.reference('',
140 refuri='_local_numref_#%s' % text,
145 def process_numref(app, doctree, from_docname):
147 Process the numref nodes once the doctree has been built and prior to
148 writing the files. The processing involves replacing the numref with a
149 link plus text to indicate if it is a Figure or Table link.
152 # Iterate over the reference nodes in the doctree.
153 for node in doctree.traverse(nodes.reference):
154 target = node.get('refuri', '')
156 # Look for numref nodes.
157 if target.startswith('_local_numref_#'):
158 target = target.replace('_local_numref_#', '')
160 # Get the target label and link information from the Sphinx env.
161 data = app.builder.env.domains['std'].data
162 docname, label, _ = data['labels'].get(target, ('', '', ''))
163 relative_url = app.builder.get_relative_uri(from_docname, docname)
165 # Add a text label to the link.
166 if target.startswith('figure'):
168 elif target.startswith('table'):
173 # New reference node with the updated link information.
174 newnode = nodes.reference('',
176 refuri='%s#%s' % (relative_url, label),
178 node.replace_self(newnode)
181 def generate_overview_table(output_filename, table_id, section, table_name, title):
183 Function to generate the Overview Table from the ini files that define
184 the features for each driver.
186 The default features for the table and their order is defined by the
190 # Default warning string.
191 warning = 'Warning generate_overview_table()'
193 # Get the default features and order from the 'default.ini' file.
194 ini_path = path_join(dirname(output_filename), 'features')
195 config = configparser.ConfigParser()
196 config.optionxform = str
197 config.read(path_join(ini_path, 'default.ini'))
198 default_features = config.items(section)
200 # Create a dict of the valid features to validate the other ini files.
202 max_feature_length = 0
203 for feature in default_features:
205 valid_features[key] = ' '
206 max_feature_length = max(max_feature_length, len(key))
208 # Get a list of driver ini files, excluding 'default.ini'.
209 ini_files = [basename(file) for file in listdir(ini_path)
210 if file.endswith('.ini') and file != 'default.ini']
213 # Build up a list of the table header names from the ini filenames.
215 for ini_filename in ini_files:
216 name = ini_filename[:-4]
217 name = name.replace('_vf', 'vf')
219 # Pad the table header names to match the existing format.
221 pmd, vec = name.split('_')
222 name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
224 name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
226 header_names.append(name)
228 # Create a dict of the defined features for each driver from the ini files.
230 for ini_filename in ini_files:
231 config = configparser.ConfigParser()
232 config.optionxform = str
233 config.read(path_join(ini_path, ini_filename))
235 # Initialize the dict with the default.ini value.
236 ini_data[ini_filename] = valid_features.copy()
238 # Check for a valid ini section.
239 if not config.has_section(section):
240 print("{}: File '{}' has no [{}] secton".format(warning,
245 # Check for valid features names.
246 for name, value in config.items(section):
247 if name not in valid_features:
248 print("{}: Unknown feature '{}' in '{}'".format(warning,
254 # Get the first letter only.
255 ini_data[ini_filename][name] = value[0]
257 # Print out the RST Driver Overview table from the ini file data.
258 outfile = open(output_filename, 'w')
259 num_cols = len(header_names)
261 print_table_css(outfile, table_id)
262 print('.. table:: ' + table_name + '\n', file=outfile)
263 print_table_header(outfile, num_cols, header_names, title)
264 print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
267 def print_table_header(outfile, num_cols, header_names, title):
268 """ Print the RST table header. The header names are vertical. """
269 print_table_divider(outfile, num_cols)
272 for name in header_names:
273 line += ' ' + name[0]
275 print_table_row(outfile, title, line)
277 for i in range(1, 10):
279 for name in header_names:
280 line += ' ' + name[i]
282 print_table_row(outfile, '', line)
284 print_table_divider(outfile, num_cols)
287 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
288 """ Print out the body of the table. Each row is a NIC feature. """
290 for feature, _ in default_features:
293 for ini_filename in ini_files:
294 line += ' ' + ini_data[ini_filename][feature]
296 print_table_row(outfile, feature, line)
298 print_table_divider(outfile, num_cols)
301 def print_table_row(outfile, feature, line):
302 """ Print a single row of the table with fixed formatting. """
304 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
307 def print_table_divider(outfile, num_cols):
308 """ Print the table divider line. """
310 column_dividers = ['='] * num_cols
311 line += ' '.join(column_dividers)
313 feature = '=' * feature_str_len
315 print_table_row(outfile, feature, line)
318 def print_table_css(outfile, table_id):
330 table#idx th, table#idx td {
335 white-space: pre-wrap;
339 table#idx th:first-child {
340 vertical-align: bottom;
346 table#idx td:first-child {
350 table#idx tr:nth-child(2n-1) td {
351 background-color: rgba(210, 210, 210, 0.2);
353 table#idx th:not(:first-child):hover,
354 table#idx td:not(:first-child):hover {
357 table#idx th:not(:first-child):hover::after,
358 table#idx td:not(:first-child):hover::after {
366 background-color: #ffb;
368 table#idx tr:hover td {
369 background-color: #ffb;
373 print(template.replace("idx", "id%d" % (table_id)), file=outfile)
377 table_file = dirname(__file__) + '/nics/overview_table.txt'
378 generate_overview_table(table_file, 1,
380 'Features availability in networking drivers',
382 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
383 generate_overview_table(table_file, 1,
385 'Features availability in crypto drivers',
387 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
388 generate_overview_table(table_file, 2,
390 'Cipher algorithms in crypto drivers',
392 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
393 generate_overview_table(table_file, 3,
395 'Authentication algorithms in crypto drivers',
396 'Authentication algorithm')
397 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
398 generate_overview_table(table_file, 4,
400 'AEAD algorithms in crypto drivers',
403 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
404 print('Upgrade sphinx to version >= 1.3.1 for '
405 'improved Figure/Table number handling.')
406 # Add a role to handle :numref: references.
407 app.add_role('numref', numref_role)
408 # Process the numref references once the doctree has been created.
409 app.connect('doctree-resolved', process_numref)