Difference between revisions of "VPP/Documentation"

From fd.io
< VPP
Jump to: navigation, search
m (Building documentation for a specific directory)
(add node template and blurb)
Line 90: Line 90:
 
== Documentation templates ==
 
== Documentation templates ==
  
And lo, verily, he did produce some morsels of scripture upon which the philistines may feast.
+
=== Documenting a graph node function ===
 +
 
 +
Nodes form the core of what VPP does and providing meaningful documentation about their function is important. This is doubly so for those nodes which are direct ancestors or descendants of a node a developer is working; that individual will be looking for details on the features the surrounding nodes make available. Examples may include the metadata passed along in the buffer opaque data which will help a node understand where a packet came from. Some nodes will expect data in the opaque section in order to steer their behavior.
 +
 
 +
By way of example, here is the documentation block for the "<code>ip4-lookup</code>" node and which may be used as a template:
 +
 
 +
<syntaxhighlight lang="c">
 +
/**
 +
* @brief IPv4 lookup node.
 +
* @node ip4-lookup
 +
*
 +
* This is the main IPv4 lookup dispatch node.
 +
*
 +
* @param vm vlib_main_t corresponding to the current thread.
 +
* @param node vlib_node_runtime_t data for this node.
 +
* @param frame vlib_frame_t whose contents should be dispatched.
 +
*
 +
* @par Graph mechanics: buffer metadata, next index usage
 +
 
 +
* <em>Uses:<em>
 +
* - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code>
 +
*    - Indicates the @c sw_if_index value of the interface that the
 +
*      packet was received on.
 +
* - <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>
 +
*    - When the value is @c ~0 then the node performs a longest prefix
 +
*      match (LPM) for the packet destination address in the FIB attached
 +
*      to the receive interface.
 +
*    - Otherwise perform LPM for the packet destination address in the
 +
*      indicated FIB. In this case <code>[VLIB_TX]</code> is a FIB index
 +
*      value (0, 1, ...) and not a VRF id.
 +
*
 +
* <em>Sets:<em>
 +
* - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
 +
*    - The lookup result adjacency index.
 +
*
 +
* <em>Next Index:</em>
 +
* - Dispatches the packet to the node index found in
 +
*  ip_adjacency_t @c adj->lookup_next_index
 +
*  (where @c adj is the lookup result adjacency).
 +
*/
 +
static uword
 +
ip4_lookup (vlib_main_t * vm,
 +
            vlib_node_runtime_t * node,
 +
            vlib_frame_t * frame)
 +
{
 +
  ...
 +
}
 +
</syntaxhighlight>
 +
 
 +
Of particular note this example describes these things:
 +
 
 +
* The node name is documented with the special "<code>@node</code>" command. This is an alias we have configured in Doxygen that provides a central index of node definitions.
 +
* A description of what extra data it uses as inputs; in this case the text describes how <code>ip4-lookup</code> makes use of <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code> and <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>.
 +
* A description of what extra data is passes on to descendants; in this case <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>.
 +
* A description of how the next node index is determined.
 +
 
 +
In this case the bulk of the node functionality can be described in terms of the <code>sw_if_index</code> sections; other nodes may need to provide more verbiage in other sections of the text. In particular, where nodes have other side-effects those should be clearly documented.

Revision as of 13:17, 28 July 2016

Documentation generation

The VPP project currently uses Doxygen as the mechanism to generate documentation. This is predominantly focused on providing developer-focused information but it can also be used to generate user-focused details.

Doxygen works by parsing source files and identifying special comment blocks that are adjacent to identifiers in the code. We have Doxygen configured to generate output for items that are not yet documented so that at the very least the names of function parameters or structure members are visible.

This wiki page aims to cover how developers can go about producing documentation. Whilst it will cover a number of Doxygen features, readers are encouraged to review the Doxygen documentation and in particular special commands page.

Build tools

All documentation generation related dependencies are installed with the install-dep target of the top level Makefile.

Building the documentation

The top level Makefile of the VPP build tree also includes a doxygen build target that will run Doxygen over the complete VPP source tree. Invoking that target will produce a significant amount of output and would look something like this:

$ make doxygen
Adding custom extension mapping: .def will be treated as language c
Adding custom extension mapping: .api will be treated as language c
Parsing layout file /home/chrisy/dev/fdio/vpp/doxygen/layout.xml...
Searching for include files...
Searching for files in directory /home/chrisy/dev/fdio/vpp/vppinfra
Searching for files in directory /home/chrisy/dev/fdio/vpp/vppinfra/autom4te.cache
Searching for files in directory /home/chrisy/dev/fdio/vpp/vppinfra/config
...
Patching output file 10218/10219
Patching output file 10219/10219
lookup cache used 25684/65536 hits=502842 misses=26575
finished...

Previewing the generated documentation

By default only HTML documentation is produced and it is built in build-root/docs/html. If you build the documentation on a workstation then you can simply open index.html in that directory with a web browser to view it, for example:

