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