.. note::
The above is recommendation, and not a hard limit.
- However, it is expected that the recommendations should be followed in all but the rarest situations.
+ Generally, line lengths up to 100 characters are acceptable in the code.
C Comment Style
---------------
~~~~~~~~~~~~~~
Each file must begin with a special comment containing the
-`Software Package Data Exchange (SPDX) License Identfier <https://spdx.org/using-spdx-license-identifier>`_.
+`Software Package Data Exchange (SPDX) License Identifier <https://spdx.org/using-spdx-license-identifier>`_.
Generally this is the BSD License, except for code granted special exceptions.
The SPDX licences identifier is sufficient, a file should not contain
Conditional Compilation
~~~~~~~~~~~~~~~~~~~~~~~
+.. note::
+
+ Conditional compilation should be used only when absolutely necessary,
+ as it increases the number of target binaries that need to be built and tested.
+ See below for details of some utility macros/defines available
+ to allow ifdefs/macros to be replaced by C conditional in some cases.
+
+Some high-level guidelines on the use of conditional compilation:
+
+* If code can compile on all platforms/systems,
+ but cannot run on some due to lack of support,
+ then regular C conditionals, as described in the next section,
+ should be used instead of conditional compilation.
+* If the code in question cannot compile on all systems,
+ but constitutes only a small fragment of a file,
+ then conditional compilation should be used, as described in this section.
+* If the code for conditional compilation implements an interface in an OS
+ or platform-specific way, then create a file for each OS or platform
+ and select the appropriate file using the Meson build system.
+ In most cases, these environment-specific files should be created inside the EAL library,
+ rather than having each library implement its own abstraction layer.
+
+Additional style guidance for the use of conditional compilation macros:
+
* When code is conditionally compiled using ``#ifdef`` or ``#if``, a comment may be added following the matching
``#endif`` or ``#else`` to permit the reader to easily discern where conditionally compiled code regions end.
* This comment should be used only for (subjectively) long regions, regions greater than 20 lines, or where a series of nested ``#ifdef``'s may be confusing to the reader.
/* Or here. */
#endif /* !COMPAT_43 */
-.. note::
+Defines to Avoid Conditional Compilation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In many cases in DPDK, one wants to run code based on
+the target platform, or runtime environment.
+While this can be done using the conditional compilation directives,
+e.g. ``#ifdef RTE_EXEC_ENV_LINUX``, present in DPDK for many releases,
+this can also be done in many cases using regular ``if`` statements
+and the following defines:
+
+* ``RTE_ENV_FREEBSD``, ``RTE_ENV_LINUX``, ``RTE_ENV_WINDOWS`` -
+ these define ids for each operating system environment.
+* ``RTE_EXEC_ENV`` - this defines the id of the current environment,
+ i.e. one of the items in list above.
+* ``RTE_EXEC_ENV_IS_FREEBSD``, ``RTE_EXEC_ENV_IS_LINUX``, ``RTE_EXEC_ENV_IS_WINDOWS`` -
+ 0/1 values indicating if the current environment is that specified,
+ shortcuts for checking e.g. ``RTE_EXEC_ENV == RTE_ENV_WINDOWS``
+
+Examples of use:
+
+.. code-block:: c
+
+ /* report a unit tests as unsupported on Windows */
+ if (RTE_EXEC_ENV_IS_WINDOWS)
+ return TEST_SKIPPED;
+
+ /* set different default values depending on OS Environment */
+ switch (RTE_EXEC_ENV) {
+ case RTE_ENV_FREEBSD:
+ default = x;
+ break;
+ case RTE_ENV_LINUX:
+ default = y;
+ break;
+ case RTE_ENV_WINDOWS:
+ default = z;
+ break;
+ }
- Conditional compilation should be used only when absolutely necessary, as it increases the number of target binaries that need to be built and tested.
C Types
-------
DPDK also provides an optimized way to store elements in lockless rings.
This should be used in all data-path code, when there are several consumer and/or producers to avoid locking for concurrent access.
+Naming
+------
+
+For symbol names and documentation, new usage of
+'master / slave' (or 'slave' independent of 'master') and 'blacklist /
+whitelist' is not allowed.
+
+Recommended replacements for 'master / slave' are:
+ '{primary,main} / {secondary,replica,subordinate}'
+ '{initiator,requester} / {target,responder}'
+ '{controller,host} / {device,worker,proxy}'
+ 'leader / follower'
+ 'director / performer'
+
+Recommended replacements for 'blacklist/whitelist' are:
+ 'denylist / allowlist'
+ 'blocklist / passlist'
+
+Exceptions for introducing new usage is to maintain compatibility
+with an existing (as of 2020) hardware or protocol
+specification that mandates those terms.
+
+
Typedefs
~~~~~~~~
typedef int (lcore_function_t)(void *);
/* launch a function of lcore_function_t type */
- int rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned slave_id);
+ int rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned worker_id);
C Indentation
~~~~~~~~~~~~
* Functions which create objects, or allocate memory, should return pointer types, and NULL on error.
- The error type should be indicated may setting the variable ``rte_errno`` appropriately.
+ The error type should be indicated by setting the variable ``rte_errno`` appropriately.
* Functions which work on bursts of packets, such as RX-like or TX-like functions, should return the number of packets handled.
* Other functions returning int should generally behave like system calls:
returning 0 on success and -1 on error, setting ``rte_errno`` to indicate the specific type of error.
* The virtio network PMD in ``drivers/net/virtio`` uses ``pmd.net.virtio``
* The eventdev software poll mode driver in ``drivers/event/sw`` uses ``pmd.event.sw``
* The octeontx mempool driver in ``drivers/mempool/octeontx`` uses ``pmd.mempool.octeontx``
- * The DPDK hash library in ``lib/librte_hash`` uses ``lib.hash``
+ * The DPDK hash library in ``lib/hash`` uses ``lib.hash``
Specializations
~~~~~~~~~~~~~~~
Python Code
-----------
-All Python code should work with Python 2.7+ and 3.2+ and be compliant with
+All Python code should be compliant with
`PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
The ``pep8`` tool can be used for testing compliance with the guidelines.
Integrating with the Build System
---------------------------------
-DPDK supports being built in two different ways:
+DPDK is built using the tools ``meson`` and ``ninja``.
-* using ``make`` - or more specifically "GNU make", i.e. ``gmake`` on FreeBSD
-* using the tools ``meson`` and ``ninja``
+.. note::
-Any new library or driver to be integrated into DPDK should support being
-built with both systems. While building using ``make`` is a legacy approach, and
-most build-system enhancements are being done using ``meson`` and ``ninja``
-there are no plans at this time to deprecate the legacy ``make`` build system.
+ In order to catch possible issues as soon as possible,
+ it is recommended that developers build DPDK in "developer mode" to enable additional checks.
+ By default, this mode is enabled if the build is being done from a git checkout,
+ but the mode can be manually enabled/disabled using the
+ ``developer_mode`` meson configuration option.
-Therefore all new component additions should include both a ``Makefile`` and a
-``meson.build`` file, and should be added to the component lists in both the
-``Makefile`` and ``meson.build`` files in the relevant top-level directory:
+Therefore all new component additions should include a ``meson.build`` file,
+and should be added to the component lists in the ``meson.build`` files in the
+relevant top-level directory:
either ``lib`` directory or a ``driver`` subdirectory.
-Makefile Contents
-~~~~~~~~~~~~~~~~~
-
-The ``Makefile`` for the component should be of the following format, where
-``<name>`` corresponds to the name of the library in question, e.g. hash,
-lpm, etc. For drivers, the same format of Makefile is used.
-
-.. code-block:: none
-
- # pull in basic DPDK definitions, including whether library is to be
- # built or not
- include $(RTE_SDK)/mk/rte.vars.mk
-
- # library name
- LIB = librte_<name>.a
-
- # any library cflags needed. Generally add "-O3 $(WERROR_FLAGS)"
- CFLAGS += -O3
- CFLAGS += $(WERROR_FLAGS)
-
- # the symbol version information for the library
- EXPORT_MAP := rte_<name>_version.map
-
- # all source filenames are stored in SRCS-y
- SRCS-$(CONFIG_RTE_LIBRTE_<NAME>) += rte_<name>.c
-
- # install includes
- SYMLINK-$(CONFIG_RTE_LIBRTE_<NAME>)-include += rte_<name>.h
-
- # pull in rules to build the library
- include $(RTE_SDK)/mk/rte.lib.mk
-
Meson Build File Contents - Libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
installed to $PREFIX/include when ``ninja install`` is run. As with
source files, these should be specified using the meson ``files()``
function.
+ When ``check_includes`` build option is set to ``true``, each header file
+ has additional checks performed on it, for example to ensure that it is
+ not missing any include statements for dependent headers.
+ For header files which are public, but only included indirectly in
+ applications, these checks can be skipped by using the ``indirect_headers``
+ variable rather than ``headers``.
+
+indirect_headers
+ **Default Value = []**.
+ As with ``headers`` option above, except that the files are not checked
+ for all needed include files as part of a DPDK build when
+ ``check_includes`` is set to ``true``.
includes:
**Default Value = []**.
If a library's .so or .a file differs from that given in the directory
name, the name should be specified using this variable. In practice,
since the convention is that for a library called ``librte_xyz.so``, the
- sources are stored in a directory ``lib/librte_xyz``, this value should
+ sources are stored in a directory ``lib/xyz``, this value should
never be needed for new libraries.
.. note::
sources [mandatory]
As above
+headers
+ As above
+
version
As above
+
+
+Meson Coding Style
+------------------
+
+The following guidelines apply to the build system code in meson.build files in DPDK.
+
+* Indentation should be using 4 spaces, no hard tabs.
+
+* Line continuations should be doubly-indented to ensure visible difference from normal indentation.
+ Any line continuations beyond the first may be singly indented to avoid large amounts of indentation.
+
+* Where a line is split in the middle of a statement, e.g. a multiline `if` statement,
+ brackets should be used in preference to escaping the line break.
+
+Example::
+
+ if (condition1 and condition2 # line breaks inside () need no escaping
+ and condition3 and condition4)
+ x = y
+ endif
+
+* Lists of files or components must be alphabetical unless doing so would cause errors.
+
+* Two formats are supported for lists of files or list of components:
+
+ * For a small number of list entries, generally 3 or fewer, all elements may be put on a single line.
+ In this case, the opening and closing braces of the list must be on the same line as the list items.
+ No trailing comma is put on the final list entry.
+ * For lists with more than 3 items,
+ it is recommended that the lists be put in the files with a *single* entry per line.
+ In this case, the opening brace, or ``files`` function call must be on a line on its own,
+ and the closing brace must similarly be on a line on its own at the end.
+ To help with readability of nested sublists, the closing brace should be dedented to appear
+ at the same level as the opening braced statement.
+ The final list entry must have a trailing comma,
+ so that adding a new entry to the list never modifies any other line in the list.
+
+Examples::
+
+ sources = files('file1.c', 'file2.c')
+
+ subdirs = ['dir1', 'dir2']
+
+ headers = files(
+ 'header1.c',
+ 'header2.c',
+ 'header3.c', # always include trailing comma
+ ) # closing brace at indent level of opening brace
+
+ components = [
+ 'comp1',
+ 'comp2',
+ ...
+ 'compN',
+ ]