xref: /dpdk/doc/guides/conf.py (revision 72c00ae9dba7fc3f8c892b0354b956e885a25770)
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 packaging.version import Version
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 Version(sphinx_version) >= Version('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    if not pmd_names:
156        # Add an empty column if table is empty (required by RST syntax)
157        pmd_names.append(' ')
158
159    # Pad the table header names.
160    max_header_len = len(max(pmd_names, key=len))
161    header_names = []
162    for name in pmd_names:
163        if '_vec' in name:
164            pmd, vec = name.split('_')
165            name = '{0:{fill}{align}{width}}vec'.format(pmd,
166                    fill='.', align='<', width=max_header_len-3)
167        else:
168            name = '{0:{fill}{align}{width}}'.format(name,
169                    fill=' ', align='<', width=max_header_len)
170        header_names.append(name)
171
172    # Create a dict of the defined features for each driver from the ini files.
173    ini_data = {}
174    for ini_filename in ini_files:
175        config = configparser.ConfigParser()
176        config.optionxform = str
177        config.read(path_join(ini_path, ini_filename))
178
179        # Initialize the dict with the default.ini value.
180        ini_data[ini_filename] = valid_features.copy()
181
182        # Check for a section.
183        if not config.has_section(section):
184            continue
185
186        # Check for valid features names.
187        for name, value in config.items(section):
188            if name not in valid_features:
189                print("{}: Unknown feature '{}' in '{}'".format(warning,
190                                                                name,
191                                                                ini_filename),
192                                                                file=stderr)
193                if stop_on_error:
194                    raise Exception('Warning is treated as a failure')
195                continue
196
197            if value:
198                # Get the first letter only.
199                ini_data[ini_filename][name] = value[0]
200
201    # Print out the RST Driver Overview table from the ini file data.
202    outfile = open(output_filename, 'w')
203    num_cols = len(header_names)
204
205    print_table_css(outfile, table_id)
206    print('.. table:: ' + table_name + '\n', file=outfile)
207    print_table_header(outfile, num_cols, header_names, title)
208    print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
209
210
211def print_table_header(outfile, num_cols, header_names, title):
212    """ Print the RST table header. The header names are vertical. """
213    print_table_divider(outfile, num_cols)
214
215    line = ''
216    for name in header_names:
217        line += ' ' + name[0]
218
219    print_table_row(outfile, title, line)
220
221    for i in range(1, len(header_names[0])):
222        line = ''
223        for name in header_names:
224            line += ' ' + name[i]
225
226        print_table_row(outfile, '', line)
227
228    print_table_divider(outfile, num_cols)
229
230
231def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
232    """ Print out the body of the table. Each row is a NIC feature. """
233
234    for feature, _ in default_features:
235        line = ''
236
237        for ini_filename in ini_files:
238            line += ' ' + ini_data[ini_filename][feature]
239
240        print_table_row(outfile, feature, line)
241
242    print_table_divider(outfile, num_cols)
243
244
245def print_table_row(outfile, feature, line):
246    """ Print a single row of the table with fixed formatting. """
247    line = line.rstrip()
248    print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
249
250
251def print_table_divider(outfile, num_cols):
252    """ Print the table divider line. """
253    line = ' '
254    column_dividers = ['='] * num_cols
255    line += ' '.join(column_dividers)
256
257    feature = '=' * feature_str_len
258
259    print_table_row(outfile, feature, line)
260
261
262def print_table_css(outfile, table_id):
263    template = """
264.. raw:: html
265
266   <style>
267      .wy-nav-content {
268         opacity: .99;
269      }
270      table#idx {
271         cursor: default;
272         overflow: hidden;
273      }
274      table#idx p {
275         margin: 0;
276         line-height: inherit;
277      }
278      table#idx th, table#idx td {
279         text-align: center;
280         border: solid 1px #ddd;
281      }
282      table#idx th {
283         padding: 0.5em 0;
284      }
285      table#idx th, table#idx th p {
286         font-size: 11px;
287         white-space: pre-wrap;
288         vertical-align: top;
289         min-width: 0.9em;
290      }
291      table#idx col:first-child {
292         width: 0;
293      }
294      table#idx th:first-child {
295         vertical-align: bottom;
296      }
297      table#idx td {
298         padding: 1px;
299      }
300      table#idx td, table#idx td p {
301         font-size: 11px;
302      }
303      table#idx td:first-child {
304         padding-left: 1em;
305         text-align: left;
306      }
307      table#idx tr:nth-child(2n-1) td {
308         background-color: rgba(210, 210, 210, 0.2);
309      }
310      table#idx th:not(:first-child):hover,
311      table#idx td:not(:first-child):hover {
312         position: relative;
313      }
314      table#idx th:not(:first-child):hover::after,
315      table#idx td:not(:first-child):hover::after {
316         content: '';
317         height: 6000px;
318         top: -3000px;
319         width: 100%;
320         left: 0;
321         position: absolute;
322         z-index: -1;
323         background-color: #ffb;
324      }
325      table#idx tr:hover td {
326         background-color: #ffb;
327      }
328   </style>
329"""
330    print(template.replace("idx", "id%d" % (table_id)), file=outfile)
331
332
333def setup(app):
334    table_file = dirname(__file__) + '/nics/overview_table.txt'
335    generate_overview_table(table_file, 1,
336                            'Features',
337                            'Features availability in networking drivers',
338                            'Feature')
339    table_file = dirname(__file__) + '/nics/rte_flow_items_table.txt'
340    generate_overview_table(table_file, 2,
341                            'rte_flow items',
342                            'rte_flow items availability in networking drivers',
343                            'Item')
344    table_file = dirname(__file__) + '/nics/rte_flow_actions_table.txt'
345    generate_overview_table(table_file, 3,
346                            'rte_flow actions',
347                            'rte_flow actions availability in networking drivers',
348                            'Action')
349    table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
350    generate_overview_table(table_file, 1,
351                            'Features',
352                            'Features availability in crypto drivers',
353                            'Feature')
354    table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
355    generate_overview_table(table_file, 2,
356                            'Cipher',
357                            'Cipher algorithms in crypto drivers',
358                            'Cipher algorithm')
359    table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
360    generate_overview_table(table_file, 3,
361                            'Auth',
362                            'Authentication algorithms in crypto drivers',
363                            'Authentication algorithm')
364    table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
365    generate_overview_table(table_file, 4,
366                            'AEAD',
367                            'AEAD algorithms in crypto drivers',
368                            'AEAD algorithm')
369    table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
370    generate_overview_table(table_file, 5,
371                            'Asymmetric',
372                            'Asymmetric algorithms in crypto drivers',
373                            'Asymmetric algorithm')
374    table_file = dirname(__file__) + '/cryptodevs/overview_os_table.txt'
375    generate_overview_table(table_file, 6,
376                            'OS',
377                            'Operating systems support for crypto drivers',
378                            'Operating system')
379    table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
380    generate_overview_table(table_file, 1,
381                            'Features',
382                            'Features availability in compression drivers',
383                            'Feature')
384    table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
385    generate_overview_table(table_file, 1,
386                            'Features',
387                            'Features availability in regex drivers',
388                            'Feature')
389    table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
390    generate_overview_table(table_file, 1,
391                            'Features',
392                            'Features availability in vDPA drivers',
393                            'Feature')
394    table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
395    generate_overview_table(table_file, 1,
396                            'Features',
397                            'Features availability in bbdev drivers',
398                            'Feature')
399    table_file = dirname(__file__) + '/gpus/overview_feature_table.txt'
400    generate_overview_table(table_file, 1,
401                            'Features',
402                            'Features availability in GPU drivers',
403                            'Feature')
404    table_file = dirname(__file__) + '/eventdevs/overview_feature_table.txt'
405    generate_overview_table(table_file, 1,
406                            'Scheduling Features',
407                            'Features availability in eventdev drivers',
408                            'Feature')
409    table_file = dirname(__file__) + '/eventdevs/overview_rx_adptr_feature_table.txt'
410    generate_overview_table(table_file, 2,
411                            'Eth Rx adapter Features',
412                            'Features availability for Ethdev Rx adapters',
413                            'Feature')
414    table_file = dirname(__file__) + '/eventdevs/overview_tx_adptr_feature_table.txt'
415    generate_overview_table(table_file, 3,
416                            'Eth Tx adapter Features',
417                            'Features availability for Ethdev Tx adapters',
418                            'Feature')
419    table_file = dirname(__file__) + '/eventdevs/overview_crypto_adptr_feature_table.txt'
420    generate_overview_table(table_file, 4,
421                            'Crypto adapter Features',
422                            'Features availability for Crypto adapters',
423                            'Feature')
424    table_file = dirname(__file__) + '/eventdevs/overview_timer_adptr_feature_table.txt'
425    generate_overview_table(table_file, 5,
426                            'Timer adapter Features',
427                            'Features availability for Timer adapters',
428                            'Feature')
429
430    if Version(sphinx_version) < Version('1.3.1'):
431        print('Upgrade sphinx to version >= 1.3.1 for '
432              'improved Figure/Table number handling.',
433              file=stderr)
434        # Add a role to handle :numref: references.
435        app.add_role('numref', numref_role)
436        # Process the numref references once the doctree has been created.
437        app.connect('doctree-resolved', process_numref)
438
439    try:
440        # New function in sphinx 1.8
441        app.add_css_file('css/custom.css')
442    except:
443        app.add_stylesheet('css/custom.css')
444