xref: /dpdk/doc/guides/conf.py (revision d429cc0b53735cc7b1e304ec1d0f35ae06ace7d0)
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    header_names = []
194    for ini_filename in ini_files:
195        name = ini_filename[:-4]
196        name = name.replace('_vf', 'vf')
197
198        # Pad the table header names to match the existing format.
199        if '_vec' in name:
200            pmd, vec = name.split('_')
201            name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
202        else:
203            name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
204
205        header_names.append(name)
206
207    # Create a dict of the defined features for each driver from the ini files.
208    ini_data = {}
209    for ini_filename in ini_files:
210        config = configparser.ConfigParser()
211        config.optionxform = str
212        config.read(path_join(ini_path, ini_filename))
213
214        # Initialize the dict with the default.ini value.
215        ini_data[ini_filename] = valid_features.copy()
216
217        # Check for a valid ini section.
218        if not config.has_section(section):
219            print("{}: File '{}' has no [{}] secton".format(warning,
220                                                            ini_filename,
221                                                            section))
222            continue
223
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,
228                                                                name,
229                                                                ini_filename))
230                continue
231
232            if value is not '':
233                # Get the first letter only.
234                ini_data[ini_filename][name] = value[0]
235
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)
239
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)
244
245
246def 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)
249
250    line = ''
251    for name in header_names:
252        line += ' ' + name[0]
253
254    print_table_row(outfile, title, line)
255
256    for i in range(1, 10):
257        line = ''
258        for name in header_names:
259            line += ' ' + name[i]
260
261        print_table_row(outfile, '', line)
262
263    print_table_divider(outfile, num_cols)
264
265
266def 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. """
268
269    for feature, _ in default_features:
270        line = ''
271
272        for ini_filename in ini_files:
273            line += ' ' + ini_data[ini_filename][feature]
274
275        print_table_row(outfile, feature, line)
276
277    print_table_divider(outfile, num_cols)
278
279
280def print_table_row(outfile, feature, line):
281    """ Print a single row of the table with fixed formatting. """
282    line = line.rstrip()
283    print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
284
285
286def print_table_divider(outfile, num_cols):
287    """ Print the table divider line. """
288    line = ' '
289    column_dividers = ['='] * num_cols
290    line += ' '.join(column_dividers)
291
292    feature = '=' * feature_str_len
293
294    print_table_row(outfile, feature, line)
295
296
297def print_table_css(outfile, table_id):
298    template = """
299.. raw:: html
300
301   <style>
302      .wy-nav-content {
303         opacity: .99;
304      }
305      table#idx {
306         cursor: default;
307         overflow: hidden;
308      }
309      table#idx th, table#idx td {
310         text-align: center;
311      }
312      table#idx th {
313         font-size: 80%;
314         white-space: pre-wrap;
315         vertical-align: top;
316         padding: 0.5em 0;
317         min-width: 0.9em;
318         width: 2em;
319      }
320      table#idx col:first-child {
321         width: 0;
322      }
323      table#idx th:first-child {
324         vertical-align: bottom;
325      }
326      table#idx td {
327         font-size: 70%;
328         padding: 1px;
329      }
330      table#idx td:first-child {
331         padding-left: 1em;
332         text-align: left;
333      }
334      table#idx tr:nth-child(2n-1) td {
335         background-color: rgba(210, 210, 210, 0.2);
336      }
337      table#idx th:not(:first-child):hover,
338      table#idx td:not(:first-child):hover {
339         position: relative;
340      }
341      table#idx th:not(:first-child):hover::after,
342      table#idx td:not(:first-child):hover::after {
343         content: '';
344         height: 6000px;
345         top: -3000px;
346         width: 100%;
347         left: 0;
348         position: absolute;
349         z-index: -1;
350         background-color: #ffb;
351      }
352      table#idx tr:hover td {
353         background-color: #ffb;
354      }
355   </style>
356"""
357    print(template.replace("idx", "id%d" % (table_id)), file=outfile)
358
359
360def setup(app):
361    table_file = dirname(__file__) + '/nics/overview_table.txt'
362    generate_overview_table(table_file, 1,
363                            'Features',
364                            'Features availability in networking drivers',
365                            'Feature')
366    table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
367    generate_overview_table(table_file, 1,
368                            'Features',
369                            'Features availability in crypto drivers',
370                            'Feature')
371    table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
372    generate_overview_table(table_file, 2,
373                            'Cipher',
374                            'Cipher algorithms in crypto drivers',
375                            'Cipher algorithm')
376    table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
377    generate_overview_table(table_file, 3,
378                            'Auth',
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,
383                            'AEAD',
384                            'AEAD algorithms in crypto drivers',
385                            'AEAD algorithm')
386
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)
394
395    app.add_stylesheet('css/custom.css')
396