1#!/usr/bin/env python3 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright(c) 2010-2015 Intel Corporation 4 5from docutils import nodes 6from distutils.version import LooseVersion 7from sphinx import __version__ as sphinx_version 8from os import listdir 9from os import environ 10from os.path import basename 11from os.path import dirname 12from os.path import join as path_join 13from sys import argv, stderr 14 15import configparser 16 17try: 18 import sphinx_rtd_theme 19 20 html_theme = "sphinx_rtd_theme" 21except: 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 27stop_on_error = ('-W' in argv) 28 29project = 'Data Plane Development Kit' 30html_logo = '../logo/DPDK_logo_vertical_rev_small.png' 31if LooseVersion(sphinx_version) >= LooseVersion('3.5'): 32 html_permalinks = False 33else: 34 html_add_permalinks = "" 35html_show_copyright = False 36highlight_language = 'none' 37 38release = environ.setdefault('DPDK_VERSION', "None") 39version = release 40 41master_doc = 'index' 42 43# Maximum feature description string length 44feature_str_len = 30 45 46# Figures, tables and code-blocks automatically numbered if they have caption 47numfig = True 48 49# Configuration for man pages 50man_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. 67def 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 81def 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 117def 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 208def 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 228def 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 242def 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 248def 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 259def 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 330def 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') 406