c3cd0bd6909e1dbb6dfdbff868361e287438fe2e
[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'])
62 version = version.decode('utf-8').rstrip()
63 release = version
64
65 master_doc = 'index'
66
67 # Maximum feature description string length
68 feature_str_len = 25
69
70 # Figures, tables and code-blocks automatically numbered if they have caption
71 numfig = True
72
73 latex_documents = [
74     ('index',
75      'doc.tex',
76      '',
77      '',
78      'manual')
79 ]
80
81 # Latex directives to be included directly in the latex/pdf docs.
82 custom_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.
91 latex_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.
104 class 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.
111 PygmentsBridge.latex_formatter = CustomLatexFormatter
112
113 # Configuration for man pages
114 man_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.
131 def 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
145 def 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
181 def 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
267 def 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
287 def 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
301 def 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
307 def 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
318 def 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
376 def 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)