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