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