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