xref: /dpdk/doc/guides/conf.py (revision c6dab2a873f65c5a4ea9735aa24d9539426adba4)
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# Figures, tables and code-blocks automatically numbered if they have caption
68numfig = True
69
70latex_documents = [
71    ('index',
72     'doc.tex',
73     '',
74     '',
75     'manual')
76]
77
78# Latex directives to be included directly in the latex/pdf docs.
79latex_preamble = r"""
80\usepackage[utf8]{inputenc}
81\usepackage[T1]{fontenc}
82\usepackage{helvet}
83\renewcommand{\familydefault}{\sfdefault}
84\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
85"""
86
87# Configuration for the latex/pdf docs.
88latex_elements = {
89    'papersize': 'a4paper',
90    'pointsize': '11pt',
91    # remove blank pages
92    'classoptions': ',openany,oneside',
93    'babel': '\\usepackage[english]{babel}',
94    # customize Latex formatting
95    'preamble': latex_preamble
96}
97
98
99# Override the default Latex formatter in order to modify the
100# code/verbatim blocks.
101class CustomLatexFormatter(LatexFormatter):
102    def __init__(self, **options):
103        super(CustomLatexFormatter, self).__init__(**options)
104        # Use the second smallest font size for code/verbatim blocks.
105        self.verboptions = r'formatcom=\footnotesize'
106
107# Replace the default latex formatter.
108PygmentsBridge.latex_formatter = CustomLatexFormatter
109
110# Configuration for man pages
111man_pages = [("testpmd_app_ug/run_app", "testpmd",
112              "tests for dpdk pmds", "", 1),
113             ("tools/pdump", "dpdk-pdump",
114              "enable packet capture on dpdk ports", "", 1),
115             ("tools/proc_info", "dpdk-procinfo",
116              "access dpdk port stats and memory info", "", 1),
117             ("tools/pmdinfo", "dpdk-pmdinfo",
118              "dump a PMDs hardware support info", "", 1),
119             ("tools/devbind", "dpdk-devbind",
120              "check device status and bind/unbind them from drivers", "", 8)]
121
122
123# ####### :numref: fallback ########
124# The following hook functions add some simple handling for the :numref:
125# directive for Sphinx versions prior to 1.3.1. The functions replace the
126# :numref: reference with a link to the target (for all Sphinx doc types).
127# It doesn't try to label figures/tables.
128def numref_role(reftype, rawtext, text, lineno, inliner):
129    """
130    Add a Sphinx role to handle numref references. Note, we can't convert
131    the link here because the doctree isn't build and the target information
132    isn't available.
133    """
134    # Add an identifier to distinguish numref from other references.
135    newnode = nodes.reference('',
136                              '',
137                              refuri='_local_numref_#%s' % text,
138                              internal=True)
139    return [newnode], []
140
141
142def process_numref(app, doctree, from_docname):
143    """
144    Process the numref nodes once the doctree has been built and prior to
145    writing the files. The processing involves replacing the numref with a
146    link plus text to indicate if it is a Figure or Table link.
147    """
148
149    # Iterate over the reference nodes in the doctree.
150    for node in doctree.traverse(nodes.reference):
151        target = node.get('refuri', '')
152
153        # Look for numref nodes.
154        if target.startswith('_local_numref_#'):
155            target = target.replace('_local_numref_#', '')
156
157            # Get the target label and link information from the Sphinx env.
158            data = app.builder.env.domains['std'].data
159            docname, label, _ = data['labels'].get(target, ('', '', ''))
160            relative_url = app.builder.get_relative_uri(from_docname, docname)
161
162            # Add a text label to the link.
163            if target.startswith('figure'):
164                caption = 'Figure'
165            elif target.startswith('table'):
166                caption = 'Table'
167            else:
168                caption = 'Link'
169
170            # New reference node with the updated link information.
171            newnode = nodes.reference('',
172                                      caption,
173                                      refuri='%s#%s' % (relative_url, label),
174                                      internal=True)
175            node.replace_self(newnode)
176
177
178def generate_nic_overview_table(output_filename):
179    """
180    Function to generate the NIC Overview Table from the ini files that define
181    the features for each NIC.
182
183    The default features for the table and their order is defined by the
184    'default.ini' file.
185
186    """
187    # Default worning string.
188    warning = 'Warning generate_nic_overview_table()'
189
190    # Get the default features and order from the 'default.ini' file.
191    ini_path = path_join(dirname(output_filename), 'features')
192    config = configparser.ConfigParser()
193    config.optionxform = str
194    config.read(path_join(ini_path, 'default.ini'))
195    default_section = 'Features'
196    default_features = config.items(default_section)
197
198    # Create a dict of the valid features to validate the other ini files.
199    valid_features = {}
200    max_feature_length = 0
201    for feature in default_features:
202        key = feature[0]
203        valid_features[key] = ' '
204        max_feature_length = max(max_feature_length, len(key))
205
206    # Get a list of NIC ini files, excluding 'default.ini'.
207    ini_files = [basename(file) for file in listdir(ini_path)
208                 if file.endswith('.ini') and file != 'default.ini']
209    ini_files.sort()
210
211    # Build up a list of the table header names from the ini filenames.
212    header_names = []
213    for ini_filename in ini_files:
214        name = ini_filename[:-4]
215        name = name.replace('_vf', 'vf')
216
217        # Pad the table header names to match the existing format.
218        if '_vec' in name:
219            pmd, vec = name.split('_')
220            name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
221        else:
222            name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
223
224        header_names.append(name)
225
226    # Create a dict of the defined features for each NIC from the ini files.
227    ini_data = {}
228    for ini_filename in ini_files:
229        config = configparser.ConfigParser()
230        config.optionxform = str
231        config.read(path_join(ini_path, ini_filename))
232
233        # Initialize the dict with the default.ini value.
234        ini_data[ini_filename] = valid_features.copy()
235
236        # Check for a valid ini section.
237        if not config.has_section(default_section):
238            print("{}: File '{}' has no [{}] secton".format(warning,
239                                                            ini_filename,
240                                                            default_section))
241            continue
242
243        # Check for valid features names.
244        for name, value in config.items(default_section):
245            if name not in valid_features:
246                print("{}: Unknown feature '{}' in '{}'".format(warning,
247                                                                name,
248                                                                ini_filename))
249                continue
250
251            if value is not '':
252                # Get the first letter only.
253                ini_data[ini_filename][name] = value[0]
254
255    # Print out the RST NIC Overview table from the ini file data.
256    outfile = open(output_filename, 'w')
257    num_cols = len(header_names)
258
259    print('.. table:: Features availability in networking drivers\n',
260          file=outfile)
261
262    print_table_header(outfile, num_cols, header_names)
263    print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
264
265
266def print_table_header(outfile, num_cols, header_names):
267    """ Print the RST table header. The header names are vertical. """
268    print_table_divider(outfile, num_cols)
269
270    line = ''
271    for name in header_names:
272        line += ' ' + name[0]
273
274    print_table_row(outfile, 'Feature', line)
275
276    for i in range(1, 10):
277        line = ''
278        for name in header_names:
279            line += ' ' + name[i]
280
281        print_table_row(outfile, '', line)
282
283    print_table_divider(outfile, num_cols)
284
285
286def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
287    """ Print out the body of the table. Each row is a NIC feature. """
288
289    for feature, _ in default_features:
290        line = ''
291
292        for ini_filename in ini_files:
293            line += ' ' + ini_data[ini_filename][feature]
294
295        print_table_row(outfile, feature, line)
296
297    print_table_divider(outfile, num_cols)
298
299
300def print_table_row(outfile, feature, line):
301    """ Print a single row of the table with fixed formatting. """
302    line = line.rstrip()
303    print('   {:<20}{}'.format(feature, line), file=outfile)
304
305
306def print_table_divider(outfile, num_cols):
307    """ Print the table divider line. """
308    line = ' '
309    column_dividers = ['='] * num_cols
310    line += ' '.join(column_dividers)
311
312    feature = '=' * 20
313
314    print_table_row(outfile, feature, line)
315
316
317def setup(app):
318    table_file = dirname(__file__) + '/nics/overview_table.txt'
319    generate_nic_overview_table(table_file)
320
321    if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
322        print('Upgrade sphinx to version >= 1.3.1 for '
323              'improved Figure/Table number handling.')
324        # Add a role to handle :numref: references.
325        app.add_role('numref', numref_role)
326        # Process the numref references once the doctree has been created.
327        app.connect('doctree-resolved', process_numref)
328