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