xref: /dpdk/doc/guides/conf.py (revision 2717246ecd7d27125a346a2c5c55b53a9c251a93)
1# SPDX-License-Identifier: BSD-3-Clause
2# Copyright(c) 2010-2015 Intel Corporation
3
4from __future__ import print_function
5import subprocess
6from docutils import nodes
7from distutils.version import LooseVersion
8from sphinx import __version__ as sphinx_version
9from sphinx.highlighting import PygmentsBridge
10from pygments.formatters.latex import LatexFormatter
11from os import listdir
12from os.path import basename
13from os.path import dirname
14from os.path import join as path_join
15
16try:
17    # Python 2.
18    import ConfigParser as configparser
19except:
20    # Python 3.
21    import configparser
22
23try:
24    import sphinx_rtd_theme
25
26    html_theme = "sphinx_rtd_theme"
27    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
28except:
29    print('Install the sphinx ReadTheDocs theme for improved html documentation '
30          'layout: pip install sphinx_rtd_theme')
31    pass
32
33project = 'Data Plane Development Kit'
34html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
35latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
36html_add_permalinks = ""
37html_show_copyright = False
38highlight_language = 'none'
39
40version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion'])
41version = version.decode('utf-8').rstrip()
42release = version
43
44master_doc = 'index'
45
46# Maximum feature description string length
47feature_str_len = 25
48
49# Figures, tables and code-blocks automatically numbered if they have caption
50numfig = True
51
52latex_documents = [
53    ('index',
54     'doc.tex',
55     '',
56     '',
57     'manual')
58]
59
60# Latex directives to be included directly in the latex/pdf docs.
61custom_latex_preamble = r"""
62\usepackage[utf8]{inputenc}
63\usepackage[T1]{fontenc}
64\usepackage{helvet}
65\renewcommand{\familydefault}{\sfdefault}
66\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
67"""
68
69# Configuration for the latex/pdf docs.
70latex_elements = {
71    'papersize': 'a4paper',
72    'pointsize': '11pt',
73    # remove blank pages
74    'classoptions': ',openany,oneside',
75    'babel': '\\usepackage[english]{babel}',
76    # customize Latex formatting
77    'preamble': custom_latex_preamble
78}
79
80
81# Override the default Latex formatter in order to modify the
82# code/verbatim blocks.
83class 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'
88
89# Replace the default latex formatter.
90PygmentsBridge.latex_formatter = CustomLatexFormatter
91
92# Configuration for man pages
93man_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)]
103
104
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.
110def numref_role(reftype, rawtext, text, lineno, inliner):
111    """
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
114    isn't available.
115    """
116    # Add an identifier to distinguish numref from other references.
117    newnode = nodes.reference('',
118                              '',
119                              refuri='_local_numref_#%s' % text,
120                              internal=True)
121    return [newnode], []
122
123
124def process_numref(app, doctree, from_docname):
125    """
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.
129    """
130
131    # Iterate over the reference nodes in the doctree.
132    for node in doctree.traverse(nodes.reference):
133        target = node.get('refuri', '')
134
135        # Look for numref nodes.
136        if target.startswith('_local_numref_#'):
137            target = target.replace('_local_numref_#', '')
138
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)
143
144            # Add a text label to the link.
145            if target.startswith('figure'):
146                caption = 'Figure'
147            elif target.startswith('table'):
148                caption = 'Table'
149            else:
150                caption = 'Link'
151
152            # New reference node with the updated link information.
153            newnode = nodes.reference('',
154                                      caption,
155                                      refuri='%s#%s' % (relative_url, label),
156                                      internal=True)
157            node.replace_self(newnode)
158
159
160def generate_overview_table(output_filename, table_id, section, table_name, title):
161    """
162    Function to generate the Overview Table from the ini files that define
163    the features for each driver.
164
165    The default features for the table and their order is defined by the
166    'default.ini' file.
167
168    """
169    # Default warning string.
170    warning = 'Warning generate_overview_table()'
171
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)
178
179    # Create a dict of the valid features to validate the other ini files.
180    valid_features = {}
181    max_feature_length = 0
182    for feature in default_features:
183        key = feature[0]
184        valid_features[key] = ' '
185        max_feature_length = max(max_feature_length, len(key))
186
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']
190    ini_files.sort()
191
192    # Build up a list of the table header names from the ini filenames.
193    pmd_names = []
194    for ini_filename in ini_files:
195        name = ini_filename[:-4]
196        name = name.replace('_vf', 'vf')
197        pmd_names.append(name)
198
199    # Pad the table header names.
200    max_header_len = len(max(pmd_names, key=len))
201    header_names = []
202    for name in pmd_names:
203        if '_vec' in name:
204            pmd, vec = name.split('_')
205            name = '{0:{fill}{align}{width}}vec'.format(pmd,
206                    fill='.', align='<', width=max_header_len-3)
207        else:
208            name = '{0:{fill}{align}{width}}'.format(name,
209                    fill=' ', align='<', width=max_header_len)
210        header_names.append(name)
211
212    # Create a dict of the defined features for each driver from the ini files.
213    ini_data = {}
214    for ini_filename in ini_files:
215        config = configparser.ConfigParser()
216        config.optionxform = str
217        config.read(path_join(ini_path, ini_filename))
218
219        # Initialize the dict with the default.ini value.
220        ini_data[ini_filename] = valid_features.copy()
221
222        # Check for a valid ini section.
223        if not config.has_section(section):
224            print("{}: File '{}' has no [{}] secton".format(warning,
225                                                            ini_filename,
226                                                            section))
227            continue
228
229        # Check for valid features names.
230        for name, value in config.items(section):
231            if name not in valid_features:
232                print("{}: Unknown feature '{}' in '{}'".format(warning,
233                                                                name,
234                                                                ini_filename))
235                continue
236
237            if value is not '':
238                # Get the first letter only.
239                ini_data[ini_filename][name] = value[0]
240
241    # Print out the RST Driver Overview table from the ini file data.
242    outfile = open(output_filename, 'w')
243    num_cols = len(header_names)
244
245    print_table_css(outfile, table_id)
246    print('.. table:: ' + table_name + '\n', file=outfile)
247    print_table_header(outfile, num_cols, header_names, title)
248    print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
249
250
251def print_table_header(outfile, num_cols, header_names, title):
252    """ Print the RST table header. The header names are vertical. """
253    print_table_divider(outfile, num_cols)
254
255    line = ''
256    for name in header_names:
257        line += ' ' + name[0]
258
259    print_table_row(outfile, title, line)
260
261    for i in range(1, len(header_names[0])):
262        line = ''
263        for name in header_names:
264            line += ' ' + name[i]
265
266        print_table_row(outfile, '', line)
267
268    print_table_divider(outfile, num_cols)
269
270
271def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
272    """ Print out the body of the table. Each row is a NIC feature. """
273
274    for feature, _ in default_features:
275        line = ''
276
277        for ini_filename in ini_files:
278            line += ' ' + ini_data[ini_filename][feature]
279
280        print_table_row(outfile, feature, line)
281
282    print_table_divider(outfile, num_cols)
283
284
285def print_table_row(outfile, feature, line):
286    """ Print a single row of the table with fixed formatting. """
287    line = line.rstrip()
288    print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
289
290
291def print_table_divider(outfile, num_cols):
292    """ Print the table divider line. """
293    line = ' '
294    column_dividers = ['='] * num_cols
295    line += ' '.join(column_dividers)
296
297    feature = '=' * feature_str_len
298
299    print_table_row(outfile, feature, line)
300
301
302def print_table_css(outfile, table_id):
303    template = """
304.. raw:: html
305
306   <style>
307      .wy-nav-content {
308         opacity: .99;
309      }
310      table#idx {
311         cursor: default;
312         overflow: hidden;
313      }
314      table#idx th, table#idx td {
315         text-align: center;
316      }
317      table#idx th {
318         font-size: 72%;
319         white-space: pre-wrap;
320         vertical-align: top;
321         padding: 0.5em 0;
322         min-width: 0.9em;
323         width: 2em;
324      }
325      table#idx col:first-child {
326         width: 0;
327      }
328      table#idx th:first-child {
329         vertical-align: bottom;
330      }
331      table#idx td {
332         font-size: 70%;
333         padding: 1px;
334      }
335      table#idx td:first-child {
336         padding-left: 1em;
337         text-align: left;
338      }
339      table#idx tr:nth-child(2n-1) td {
340         background-color: rgba(210, 210, 210, 0.2);
341      }
342      table#idx th:not(:first-child):hover,
343      table#idx td:not(:first-child):hover {
344         position: relative;
345      }
346      table#idx th:not(:first-child):hover::after,
347      table#idx td:not(:first-child):hover::after {
348         content: '';
349         height: 6000px;
350         top: -3000px;
351         width: 100%;
352         left: 0;
353         position: absolute;
354         z-index: -1;
355         background-color: #ffb;
356      }
357      table#idx tr:hover td {
358         background-color: #ffb;
359      }
360   </style>
361"""
362    print(template.replace("idx", "id%d" % (table_id)), file=outfile)
363
364
365def setup(app):
366    table_file = dirname(__file__) + '/nics/overview_table.txt'
367    generate_overview_table(table_file, 1,
368                            'Features',
369                            'Features availability in networking drivers',
370                            'Feature')
371    table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
372    generate_overview_table(table_file, 1,
373                            'Features',
374                            'Features availability in crypto drivers',
375                            'Feature')
376    table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
377    generate_overview_table(table_file, 2,
378                            'Cipher',
379                            'Cipher algorithms in crypto drivers',
380                            'Cipher algorithm')
381    table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
382    generate_overview_table(table_file, 3,
383                            'Auth',
384                            'Authentication algorithms in crypto drivers',
385                            'Authentication algorithm')
386    table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
387    generate_overview_table(table_file, 4,
388                            'AEAD',
389                            'AEAD algorithms in crypto drivers',
390                            'AEAD algorithm')
391    table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
392    generate_overview_table(table_file, 1,
393                            'Features',
394                            'Features availability in compression drivers',
395                            'Feature')
396
397    if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
398        print('Upgrade sphinx to version >= 1.3.1 for '
399              'improved Figure/Table number handling.')
400        # Add a role to handle :numref: references.
401        app.add_role('numref', numref_role)
402        # Process the numref references once the doctree has been created.
403        app.connect('doctree-resolved', process_numref)
404
405    app.add_stylesheet('css/custom.css')
406