doc: add notes for ACVP FIPS validation support
[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 packaging.version import Version
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 Version(sphinx_version) >= Version('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     if not pmd_names:
156         # Add an empty column if table is empty (required by RST syntax)
157         pmd_names.append(' ')
158
159     # Pad the table header names.
160     max_header_len = len(max(pmd_names, key=len))
161     header_names = []
162     for name in pmd_names:
163         if '_vec' in name:
164             pmd, vec = name.split('_')
165             name = '{0:{fill}{align}{width}}vec'.format(pmd,
166                     fill='.', align='<', width=max_header_len-3)
167         else:
168             name = '{0:{fill}{align}{width}}'.format(name,
169                     fill=' ', align='<', width=max_header_len)
170         header_names.append(name)
171
172     # Create a dict of the defined features for each driver from the ini files.
173     ini_data = {}
174     for ini_filename in ini_files:
175         config = configparser.ConfigParser()
176         config.optionxform = str
177         config.read(path_join(ini_path, ini_filename))
178
179         # Initialize the dict with the default.ini value.
180         ini_data[ini_filename] = valid_features.copy()
181
182         # Check for a section.
183         if not config.has_section(section):
184             continue
185
186         # Check for valid features names.
187         for name, value in config.items(section):
188             if name not in valid_features:
189                 print("{}: Unknown feature '{}' in '{}'".format(warning,
190                                                                 name,
191                                                                 ini_filename),
192                                                                 file=stderr)
193                 if stop_on_error:
194                     raise Exception('Warning is treated as a failure')
195                 continue
196
197             if value:
198                 # Get the first letter only.
199                 ini_data[ini_filename][name] = value[0]
200
201     # Print out the RST Driver Overview table from the ini file data.
202     outfile = open(output_filename, 'w')
203     num_cols = len(header_names)
204
205     print_table_css(outfile, table_id)
206     print('.. table:: ' + table_name + '\n', file=outfile)
207     print_table_header(outfile, num_cols, header_names, title)
208     print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
209
210
211 def print_table_header(outfile, num_cols, header_names, title):
212     """ Print the RST table header. The header names are vertical. """
213     print_table_divider(outfile, num_cols)
214
215     line = ''
216     for name in header_names:
217         line += ' ' + name[0]
218
219     print_table_row(outfile, title, line)
220
221     for i in range(1, len(header_names[0])):
222         line = ''
223         for name in header_names:
224             line += ' ' + name[i]
225
226         print_table_row(outfile, '', line)
227
228     print_table_divider(outfile, num_cols)
229
230
231 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
232     """ Print out the body of the table. Each row is a NIC feature. """
233
234     for feature, _ in default_features:
235         line = ''
236
237         for ini_filename in ini_files:
238             line += ' ' + ini_data[ini_filename][feature]
239
240         print_table_row(outfile, feature, line)
241
242     print_table_divider(outfile, num_cols)
243
244
245 def print_table_row(outfile, feature, line):
246     """ Print a single row of the table with fixed formatting. """
247     line = line.rstrip()
248     print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
249
250
251 def print_table_divider(outfile, num_cols):
252     """ Print the table divider line. """
253     line = ' '
254     column_dividers = ['='] * num_cols
255     line += ' '.join(column_dividers)
256
257     feature = '=' * feature_str_len
258
259     print_table_row(outfile, feature, line)
260
261
262 def print_table_css(outfile, table_id):
263     template = """
264 .. raw:: html
265
266    <style>
267       .wy-nav-content {
268          opacity: .99;
269       }
270       table#idx {
271          cursor: default;
272          overflow: hidden;
273       }
274       table#idx p {
275          margin: 0;
276          line-height: inherit;
277       }
278       table#idx th, table#idx td {
279          text-align: center;
280          border: solid 1px #ddd;
281       }
282       table#idx th {
283          padding: 0.5em 0;
284       }
285       table#idx th, table#idx th p {
286          font-size: 11px;
287          white-space: pre-wrap;
288          vertical-align: top;
289          min-width: 0.9em;
290       }
291       table#idx col:first-child {
292          width: 0;
293       }
294       table#idx th:first-child {
295          vertical-align: bottom;
296       }
297       table#idx td {
298          padding: 1px;
299       }
300       table#idx td, table#idx td p {
301          font-size: 11px;
302       }
303       table#idx td:first-child {
304          padding-left: 1em;
305          text-align: left;
306       }
307       table#idx tr:nth-child(2n-1) td {
308          background-color: rgba(210, 210, 210, 0.2);
309       }
310       table#idx th:not(:first-child):hover,
311       table#idx td:not(:first-child):hover {
312          position: relative;
313       }
314       table#idx th:not(:first-child):hover::after,
315       table#idx td:not(:first-child):hover::after {
316          content: '';
317          height: 6000px;
318          top: -3000px;
319          width: 100%;
320          left: 0;
321          position: absolute;
322          z-index: -1;
323          background-color: #ffb;
324       }
325       table#idx tr:hover td {
326          background-color: #ffb;
327       }
328    </style>
329 """
330     print(template.replace("idx", "id%d" % (table_id)), file=outfile)
331
332
333 def setup(app):
334     table_file = dirname(__file__) + '/nics/overview_table.txt'
335     generate_overview_table(table_file, 1,
336                             'Features',
337                             'Features availability in networking drivers',
338                             'Feature')
339     table_file = dirname(__file__) + '/nics/rte_flow_items_table.txt'
340     generate_overview_table(table_file, 2,
341                             'rte_flow items',
342                             'rte_flow items availability in networking drivers',
343                             'Item')
344     table_file = dirname(__file__) + '/nics/rte_flow_actions_table.txt'
345     generate_overview_table(table_file, 3,
346                             'rte_flow actions',
347                             'rte_flow actions availability in networking drivers',
348                             'Action')
349     table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
350     generate_overview_table(table_file, 1,
351                             'Features',
352                             'Features availability in crypto drivers',
353                             'Feature')
354     table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
355     generate_overview_table(table_file, 2,
356                             'Cipher',
357                             'Cipher algorithms in crypto drivers',
358                             'Cipher algorithm')
359     table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
360     generate_overview_table(table_file, 3,
361                             'Auth',
362                             'Authentication algorithms in crypto drivers',
363                             'Authentication algorithm')
364     table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
365     generate_overview_table(table_file, 4,
366                             'AEAD',
367                             'AEAD algorithms in crypto drivers',
368                             'AEAD algorithm')
369     table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
370     generate_overview_table(table_file, 5,
371                             'Asymmetric',
372                             'Asymmetric algorithms in crypto drivers',
373                             'Asymmetric algorithm')
374     table_file = dirname(__file__) + '/cryptodevs/overview_os_table.txt'
375     generate_overview_table(table_file, 6,
376                             'OS',
377                             'Operating systems support for crypto drivers',
378                             'Operating system')
379     table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
380     generate_overview_table(table_file, 1,
381                             'Features',
382                             'Features availability in compression drivers',
383                             'Feature')
384     table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
385     generate_overview_table(table_file, 1,
386                             'Features',
387                             'Features availability in regex drivers',
388                             'Feature')
389     table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
390     generate_overview_table(table_file, 1,
391                             'Features',
392                             'Features availability in vDPA drivers',
393                             'Feature')
394     table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
395     generate_overview_table(table_file, 1,
396                             'Features',
397                             'Features availability in bbdev drivers',
398                             'Feature')
399     table_file = dirname(__file__) + '/gpus/overview_feature_table.txt'
400     generate_overview_table(table_file, 1,
401                             'Features',
402                             'Features availability in GPU drivers',
403                             'Feature')
404     table_file = dirname(__file__) + '/eventdevs/overview_feature_table.txt'
405     generate_overview_table(table_file, 1,
406                             'Scheduling Features',
407                             'Features availability in eventdev drivers',
408                             'Feature')
409     table_file = dirname(__file__) + '/eventdevs/overview_rx_adptr_feature_table.txt'
410     generate_overview_table(table_file, 2,
411                             'Eth Rx adapter Features',
412                             'Features availability for Ethdev Rx adapters',
413                             'Feature')
414     table_file = dirname(__file__) + '/eventdevs/overview_tx_adptr_feature_table.txt'
415     generate_overview_table(table_file, 3,
416                             'Eth Tx adapter Features',
417                             'Features availability for Ethdev Tx adapters',
418                             'Feature')
419     table_file = dirname(__file__) + '/eventdevs/overview_crypto_adptr_feature_table.txt'
420     generate_overview_table(table_file, 4,
421                             'Crypto adapter Features',
422                             'Features availability for Crypto adapters',
423                             'Feature')
424     table_file = dirname(__file__) + '/eventdevs/overview_timer_adptr_feature_table.txt'
425     generate_overview_table(table_file, 5,
426                             'Timer adapter Features',
427                             'Features availability for Timer adapters',
428                             'Feature')
429
430     if Version(sphinx_version) < Version('1.3.1'):
431         print('Upgrade sphinx to version >= 1.3.1 for '
432               'improved Figure/Table number handling.',
433               file=stderr)
434         # Add a role to handle :numref: references.
435         app.add_role('numref', numref_role)
436         # Process the numref references once the doctree has been created.
437         app.connect('doctree-resolved', process_numref)
438
439     try:
440         # New function in sphinx 1.8
441         app.add_css_file('css/custom.css')
442     except:
443         app.add_stylesheet('css/custom.css')