xref: /dpdk/doc/guides/conf.py (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2010-2015 Intel Corporation
4
5from docutils import nodes
6from distutils.version import LooseVersion
7from sphinx import __version__ as sphinx_version
8from os import listdir
9from os import environ
10from os.path import basename
11from os.path import dirname
12from os.path import join as path_join
13from sys import argv, stderr
14
15import configparser
16
17try:
18    import sphinx_rtd_theme
19
20    html_theme = "sphinx_rtd_theme"
21except:
22    print('Install the sphinx ReadTheDocs theme for improved html documentation '
23          'layout: https://sphinx-rtd-theme.readthedocs.io/',
24          file=stderr)
25    pass
26
27stop_on_error = ('-W' in argv)
28
29project = 'Data Plane Development Kit'
30html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
31if LooseVersion(sphinx_version) >= LooseVersion('3.5'):
32    html_permalinks = False
33else:
34    html_add_permalinks = ""
35html_show_copyright = False
36highlight_language = 'none'
37
38release = environ.setdefault('DPDK_VERSION', "None")
39version = release
40
41master_doc = 'index'
42
43# Maximum feature description string length
44feature_str_len = 30
45
46# Figures, tables and code-blocks automatically numbered if they have caption
47numfig = True
48
49# Configuration for man pages
50man_pages = [("testpmd_app_ug/run_app", "testpmd",
51              "tests for dpdk pmds", "", 1),
52             ("tools/pdump", "dpdk-pdump",
53              "enable packet capture on dpdk ports", "", 1),
54             ("tools/proc_info", "dpdk-procinfo",
55              "access dpdk port stats and memory info", "", 1),
56             ("tools/pmdinfo", "dpdk-pmdinfo",
57              "dump a PMDs hardware support info", "", 1),
58             ("tools/devbind", "dpdk-devbind",
59              "check device status and bind/unbind them from drivers", "", 8)]
60
61
62# ####### :numref: fallback ########
63# The following hook functions add some simple handling for the :numref:
64# directive for Sphinx versions prior to 1.3.1. The functions replace the
65# :numref: reference with a link to the target (for all Sphinx doc types).
66# It doesn't try to label figures/tables.
67def numref_role(reftype, rawtext, text, lineno, inliner):
68    """
69    Add a Sphinx role to handle numref references. Note, we can't convert
70    the link here because the doctree isn't build and the target information
71    isn't available.
72    """
73    # Add an identifier to distinguish numref from other references.
74    newnode = nodes.reference('',
75                              '',
76                              refuri='_local_numref_#%s' % text,
77                              internal=True)
78    return [newnode], []
79
80
81def process_numref(app, doctree, from_docname):
82    """
83    Process the numref nodes once the doctree has been built and prior to
84    writing the files. The processing involves replacing the numref with a
85    link plus text to indicate if it is a Figure or Table link.
86    """
87
88    # Iterate over the reference nodes in the doctree.
89    for node in doctree.traverse(nodes.reference):
90        target = node.get('refuri', '')
91
92        # Look for numref nodes.
93        if target.startswith('_local_numref_#'):
94            target = target.replace('_local_numref_#', '')
95
96            # Get the target label and link information from the Sphinx env.
97            data = app.builder.env.domains['std'].data
98            docname, label, _ = data['labels'].get(target, ('', '', ''))
99            relative_url = app.builder.get_relative_uri(from_docname, docname)
100
101            # Add a text label to the link.
102            if target.startswith('figure'):
103                caption = 'Figure'
104            elif target.startswith('table'):
105                caption = 'Table'
106            else:
107                caption = 'Link'
108
109            # New reference node with the updated link information.
110            newnode = nodes.reference('',
111                                      caption,
112                                      refuri='%s#%s' % (relative_url, label),
113                                      internal=True)
114            node.replace_self(newnode)
115
116
117def generate_overview_table(output_filename, table_id, section, table_name, title):
118    """
119    Function to generate the Overview Table from the ini files that define
120    the features for each driver.
121
122    The default features for the table and their order is defined by the
123    'default.ini' file.
124
125    """
126    # Default warning string.
127    warning = 'Warning generate_overview_table()'
128
129    # Get the default features and order from the 'default.ini' file.
130    ini_path = path_join(dirname(output_filename), 'features')
131    config = configparser.ConfigParser()
132    config.optionxform = str
133    config.read(path_join(ini_path, 'default.ini'))
134    default_features = config.items(section)
135
136    # Create a dict of the valid features to validate the other ini files.
137    valid_features = {}
138    max_feature_length = 0
139    for feature in default_features:
140        key = feature[0]
141        valid_features[key] = ' '
142        max_feature_length = max(max_feature_length, len(key))
143
144    # Get a list of driver ini files, excluding 'default.ini'.
145    ini_files = [basename(file) for file in listdir(ini_path)
146                 if file.endswith('.ini') and file != 'default.ini']
147    ini_files.sort()
148
149    # Build up a list of the table header names from the ini filenames.
150    pmd_names = []
151    for ini_filename in ini_files:
152        name = ini_filename[:-4]
153        name = name.replace('_vf', 'vf')
154        pmd_names.append(name)
155
156    # Pad the table header names.
157    max_header_len = len(max(pmd_names, key=len))
158    header_names = []
159    for name in pmd_names:
160        if '_vec' in name:
161            pmd, vec = name.split('_')
162            name = '{0:{fill}{align}{width}}vec'.format(pmd,
163                    fill='.', align='<', width=max_header_len-3)
164        else:
165            name = '{0:{fill}{align}{width}}'.format(name,
166                    fill=' ', align='<', width=max_header_len)
167        header_names.append(name)
168
169    # Create a dict of the defined features for each driver from the ini files.
170    ini_data = {}
171    for ini_filename in ini_files:
172        config = configparser.ConfigParser()
173        config.optionxform = str
174        config.read(path_join(ini_path, ini_filename))
175
176        # Initialize the dict with the default.ini value.
177        ini_data[ini_filename] = valid_features.copy()
178
179        # Check for a section.
180        if not config.has_section(section):
181            continue
182
183        # Check for valid features names.
184        for name, value in config.items(section):
185            if name not in valid_features:
186                print("{}: Unknown feature '{}' in '{}'".format(warning,
187                                                                name,
188                                                                ini_filename),
189                                                                file=stderr)
190                if stop_on_error:
191                    raise Exception('Warning is treated as a failure')
192                continue
193
194            if value:
195                # Get the first letter only.
196                ini_data[ini_filename][name] = value[0]
197
198    # Print out the RST Driver Overview table from the ini file data.
199    outfile = open(output_filename, 'w')
200    num_cols = len(header_names)
201
202    print_table_css(outfile, table_id)
203    print('.. table:: ' + table_name + '\n', file=outfile)
204    print_table_header(outfile, num_cols, header_names, title)
205    print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
206
207
208def print_table_header(outfile, num_cols, header_names, title):
209    """ Print the RST table header. The header names are vertical. """
210    print_table_divider(outfile, num_cols)
211
212    line = ''
213    for name in header_names:
214        line += ' ' + name[0]
215
216    print_table_row(outfile, title, line)
217
218    for i in range(1, len(header_names[0])):
219        line = ''
220        for name in header_names:
221            line += ' ' + name[i]
222
223        print_table_row(outfile, '', line)
224
225    print_table_divider(outfile, num_cols)
226
227
228def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
229    """ Print out the body of the table. Each row is a NIC feature. """
230
231    for feature, _ in default_features:
232        line = ''
233
234        for ini_filename in ini_files:
235            line += ' ' + ini_data[ini_filename][feature]
236
237        print_table_row(outfile, feature, line)
238
239    print_table_divider(outfile, num_cols)
240
241
242def print_table_row(outfile, feature, line):
243    """ Print a single row of the table with fixed formatting. """
244    line = line.rstrip()
245    print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
246
247
248def print_table_divider(outfile, num_cols):
249    """ Print the table divider line. """
250    line = ' '
251    column_dividers = ['='] * num_cols
252    line += ' '.join(column_dividers)
253
254    feature = '=' * feature_str_len
255
256    print_table_row(outfile, feature, line)
257
258
259def print_table_css(outfile, table_id):
260    template = """
261.. raw:: html
262
263   <style>
264      .wy-nav-content {
265         opacity: .99;
266      }
267      table#idx {
268         cursor: default;
269         overflow: hidden;
270      }
271      table#idx p {
272         margin: 0;
273         line-height: inherit;
274      }
275      table#idx th, table#idx td {
276         text-align: center;
277         border: solid 1px #ddd;
278      }
279      table#idx th {
280         padding: 0.5em 0;
281      }
282      table#idx th, table#idx th p {
283         font-size: 11px;
284         white-space: pre-wrap;
285         vertical-align: top;
286         min-width: 0.9em;
287      }
288      table#idx col:first-child {
289         width: 0;
290      }
291      table#idx th:first-child {
292         vertical-align: bottom;
293      }
294      table#idx td {
295         padding: 1px;
296      }
297      table#idx td, table#idx td p {
298         font-size: 11px;
299      }
300      table#idx td:first-child {
301         padding-left: 1em;
302         text-align: left;
303      }
304      table#idx tr:nth-child(2n-1) td {
305         background-color: rgba(210, 210, 210, 0.2);
306      }
307      table#idx th:not(:first-child):hover,
308      table#idx td:not(:first-child):hover {
309         position: relative;
310      }
311      table#idx th:not(:first-child):hover::after,
312      table#idx td:not(:first-child):hover::after {
313         content: '';
314         height: 6000px;
315         top: -3000px;
316         width: 100%;
317         left: 0;
318         position: absolute;
319         z-index: -1;
320         background-color: #ffb;
321      }
322      table#idx tr:hover td {
323         background-color: #ffb;
324      }
325   </style>
326"""
327    print(template.replace("idx", "id%d" % (table_id)), file=outfile)
328
329
330def setup(app):
331    table_file = dirname(__file__) + '/nics/overview_table.txt'
332    generate_overview_table(table_file, 1,
333                            'Features',
334                            'Features availability in networking drivers',
335                            'Feature')
336    table_file = dirname(__file__) + '/nics/rte_flow_items_table.txt'
337    generate_overview_table(table_file, 2,
338                            'rte_flow items',
339                            'rte_flow items availability in networking drivers',
340                            'Item')
341    table_file = dirname(__file__) + '/nics/rte_flow_actions_table.txt'
342    generate_overview_table(table_file, 3,
343                            'rte_flow actions',
344                            'rte_flow actions availability in networking drivers',
345                            'Action')
346    table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
347    generate_overview_table(table_file, 1,
348                            'Features',
349                            'Features availability in crypto drivers',
350                            'Feature')
351    table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
352    generate_overview_table(table_file, 2,
353                            'Cipher',
354                            'Cipher algorithms in crypto drivers',
355                            'Cipher algorithm')
356    table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
357    generate_overview_table(table_file, 3,
358                            'Auth',
359                            'Authentication algorithms in crypto drivers',
360                            'Authentication algorithm')
361    table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
362    generate_overview_table(table_file, 4,
363                            'AEAD',
364                            'AEAD algorithms in crypto drivers',
365                            'AEAD algorithm')
366    table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
367    generate_overview_table(table_file, 5,
368                            'Asymmetric',
369                            'Asymmetric algorithms in crypto drivers',
370                            'Asymmetric algorithm')
371    table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
372    generate_overview_table(table_file, 1,
373                            'Features',
374                            'Features availability in compression drivers',
375                            'Feature')
376    table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
377    generate_overview_table(table_file, 1,
378                            'Features',
379                            'Features availability in regex drivers',
380                            'Feature')
381    table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
382    generate_overview_table(table_file, 1,
383                            'Features',
384                            'Features availability in vDPA drivers',
385                            'Feature')
386    table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
387    generate_overview_table(table_file, 1,
388                            'Features',
389                            'Features availability in bbdev drivers',
390                            'Feature')
391
392    if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
393        print('Upgrade sphinx to version >= 1.3.1 for '
394              'improved Figure/Table number handling.',
395              file=stderr)
396        # Add a role to handle :numref: references.
397        app.add_role('numref', numref_role)
398        # Process the numref references once the doctree has been created.
399        app.connect('doctree-resolved', process_numref)
400
401    try:
402        # New function in sphinx 1.8
403        app.add_css_file('css/custom.css')
404    except:
405        app.add_stylesheet('css/custom.css')
406