$ make doxygen
...
$ sensible-browser build-root/docs/html/index.html

Alternatively if you run this on a remote machine then an approach might be to add an HTTP server (such as Nginx or Apache HTTPD) to that host and configure it to expose the build-root/docs/html directory; one mechanism is to symbolically link to this directory from inside some other directory already visible from the HTTP server, assuming the use of symbolic links is allowed. Details on this are beyond the scope of this page.

Building documentation for a specific directory or file

Producing the documentation for the entire build tree can take some time which can become an issue if a developer is working on documentation for a specific module or directory tree. As a convenience it is possible to override the set of directories into which Doxygen will descend when searching for files to parse. For example:

$ make doxygen DOXY_INPUT=vppinfra

or, if you wanted just one file:

$ make doxygen DOXY_INPUT=vppinfra/vppinfra/pool.h

Cleaning up after Doxygen

It is also possible to clean up the Doxygen output directory. This can become useful since Doxygen does not itself remove files from the build directory on subsequent runs should they become redundant.

$ make wipe-doxygen

This is especially worth noting should you have previously built the documentation for the whole source tree and then want to build it for only one directory or file (using DOXY_INPUT); whilst unlikely, the remnants of previous documentation may interfere with Doxygen runs with a narrower scope.

Documenting the code

Whereupon Chris will provide examples of how to document code.

Documentation conventions

Doxygen comments/commands

Doxygen requires the use of specially marked comment blocks to identify documentation and recognizes several special commands inside those blocks. It provides several ways to indicate both of these things. Whilst any will work, VPP as a project has adopted the following as conventions:

  • Pre-identifier comment blocks are signified with /** ... */.
  • Post-identifier comment blocks are given with /**< ... */.
  • Special commands are prefixed with the at-sign, for example @param or @code.
    • Though you may often find the use of a back-slash in the existing code (especially \brief) these are being migrated to using at-sign.

Referring to identifiers in the text

Doxygen will automatically spot the names of known functions in the text and link those to the definition of that function. For other identifiers you must tell it to using @ref and this is encouraged in all places; note that not all things are linkable in this way (refer to the Doxygen documentation) but it it harmless to use @ref in such places.

For other items, such as function parameters, local variables or constants the use of @c is recommended. This will mono-space the text thus providing contrast with the surrounding text. Note that this works only for a single word; <tt> ... </tt> can be used for multiple words or @code ... @endcode for a C code block.

Documentation templates

Documenting a graph node function

Nodes form the core of what VPP does and providing meaningful documentation about their function is important. This is doubly so for those nodes which are direct ancestors or descendants of a node a developer is working; that individual will be looking for details on the features the surrounding nodes make available. Examples may include the metadata passed along in the buffer opaque data which will help a node understand where a packet came from. Some nodes will expect data in the opaque section in order to steer their behavior.

By way of example, here is the documentation block for the "ip4-lookup" node and which may be used as a template:

/**
 * @brief IPv4 lookup node.
 * @node ip4-lookup
 *
 * This is the main IPv4 lookup dispatch node.
 *
 * @param vm vlib_main_t corresponding to the current thread.
 * @param node vlib_node_runtime_t data for this node.
 * @param frame vlib_frame_t whose contents should be dispatched.
 *
 * @par Graph mechanics: buffer metadata, next index usage
 
 * <em>Uses:<em>
 * - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code>
 *     - Indicates the @c sw_if_index value of the interface that the
 *       packet was received on.
 * - <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>
 *     - When the value is @c ~0 then the node performs a longest prefix
 *       match (LPM) for the packet destination address in the FIB attached
 *       to the receive interface.
 *     - Otherwise perform LPM for the packet destination address in the
 *       indicated FIB. In this case <code>[VLIB_TX]</code> is a FIB index
 *       value (0, 1, ...) and not a VRF id.
 *
 * <em>Sets:<em>
 * - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
 *     - The lookup result adjacency index.
 *
 * <em>Next Index:</em>
 * - Dispatches the packet to the node index found in
 *   ip_adjacency_t @c adj->lookup_next_index
 *   (where @c adj is the lookup result adjacency).
*/
static uword
ip4_lookup (vlib_main_t * vm,
            vlib_node_runtime_t * node,
            vlib_frame_t * frame)
{
  ...
}

Of particular note this example describes these things:

  • The node name is documented with the special "@node" command. This is an alias we have configured in Doxygen that provides a central index of node definitions.
  • A description of what extra data it uses as inputs; in this case the text describes how ip4-lookup makes use of vnet_buffer(b)->sw_if_index[VLIB_RX] and vnet_buffer(b)->sw_if_index[VLIB_TX].
  • A description of what extra data is passes on to descendants; in this case vnet_buffer(b)->sw_if_index[VLIB_TX].
  • A description of how the next node index is determined.

In this case the bulk of the node functionality can be described in terms of the sw_if_index sections; other nodes may need to provide more verbiage in other sections of the text. In particular, where nodes have other side-effects those should be clearly documented.