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