c45c4bec9dda37ff8b20349b4afd132fd86eb48a
[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
118 ######## :numref: fallback ########
119 # The following hook functions add some simple handling for the :numref:
120 # directive for Sphinx versions prior to 1.3.1. The functions replace the
121 # :numref: reference with a link to the target (for all Sphinx doc types).
122 # It doesn't try to label figures/tables.
123
124 def numref_role(reftype, rawtext, text, lineno, inliner):
125     """
126     Add a Sphinx role to handle numref references. Note, we can't convert
127     the link here because the doctree isn't build and the target information
128     isn't available.
129     """
130     # Add an identifier to distinguish numref from other references.
131     newnode = nodes.reference('',
132                               '',
133                               refuri='_local_numref_#%s' % text,
134                               internal=True)
135     return [newnode], []
136
137 def process_numref(app, doctree, from_docname):
138     """
139     Process the numref nodes once the doctree has been built and prior to
140     writing the files. The processing involves replacing the numref with a
141     link plus text to indicate if it is a Figure or Table link.
142     """
143
144     # Iterate over the reference nodes in the doctree.
145     for node in doctree.traverse(nodes.reference):
146         target = node.get('refuri', '')
147
148         # Look for numref nodes.
149         if target.startswith('_local_numref_#'):
150             target = target.replace('_local_numref_#', '')
151
152             # Get the target label and link information from the Sphinx env.
153             data = app.builder.env.domains['std'].data
154             docname, label, _ = data['labels'].get(target, ('', '', ''))
155             relative_url = app.builder.get_relative_uri(from_docname, docname)
156
157             # Add a text label to the link.
158             if target.startswith('figure'):
159                 caption = 'Figure'
160             elif target.startswith('table'):
161                 caption = 'Table'
162             else:
163                 caption = 'Link'
164
165             # New reference node with the updated link information.
166             newnode = nodes.reference('',
167                                       caption,
168                                       refuri='%s#%s' % (relative_url, label),
169                                       internal=True)
170             node.replace_self(newnode)
171
172
173 def generate_nic_overview_table(output_filename):
174     """
175     Function to generate the NIC Overview Table from the ini files that define
176     the features for each NIC.
177
178     The default features for the table and their order is defined by the
179     'default.ini' file.
180
181     """
182     # Default worning string.
183     warning = 'Warning generate_nic_overview_table()'
184
185     # Get the default features and order from the 'default.ini' file.
186     ini_path = path_join(dirname(output_filename), 'features')
187     config = configparser.ConfigParser()
188     config.optionxform = str
189     config.read(path_join(ini_path, 'default.ini'))
190     default_section = 'Features'
191     default_features = config.items(default_section)
192
193     # Create a dict of the valid features to validate the other ini files.
194     valid_features = {}
195     max_feature_length = 0
196     for feature in default_features:
197         key = feature[0]
198         valid_features[key] = ' '
199         max_feature_length = max(max_feature_length, len(key))
200
201     # Get a list of NIC ini files, excluding 'default.ini'.
202     ini_files = [basename(file) for file in listdir(ini_path)
203                  if file.endswith('.ini') and file != 'default.ini']
204     ini_files.sort()
205
206     # Build up a list of the table header names from the ini filenames.
207     header_names = []
208     for ini_filename in ini_files:
209         name = ini_filename[:-4]
210         name = name.replace('_vf', 'vf')
211
212         # Pad the table header names to match the existing format.
213         if '_vec' in name:
214             pmd, vec = name.split('_')
215             name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
216         else:
217             name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
218
219         header_names.append(name)
220
221     # Create a dict of the defined features for each NIC from the ini files.
222     ini_data = {}
223     for ini_filename in ini_files:
224         config = configparser.ConfigParser()
225         config.optionxform = str
226         config.read(path_join(ini_path, ini_filename))
227
228         # Initialize the dict with the default.ini value.
229         ini_data[ini_filename] = valid_features.copy()
230
231         # Check for a valid ini section.
232         if not config.has_section(default_section):
233             print("{}: File '{}' has no [{}] secton".format(warning,
234                                                             ini_filename,
235                                                             default_section))
236             continue
237
238         # Check for valid features names.
239         for name, value in config.items(default_section):
240             if name not in valid_features:
241                 print("{}: Unknown feature '{}' in '{}'".format(warning,
242                                                                 name,
243                                                                 ini_filename))
244                 continue
245
246             if value is not '':
247                 # Get the first letter only.
248                 ini_data[ini_filename][name] = value[0]
249
250     # Print out the RST NIC Overview table from the ini file data.
251     outfile = open(output_filename, 'w')
252     num_cols = len(header_names)
253
254     print('.. table:: Features availability in networking drivers\n',
255           file=outfile)
256
257     print_table_header(outfile, num_cols, header_names)
258     print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
259
260
261 def print_table_header(outfile, num_cols, header_names):
262     """ Print the RST table header. The header names are vertical. """
263     print_table_divider(outfile, num_cols)
264
265     line = ''
266     for name in header_names:
267         line += ' ' + name[0]
268
269     print_table_row(outfile, 'Feature', line)
270
271     for i in range(1, 10):
272         line = ''
273         for name in header_names:
274             line += ' ' + name[i]
275
276         print_table_row(outfile, '', line)
277
278     print_table_divider(outfile, num_cols)
279
280
281 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
282     """ Print out the body of the table. Each row is a NIC feature. """
283
284     for feature, _ in default_features:
285         line = ''
286
287         for ini_filename in ini_files:
288             line += ' ' + ini_data[ini_filename][feature]
289
290         print_table_row(outfile, feature, line)
291
292     print_table_divider(outfile, num_cols)
293
294
295 def print_table_row(outfile, feature, line):
296     """ Print a single row of the table with fixed formatting. """
297     line = line.rstrip()
298     print('   {:<20}{}'.format(feature, line), file=outfile)
299
300
301 def print_table_divider(outfile, num_cols):
302     """ Print the table divider line. """
303     line = ' '
304     column_dividers = ['='] * num_cols
305     line += ' '.join(column_dividers)
306
307     feature = '=' * 20
308
309     print_table_row(outfile, feature, line)
310
311
312 def setup(app):
313     generate_nic_overview_table('doc/guides/nics/overview_table.txt')
314
315     if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
316         print('Upgrade sphinx to version >= 1.3.1 for '
317               'improved Figure/Table number handling.')
318         # Add a role to handle :numref: references.
319         app.add_role('numref', numref_role)
320         # Process the numref references once the doctree has been created.
321         app.connect('doctree-resolved', process_numref)