+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2018 The DPDK contributors
+
.. _coding_style:
DPDK Coding Style
License Header
~~~~~~~~~~~~~~
-Each file should begin with a special comment containing the appropriate copyright and license for the file.
-Generally this is the BSD License, except for code for Linux Kernel modules.
+Each file must begin with a special comment containing the
+`Software Package Data Exchange (SPDX) License Identfier <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
+an additional text version of the license (boilerplate).
+
After any copyright header, a blank line should be left before any other contents, e.g. include statements in a C file.
C Preprocessor Directives
* Use of the structures should be by separate variable declarations and those declarations must be extern if they are declared in a header file.
* Externally visible structure definitions should have the structure name prefixed by ``rte_`` to avoid namespace collisions.
+.. note::
+
+ Uses of ``bool`` in structures are not preferred as is wastes space and
+ it's also not clear as to what type size the bool is. A preferred use of
+ ``bool`` is mainly as a return type from functions that return true/false,
+ and maybe local variable functions.
+
+ Ref: `LKML <https://lkml.org/lkml/2017/11/21/384>`_
+
Queues
~~~~~~
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
* is DEBUG) */
rte_log_set_level(my_logtype2, RTE_LOG_NOTICE);
- /* enable all PMD logs (whose identifier string starts with "pmd") */
- rte_log_set_level_regexp("pmd.*", RTE_LOG_DEBUG);
+ /* enable all PMD logs (whose identifier string starts with "pmd.") */
+ rte_log_set_level_pattern("pmd.*", RTE_LOG_DEBUG);
/* log in debug level */
rte_log_set_global_level(RTE_LOG_DEBUG);
- RTE_LOG(DEBUG, my_logtype1, "this is is a debug level message\n");
- RTE_LOG(INFO, my_logtype1, "this is is a info level message\n");
- RTE_LOG(WARNING, my_logtype1, "this is is a warning level message\n");
- RTE_LOG(WARNING, my_logtype2, "this is is a debug level message (not displayed)\n");
+ RTE_LOG(DEBUG, my_logtype1, "this is a debug level message\n");
+ RTE_LOG(INFO, my_logtype1, "this is a info level message\n");
+ RTE_LOG(WARNING, my_logtype1, "this is a warning level message\n");
+ RTE_LOG(WARNING, my_logtype2, "this is a debug level message (not displayed)\n");
/* log in info level */
rte_log_set_global_level(RTE_LOG_INFO);
/* NOTREACHED */
}
+Dynamic Logging
+---------------
-Python Code
------------
+DPDK provides infrastructure to perform logging during runtime. This is very
+useful for enabling debug output without recompilation. To enable or disable
+logging of a particular topic, the ``--log-level`` parameter can be provided
+to EAL, which will change the log level. DPDK code can register topics,
+which allows the user to adjust the log verbosity for that specific topic.
-All Python code should work with Python 2.7+ and 3.2+ and be compliant with
-`PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
+In general, the naming scheme is as follows: ``type.section.name``
-The ``pep8`` tool can be used for testing compliance with the guidelines.
+ * Type is the type of component, where ``lib``, ``pmd``, ``bus`` and ``user``
+ are the common options.
+ * Section refers to a specific area, for example a poll-mode-driver for an
+ ethernet device would use ``pmd.net``, while an eventdev PMD uses
+ ``pmd.event``.
+ * The name identifies the individual item that the log applies to.
+ The name section must align with
+ the directory that the PMD code resides. See examples below for clarity.
-Integrating with the Build System
----------------------------------
+Examples:
-DPDK supports being built in two different ways:
+ * 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``
-* using ``make`` - or more specifically "GNU make", i.e. ``gmake`` on FreeBSD
-* using the tools ``meson`` and ``ninja``
+Specializations
+~~~~~~~~~~~~~~~
-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 addition to the above logging topic, any PMD or library can further split
+logging output by using "specializations". A specialization could be the
+difference between initialization code, and logs of events that occur at runtime.
-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:
-either ``lib`` directory or a ``driver`` subdirectory.
+An example could be the initialization log messages getting one
+specialization, while another specialization handles mailbox command logging.
+Each PMD, library or component can create as many specializations as required.
-Makefile Contents
-~~~~~~~~~~~~~~~~~
+A specialization looks like this:
-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.
+ * Initialization output: ``type.section.name.init``
+ * PF/VF mailbox output: ``type.section.name.mbox``
-.. code-block:: none
+A real world example is the i40e poll mode driver which exposes two
+specializations, one for initialization ``pmd.net.i40e.init`` and the other for
+the remaining driver logs ``pmd.net.i40e.driver``.
- # pull in basic DPDK definitions, including whether library is to be
- # built or not
- include $(RTE_SDK)/mk/rte.vars.mk
+Note that specializations have no formatting rules, but please follow
+a precedent if one exists. In order to see all current log topics and
+specializations, run the ``app/test`` binary, and use the ``dump_log_types``
- # library name
- LIB = librte_<name>.a
+Python Code
+-----------
- # any library cflags needed. Generally add "-O3 $(WERROR_FLAGS)"
- CFLAGS += -O3
- CFLAGS += $(WERROR_FLAGS)
+All Python code should be compliant with
+`PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
- # the symbol version information for the library, and .so version
- EXPORT_MAP := rte_<name>_version.map
- LIBABIVER := 1
+The ``pep8`` tool can be used for testing compliance with the guidelines.
- # all source filenames are stored in SRCS-y
- SRCS-$(CONFIG_RTE_LIBRTE_<NAME>) += rte_<name>.c
+Integrating with the Build System
+---------------------------------
- # install includes
- SYMLINK-$(CONFIG_RTE_LIBRTE_<NAME>)-include += rte_<name>.h
+DPDK is built using the tools ``meson`` and ``ninja``.
- # pull in rules to build the library
- include $(RTE_SDK)/mk/rte.lib.mk
+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.
Meson Build File Contents - Libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: python
sources = files('file1.c', ...)
- headers = files('file1.c', ...)
+ headers = files('file1.h', ...)
-The will build based on a number of conventions and assumptions within the DPDK
+This will build based on a number of conventions and assumptions within the DPDK
itself, for example, that the library name is the same as the directory name in
which the files are stored.
The optional fields are:
-allow_experimental_apis
- **Default Value = false**
- Used to allow the library to make use of APIs marked as experimental.
- Set to ``true`` if the C files in the library call any functions
- marked as experimental in any included header files.
-
build
**Default Value = true**
Used to optionally compile a library, based on its dependencies or
- environment. A simple example of use would be:
+ environment. When set to "false" the ``reason`` value, explained below, should
+ also be set to explain to the user why the component is not being built.
+ A simple example of use would be:
.. code-block:: python
- if host_machine.system() != 'linux'
+ if not is_linux
build = false
+ reason = 'only supported on Linux'
endif
cflags
- **Default Value = []**.
+ **Default Value = [<-march/-mcpu flags>]**.
Used to specify any additional cflags that need to be passed to compile
the sources in the library.
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 = []**.
+ Used to indicate any additional header file paths which should be
+ added to the header search path for other libs depending on this
+ library. EAL uses this so that other libraries building against it
+ can find the headers in subdirectories of the main EAL directory. The
+ base directory of each library is always given in the include path,
+ it does not need to be specified here.
name
**Default Value = library name derived from the directory name**.
objects that were compiled up as part of another target given in the
included library ``meson.build`` file.
-version
- **Default Value = 1**.
- Specifies the ABI version of the library, and is used as the major
- version number of the resulting ``.so`` library.
+reason
+ **Default Value = '<unknown reason>'**.
+ This variable should be used when a library is not to be built i.e. when
+ ``build`` is set to "false", to specify the reason why a library will not be
+ built. For missing dependencies this should be of the form
+ ``'missing dependency, "libname"'``.
+
+use_function_versioning
+ **Default Value = false**.
+ Specifies if the library in question has ABI versioned functions. If it
+ has, this value should be set to ensure that the C files are compiled
+ twice with suitable parameters for each of shared or static library
+ builds.
Meson Build File Contents - Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For drivers, the values are largely the same as for libraries. The variables
supported are:
-allow_experimental_apis
- As above.
-
build
As above.
using static libraries. Anything added here will be appended to the end
of the ``pkgconfig --libs`` output.
+reason
+ As above.
+
sources [mandatory]
As above
+headers
+ As above
+
version
As above