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