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