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