1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright(c) 2010-2015 Intel Corporation 3 4from __future__ import print_function 5import subprocess 6from docutils import nodes 7from distutils.version import LooseVersion 8from sphinx import __version__ as sphinx_version 9from sphinx.highlighting import PygmentsBridge 10from pygments.formatters.latex import LatexFormatter 11from os import listdir 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 40version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion']) 41version = version.decode('utf-8').rstrip() 42release = version 43 44master_doc = 'index' 45 46# Maximum feature description string length 47feature_str_len = 25 48 49# Figures, tables and code-blocks automatically numbered if they have caption 50numfig = True 51 52latex_documents = [ 53 ('index', 54 'doc.tex', 55 '', 56 '', 57 'manual') 58] 59 60# Latex directives to be included directly in the latex/pdf docs. 61custom_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. 70latex_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. 83class 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. 90PygmentsBridge.latex_formatter = CustomLatexFormatter 91 92# Configuration for man pages 93man_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. 110def 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 124def 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 160def 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 header_names = [] 194 for ini_filename in ini_files: 195 name = ini_filename[:-4] 196 name = name.replace('_vf', 'vf') 197 198 # Pad the table header names to match the existing format. 199 if '_vec' in name: 200 pmd, vec = name.split('_') 201 name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<') 202 else: 203 name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<') 204 205 header_names.append(name) 206 207 # Create a dict of the defined features for each driver from the ini files. 208 ini_data = {} 209 for ini_filename in ini_files: 210 config = configparser.ConfigParser() 211 config.optionxform = str 212 config.read(path_join(ini_path, ini_filename)) 213 214 # Initialize the dict with the default.ini value. 215 ini_data[ini_filename] = valid_features.copy() 216 217 # Check for a valid ini section. 218 if not config.has_section(section): 219 print("{}: File '{}' has no [{}] secton".format(warning, 220 ini_filename, 221 section)) 222 continue 223 224 # Check for valid features names. 225 for name, value in config.items(section): 226 if name not in valid_features: 227 print("{}: Unknown feature '{}' in '{}'".format(warning, 228 name, 229 ini_filename)) 230 continue 231 232 if value is not '': 233 # Get the first letter only. 234 ini_data[ini_filename][name] = value[0] 235 236 # Print out the RST Driver Overview table from the ini file data. 237 outfile = open(output_filename, 'w') 238 num_cols = len(header_names) 239 240 print_table_css(outfile, table_id) 241 print('.. table:: ' + table_name + '\n', file=outfile) 242 print_table_header(outfile, num_cols, header_names, title) 243 print_table_body(outfile, num_cols, ini_files, ini_data, default_features) 244 245 246def print_table_header(outfile, num_cols, header_names, title): 247 """ Print the RST table header. The header names are vertical. """ 248 print_table_divider(outfile, num_cols) 249 250 line = '' 251 for name in header_names: 252 line += ' ' + name[0] 253 254 print_table_row(outfile, title, line) 255 256 for i in range(1, 10): 257 line = '' 258 for name in header_names: 259 line += ' ' + name[i] 260 261 print_table_row(outfile, '', line) 262 263 print_table_divider(outfile, num_cols) 264 265 266def print_table_body(outfile, num_cols, ini_files, ini_data, default_features): 267 """ Print out the body of the table. Each row is a NIC feature. """ 268 269 for feature, _ in default_features: 270 line = '' 271 272 for ini_filename in ini_files: 273 line += ' ' + ini_data[ini_filename][feature] 274 275 print_table_row(outfile, feature, line) 276 277 print_table_divider(outfile, num_cols) 278 279 280def print_table_row(outfile, feature, line): 281 """ Print a single row of the table with fixed formatting. """ 282 line = line.rstrip() 283 print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile) 284 285 286def print_table_divider(outfile, num_cols): 287 """ Print the table divider line. """ 288 line = ' ' 289 column_dividers = ['='] * num_cols 290 line += ' '.join(column_dividers) 291 292 feature = '=' * feature_str_len 293 294 print_table_row(outfile, feature, line) 295 296 297def print_table_css(outfile, table_id): 298 template = """ 299.. raw:: html 300 301 <style> 302 .wy-nav-content { 303 opacity: .99; 304 } 305 table#idx { 306 cursor: default; 307 overflow: hidden; 308 } 309 table#idx th, table#idx td { 310 text-align: center; 311 } 312 table#idx th { 313 font-size: 80%; 314 white-space: pre-wrap; 315 vertical-align: top; 316 padding: 0.5em 0; 317 min-width: 0.9em; 318 width: 2em; 319 } 320 table#idx col:first-child { 321 width: 0; 322 } 323 table#idx th:first-child { 324 vertical-align: bottom; 325 } 326 table#idx td { 327 font-size: 70%; 328 padding: 1px; 329 } 330 table#idx td:first-child { 331 padding-left: 1em; 332 text-align: left; 333 } 334 table#idx tr:nth-child(2n-1) td { 335 background-color: rgba(210, 210, 210, 0.2); 336 } 337 table#idx th:not(:first-child):hover, 338 table#idx td:not(:first-child):hover { 339 position: relative; 340 } 341 table#idx th:not(:first-child):hover::after, 342 table#idx td:not(:first-child):hover::after { 343 content: ''; 344 height: 6000px; 345 top: -3000px; 346 width: 100%; 347 left: 0; 348 position: absolute; 349 z-index: -1; 350 background-color: #ffb; 351 } 352 table#idx tr:hover td { 353 background-color: #ffb; 354 } 355 </style> 356""" 357 print(template.replace("idx", "id%d" % (table_id)), file=outfile) 358 359 360def setup(app): 361 table_file = dirname(__file__) + '/nics/overview_table.txt' 362 generate_overview_table(table_file, 1, 363 'Features', 364 'Features availability in networking drivers', 365 'Feature') 366 table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt' 367 generate_overview_table(table_file, 1, 368 'Features', 369 'Features availability in crypto drivers', 370 'Feature') 371 table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt' 372 generate_overview_table(table_file, 2, 373 'Cipher', 374 'Cipher algorithms in crypto drivers', 375 'Cipher algorithm') 376 table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt' 377 generate_overview_table(table_file, 3, 378 'Auth', 379 'Authentication algorithms in crypto drivers', 380 'Authentication algorithm') 381 table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt' 382 generate_overview_table(table_file, 4, 383 'AEAD', 384 'AEAD algorithms in crypto drivers', 385 'AEAD algorithm') 386 387 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'): 388 print('Upgrade sphinx to version >= 1.3.1 for ' 389 'improved Figure/Table number handling.') 390 # Add a role to handle :numref: references. 391 app.add_role('numref', numref_role) 392 # Process the numref references once the doctree has been created. 393 app.connect('doctree-resolved', process_numref) 394 395 app.add_stylesheet('css/custom.css') 396