From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <siobhan.a.butler@intel.com>
Received: from mga14.intel.com (mga14.intel.com [192.55.52.115])
 by dpdk.org (Postfix) with ESMTP id 650113237
 for <dev@dpdk.org>; Wed,  8 Apr 2015 12:43:57 +0200 (CEST)
Received: from fmsmga003.fm.intel.com ([10.253.24.29])
 by fmsmga103.fm.intel.com with ESMTP; 08 Apr 2015 03:43:57 -0700
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.11,544,1422950400"; d="scan'208";a="478251457"
Received: from irsmsx107.ger.corp.intel.com ([163.33.3.99])
 by FMSMGA003.fm.intel.com with ESMTP; 08 Apr 2015 03:43:55 -0700
Received: from irsmsx155.ger.corp.intel.com (163.33.192.3) by
 IRSMSX107.ger.corp.intel.com (163.33.3.99) with Microsoft SMTP Server (TLS)
 id 14.3.224.2; Wed, 8 Apr 2015 11:43:54 +0100
Received: from irsmsx109.ger.corp.intel.com ([169.254.13.95]) by
 irsmsx155.ger.corp.intel.com ([169.254.14.178]) with mapi id 14.03.0224.002;
 Wed, 8 Apr 2015 11:43:53 +0100
From: "Butler, Siobhan A" <siobhan.a.butler@intel.com>
To: Thomas Monjalon <thomas.monjalon@6wind.com>, "dev@dpdk.org" <dev@dpdk.org>
Thread-Topic: [dpdk-dev] tools brainstorming
Thread-Index: AQHQYx105wa2dYsDE0GLqygeszi7351DCqJg
Date: Wed, 8 Apr 2015 10:43:53 +0000
Message-ID: <0C5AFCA4B3408848ADF2A3073F7D8CC86D58F9C2@IRSMSX109.ger.corp.intel.com>
References: <3571725.20GtF5MAnU@xps13>
In-Reply-To: <3571725.20GtF5MAnU@xps13>
Accept-Language: en-IE, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-originating-ip: [163.33.239.182]
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Subject: Re: [dpdk-dev] tools brainstorming
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: patches and discussions about DPDK <dev.dpdk.org>
List-Unsubscribe: <http://dpdk.org/ml/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <http://dpdk.org/ml/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Wed, 08 Apr 2015 10:43:58 -0000

Hi all,
To add to the tools brainstorming - I propose we use the following Coding S=
tandards as the basis of guidelines on coding style going forward.
The style outlined below is in alignment with the current convention used f=
or the majority of the project.
Any thoughts/suggestions or feedback welcome.
Thanks
Siobhan :)
<siobhan.a.butler@intel.com>



Coding Style
~~~~~~~~~~

Description
-----------

This document specifies the preferred style for source files in the DPDK so=
urce tree.=20
It is based on the Linux Kernel coding guidelines and the FreeBSD 7.2 Kerne=
l Developer's Manual (see man style(9)),=20
but was heavily modified for the needs of the DPDK. Many of the style rules=
 are implicit in the examples.=20
Be careful to check the examples before assuming that style is silent on an=
 issue.=20

General Guidelines
------------------

The rules and guidelines given in this document cannot cover every situatio=
n, so the following general guidelines should be used as a fallback:=20
The code style should be consistent within each individual file, and within=
 each file in a given directory or module - in the case of creating new fil=
es=20
The primary reason for coding standards is to increase code readability and=
 comprehensibility, therefore always use whatever option will make the code=
 easiest to read.=20

The following more specific recommendations apply to all sections, both for=
 C and assembly code:=20
Line length is recommended to be not more than 80 characters, including com=
ments. [Tab stop size should be assumed to be at least 4-characters wide]=20
Indentation should be to no more than 3 levels deep.=20
NOTE The above are recommendations, and not hard limits. However, it is exp=
ected that the recommendations should be followed in all but the rarest sit=
uations.=20
C Comment Style

Usual Comments
--------------

These comments should be used in normal cases. To document a public API, a =
doxygen-like format must be used: refer to Doxygen Documentation.=20
 /*
  * VERY important single-line comments look like this.
  */
=20
 /* Most single-line comments look like this. */
=20
 /*
  * Multi-line comments look like this.  Make them real sentences. Fill
  * them so they look like real paragraphs.
  */

License Header
--------------

Each file should begin with a special comment tag which will contain the ap=
propriate copyright and license for the file (Generally BSD License).=20
After any copyright header, a blank line should be left before any other co=
ntents, e.g. include statements in a C file.=20

C Preprocessor Directives
-------------------------

Header Includes

In DPDK sources, the include files should be ordered as following:=20
 libc includes (system includes first)=20
 DPDK EAL includes=20
 DPDK misc libraries includes=20
 application-specific includes=20

Example:=20
 #include <stdio.h>
 #include <stdlib.h>
=20
 #include <rte_eal.h>
=20
 #include <rte_ring.h>
 #include <rte_mempool.h>
=20
 #include "application.h"


Global pathnames are defined in <paths.h>. Pathnames local to the program g=
o in "pathnames.h" in the local directory.=20
 #include <paths.h>


Leave another blank line before the user include files.=20
 #include "pathnames.h"         /* Local includes in double quotes. */

NOTE Please avoid, as much as possible, including headers from other header=
s file. Doing so should be properly explained and justified.=20
Headers should be protected against multiple inclusion with the usual:=20
 #ifndef _FILE_H_
 #define _FILE_H_
=20
 /* Code */
=20
 #endif /* _FILE_H_ */


Macros

Do not ``#define`` or declare names in the implementation namespace except =
for implementing application interfaces.=20

The names of ``unsafe`` macros (ones that have side effects), and the names=
 of macros for manifest constants, are all in uppercase.=20

The expansions of expression-like macros are either a single token or have =
outer parentheses. If a macro is an inline expansion of a function,=20
the function name is all in lowercase and the macro has the same name all i=
n uppercase. Right-justify the backslashes;=20
it makes it easier to read. If the macro encapsulates a compound statement,=
 enclose it in a do loop, so that it can be used safely in if statements.=20
Any final statement-terminating semicolon should be supplied by the macro i=
nvocation rather than the macro, to make parsing easier for pretty-printers=
 and editors.=20
 #define MACRO(x, y) do {                                        \
         variable =3D (x) + (y);                                   \
         (y) +=3D 2;                                               \
 }while (0)

NOTE Wherever possible, enums and typedefs should be preferred to macros, s=
ince they provide additional degrees=20
of type-safety and can allow compilers to emit extra warnings about unsafe =
code.=20

Conditional Compilation
-----------------------

When code is conditionally compiled using #ifdef or #if, a comment may be a=
dded following the matching #endif or #else to=20
permit the reader to easily discern where conditionally compiled code regio=
ns end. This comment should be used only for=20
(subjectively) long regions, regions greater than 20 lines, or where a seri=
es of nested #ifdef 's may be confusing to the reader.=20
Exceptions may be made for cases where code is conditionally not compiled f=
or the purposes of lint(1), even though the uncompiled=20
region may be small. The comment should be separated from the #endif or #el=
se by a single space. For short conditionally compiled regions,=20
a closing comment should not be used.=20

The comment for #endif should match the expression used in the correspondin=
g #if or #ifdef. The comment for #else and #elif=20
should match the inverse of the expression(s) used in the preceding #if and=
/or #elif statements. In the comments,=20
the subexpression defined(FOO) is abbreviated as FOO. For the purposes of c=
omments, #ifndef FOO is treated as #if !defined(FOO).=20
 #ifdef KTRACE
 #include <sys/ktrace.h>
 #endif
=20
 #ifdef COMPAT_43
 /* A large region here, or other conditional code. */
 #else /* !COMPAT_43 */
 /* Or here. */
 #endif /* COMPAT_43 */
=20
 #ifndef COMPAT_43
 /* Yet another large region here, or other conditional code. */
 #else /* COMPAT_43 */
 /* Or here. */
 #endif /* !COMPAT_43 */

NOTE Conditional compilation should be used only when absolutely necessary,=
 as it increases the number of target binaries that need to be built and te=
sted.=20
C Types

Integers

For fixed/minimum-size integer values, the project uses the form uintXX_t (=
from stdint.h) instead of older BSD-style integer identifiers of the form u=
_intXX_t.=20

Enumerations
------------

Enumeration values are all uppercase.=20
 enum enumtype { ONE, TWO } et;


Bitfields
---------

The developer should group bitfields that are included in the same integer,=
 as follows:=20
 struct grehdr {
   uint16_t rec:3,
       srr:1,
       seq:1,
       key:1,
       routing:1,
       csum:1,
       version:3,
       reserved:4,
       ack:1;
 /* ... */
 }


Variable Declarations
---------------------

In declarations, do not put any whitespace between asterisks and adjacent t=
okens, except for tokens that are identifiers related to types.=20
(These identifiers are the names of basic types, type qualifiers, and typed=
ef-names other than the one being declared.)=20
Separate these identifiers from asterisks using a single space.=20

Structure Declarations

When declaring variables in structures, declare them sorted by use, then by=
 size (largest to smallest), and then in alphabetical order.=20
Alignment constraints may override the previous rules. The first category n=
ormally does not apply, but there are exceptions.=20
Each structure element gets its own line. Try to make the structure readabl=
e by aligning the member names using spaces as shown below.=20
Names following extremely long types, which therefore cannot be easily alig=
ned with the rest, should be separated by a single space.=20
 struct foo {
         struct foo      *next;          /* List of active foo. */
         struct mumble   amumble;        /* Comment for mumble. */
         int             bar;            /* Try to align the comments. */
         struct verylongtypename *baz;   /* Won't fit with other members */
 };


Major structures should be declared at the top of the file in which they ar=
e used, or in separate header files if they are used=20
in multiple source files. Use of the structures should be by separate decla=
rations and should be extern if they are declared in a header file.=20

Queues

Use queue(3) macros rather than rolling your own lists, whenever possible. =
Thus, the previous example would be better written:=20
 #include <sys/queue.h>
=20
 struct foo {
         LIST_ENTRY(foo) link;      /* Use queue macros for foo lists. */
         struct mumble   amumble;   /* Comment for mumble. */
         int             bar;       /* Try to align the comments. */
         struct verylongtypename *baz;   /* Won't fit with other members */
 };
 LIST_HEAD(, foo) foohead;          /* Head of global foo list. */


DPDK also provides an optimized way to store elements in lockless rings. Th=
is should be used in all data-path code, when there are several=20
consumer and/or producers to avoid locking for concurrent access.=20

Typedefs

Avoid using typedefs for structure types. For example, use:=20
 struct my_struct_type {
 /* ... */
 };
=20
 struct my_struct_type my_var;


rather than:=20
 typedef struct my_struct_type {
 /* ... */
 } my_struct_type;
=20
 my_struct_type my_var


Typedefs are problematic because they do not properly hide their underlying=
 type; for example, you need to know if the typedef is=20
the structure itself, as shown above, or a pointer to the structure. In add=
ition, they must be declared exactly once, whereas an=20
incomplete structure type can be mentioned as many times as necessary. Type=
defs are difficult to use in stand-alone header files.=20
The header that defines the typedef must be included before the header that=
 uses it, or by the header that uses it (which causes namespace pollution),=
=20
or there must be a back-door mechanism for obtaining the typedef.=20
NOTE #defines used instead of typedefs also are problematic (since they do =
not propagate the pointer type correctly due to direct text replacement).=20
For example, ``#define pint int *`` does not work as expected, while ``type=
def int *pint`` does work. As stated when discussing macros, typedefs=20
should be preferred to macros in cases like this.=20
When convention requires a typedef; make its name match the struct tag. Avo=
id typedefs ending in ``_t``, except as specified in Standard C or by POSIX=
.=20
 /* Make the structure name match the typedef. */
 typedef struct bar {
         int     level;
 } BAR;
 typedef int             foo;            /* This is foo. */
 typedef const long      baz;            /* This is baz. */


C Function Definition, Declaration and Use

Prototypes

It is recommended, but not required that all functions are prototyped somew=
here.=20

Any function prototypes for private functions (that is, functions not used =
elsewhere) go at the top of the first source module. Functions=20
local to one source module should be declared static.=20

Functions used from other parts of code (external API) must be prototyped i=
n the relevant include file.=20
Function prototypes should be listed in a logical order, preferably alphabe=
tical unless there is a compelling reason to use a different ordering.=20

Functions that are used locally in more than one module go into a separate =
header file, for example, "extern.h".=20

Do not use the ``__P`` macro.=20

Functions that are part of an external API should be documented using Doxyg=
en-like comments above declarations. See the Doxgen documentation topic for=
 details.=20

Associate names with parameter types, for example:=20
 void function(int fd);


Short function prototypes should be contained on a single line. Longer prot=
otypes, e.g. those with many parameters,=20
can be split across multiple lines. Multi-line prototypes should use space-=
indentation to enable function parameters to line up:=20
 static char *function1(int _arg, const char *_arg2,=20
                      struct foo *_arg3,
                      struct bar *_arg4,
                      struct baz *_arg5);
 static void usage(void);


Definitions
-----------

The function type should be on a line by itself preceding the function. The=
 opening brace of the function body should be on a line by itself.=20
 static char *
 function(int a1, int a2, float fl, int a4)
 {


Do not declare functions inside other functions. ANSI C states that such de=
clarations have file scope regardless of the nesting of the declaration.=20
Hiding file declarations in what appears to be a local scope is undesirable=
 and will elicit complaints from a good compiler.=20

Old-style (K&R) function declaration should not be used, use ANSI function =
declarations instead as shown below. Long argument lists=20
should be wrapped as described above in the function prototypes section.=20
 /*
  * All major routines should have a comment briefly describing what
  * they do. The comment before the "main" routine should describe
  * what the program does.
  */
 int
 main(int argc, char *argv[])
 {
         char *ep;
         long num;
         int ch;


C Command Line Parsing
----------------------

For consistency, getopt(3) should be used to parse options. Options should =
be sorted in the getopt(3) call and the switch statement,=20
unless parts of the switch cascade. Elements in a switch statement that cas=
cade should have a FALLTHROUGH comment.=20
Numerical arguments should be checked for accuracy. Code that cannot be rea=
ched should have a NOTREACHED comment.=20
 while ((ch =3D getopt(argc, argv, "abNn:")) !=3D -1)
         switch (ch) {         /* Indent the switch. */
         case 'a':             /* Don't indent the case. */
                 aflag =3D 1;    /* Indent case body one tab. */
                 /* FALLTHROUGH */
         case 'b':
                 bflag =3D 1;
                 break;
         case 'N':
                 Nflag =3D 1;
                 break;
         case 'n':
                 num =3D strtol(optarg, &ep, 10);
                 if (num <=3D 0 || *ep !=3D '\0') {
                         warnx("illegal number, -n argument -- %s",
                               optarg);
                         usage();
                 }
                 break;
         case '?':
         default:
                 usage();
                 /* NOTREACHED */
         }
 argc -=3D optind;
 argv +=3D optind;





C Indentation
-------------

Control Statements and Loops

Include a space after keywords (if, while, for, return, switch). Do not use=
 braces (``{`` and ``}``) for control statements with zero or just a=20
single statement, unless that statement is more than a single line in which=
 case the braces are permitted. Forever loops are done with for statements,=
 not while statements.=20
 for (p =3D buf; *p !=3D '\0'; ++p)
         ;       /* nothing */
 for (;;)
         stmt;
 for (;;) {
         z =3D a + really + long + statement + that + needs +
                 two + lines + gets + indented + on + the +=20
                 second + and + subsequent + lines;
 }
 for (;;) {
         if (cond)
                 stmt;
 }
 if (val !=3D NULL)
         val =3D realloc(val, newsize);


Parts of a for loop may be left empty. It is recommended that you do not pu=
t declarations inside blocks unless the routine is unusually complicated.=20
 for (; cnt < 15; cnt++) {
         stmt1;
         stmt2;
 }


Indentation is a hard tab, that is, a tab character, not a sequence of spac=
es.=20
NOTE General rule in DPDK, use tabs for indentation, spaces for alignment.=
=20
If you have to wrap a long statement, put the operator at the end of the li=
ne, and indent again. For control statements (if, while, etc.),=20
it is recommended that the next line be indented by two tabs, rather than o=
ne, to prevent confusion as to whether the second line of the=20
control statement forms part of the statement body or not. For non-control =
statements, this issue does not apply, so they can be indented=20
by a single tab. However, a two-tab indent is recommended in this case also=
 to keep consistency across all statement types.=20
 while (really_long_variable_name_1 =3D=3D really_long_variable_name_2 &&
     var3 =3D=3D var4){
     x =3D y + z;      /* control stmt body lines up with second line of */
     a =3D b + c;      /* control statement itself if single indent used */
 }
=20
 if (really_long_variable_name_1 =3D=3D really_long_variable_name_2 &&
         var3 =3D=3D var4){  /* two tabs used */
     x =3D y + z;          /* statement body no longer lines up */
     a =3D b + c;
 }
=20
 z =3D a + really + long + statement + that + needs +
         two + lines + gets + indented + on + the +=20
         second + and + subsequent + lines;


Do not add whitespace at the end of a line.=20

Closing and opening braces go on the same line as the else keyword. Braces =
that are not necessary should be left out.=20
 if (test)
         stmt;
 else if (bar) {
         stmt;
         stmt;
 } else
         stmt;


Function Calls
--------------

Do not use spaces after function names. Commas should have a space after th=
em. No spaces after ``(`` or ``[`` or preceding the ``]`` or ``)`` characte=
rs.=20
 error =3D function(a1, a2);
 if (error !=3D 0)
         exit(error);


Operators
---------

Unary operators do not require spaces, binary operators do. Do not use pare=
ntheses unless they are required for precedence or unless the=20
statement is confusing without them. Remember that other people may be more=
 easily confused than you.=20

Exit

Exits should be 0 on success, or 1 on failure.=20
         exit(0);        /*
                          * Avoid obvious comments such as
                          * "Exit 0 on success."
                          */
 }


Local Variables
---------------

When declaring variables in functions, declare them sorted by size, then in=
 alphabetical order. Multiple variables per line are OK.=20
If a line overflows reuse the type keyword.=20

Be careful to not obfuscate the code by initializing variables in the decla=
rations, only the last variable on a line should be initialized.=20
If multiple variables are to be initialised when defined, put one per line.=
 Do not use function calls in initializers.=20
 int i =3D 0, j =3D 0, k =3D 0;  /* bad, too many initializer */
=20
 char a =3D 0;        /* OK, one variable per line with initializer */
 char b =3D 0;
=20
 float x, y =3D 0.0;  /* OK, only last variable has initializer */


Casts and sizeof

Casts and sizeof statements are not followed by a space. Always write sizeo=
f statements with parenthesis.=20
The redundant parenthesis rules do not apply to sizeof(var) instances.=20

C Style and Conventions

NULL Pointers

NULL is the preferred null pointer constant. Use NULL instead of ``(type *)=
0`` or ``(type *)NULL`` in contexts where the compiler knows the type,=20
for example, in assignments. Use ``(type *)NULL`` in other contexts, in par=
ticular for all function args.=20
(Casting is essential for variadic args and is necessary for other args if =
the function prototype might not be in scope.) Test pointers against NULL, =
for example, use::=20
 (p =3D f()) =3D=3D NULL


not::=20
 !(p =3D f())


Do not use ! for tests unless it is a boolean, for example, use::=20
 if (*p =3D=3D '\0')


not::=20
 if (!*p)


Return Value
------------

If possible, functions should return 0 on success and a negative value on e=
rror. The negative value should be ``-errno`` if relevant, for example, ``-=
EINVAL``.=20

Routines returning ``void *`` should not have their return values cast to a=
ny pointer type.=20
(Typecasting can prevent the compiler from warning about missing prototypes=
 as any implicit definition of a function returns int - which, unlike "void=
 *" needs a typecast to assign to a pointer variable.)=20
NOTE The above rule applies to malloc, as well as to DPDK functions.=20
Values in return statements should be enclosed in parentheses.=20

Logging and Errors
------------------

In the DPDK environment, use the logging interface provided::=20
 #define RTE_LOGTYPE_TESTAPP1 RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_TESTAPP2 RTE_LOGTYPE_USER2
=20
 /* enable these logs type */
 rte_set_log_type(RTE_LOGTYPE_TESTAPP1, 1);
 rte_set_log_type(RTE_LOGTYPE_TESTAPP2, 1);
=20
 /* log in debug level */
 rte_set_log_level(RTE_LOG_DEBUG);
 RTE_LOG(DEBUG, TESTAPP1, "this is is a debug level message\n");
 RTE_LOG(INFO, TESTAPP1, "this is is a info level message\n");
 RTE_LOG(WARNING, TESTAPP1, "this is is a warning level message\n");
=20
 /* log in info level */
 rte_set_log_level(RTE_LOG_INFO);
 RTE_LOG(DEBUG, TESTAPP2, "debug level message (not displayed)\n");


In a userland program that is not a DPDK application, use err(3) or warn(3)=
. Do not create your own variant.=20
         if ((four =3D malloc(sizeof(struct foo))) =3D=3D NULL)
                 err(1, (char *)NULL);
         if ((six =3D (int *)overflow()) =3D=3D NULL)
                 errx(1, "number overflowed");
         return (eight);
 }


Variable Arguments List
-----------------------

Variable numbers of arguments should look like this:=20
 #include <stdarg.h>
=20
 void
 vaf(const char *fmt, ...)
 {
         va_list ap;
=20
         va_start(ap, fmt);
         STUFF;
         va_end(ap);
         /* No return needed for void functions. */
 }
=20
 static void
 usage()
 {
         /* Insert an empty line if the function has no local variables. */


Printf
------

Use printf(3), not fputs(3), puts(3), putchar(3) or whatever. It is faster =
and usually cleaner, and helps to avoid unnecessary bugs. However, be aware=
 of format string bugs::=20
 int
 main(int argc, char **argv)
 {
         if(argc !=3D 2)
             exit(1);
         printf(argv[1]); /* bad ! */
         printf("%s", argv[1]); /* correct */


Usage
-----

Usage statements should look like the manual pages SYNOPSIS. The usage stat=
ement should be structured in the following order:=20
1. Options without operands come first, in alphabetical order, inside a sin=
gle set of brackets (``[`` and ``]``).=20
2. Options with operands come next, also in alphabetical order, with each o=
ption and its argument inside its own pair of brackets.=20
3. Required arguments (if any) are next, listed in the order they should be=
 specified on the command line.=20
4. Finally, any optional arguments, listed in the order they should be spec=
ified, and all inside brackets.=20

A bar (`|') separates ``either-or`` options/arguments, and multiple options=
/arguments, which are specified together, are placed in a single set of bra=
ckets.=20
 "usage: f [-aDde] [-b b_arg] [-m m_arg] req1 req2 [opt1 [opt2]]\n"
 "usage: f [-a | -b] [-c [-dEe] [-n number]]\n"
=20
 (void)fprintf(stderr, "usage: f [-ab]\n");
         exit(1);
 }


Note that the manual page options description should list the options in pu=
re alphabetical order. That is, without regard to=20
whether an option takes arguments or not. The alphabetical ordering should =
take into account the case ordering shown above.=20

Branch Prediction
-----------------

When a test is done in a critical zone (called often or in a data path) use=
 the ``likely()`` and ``unlikely()`` macros. They are expanded=20
as a compiler builtin and allow the developer to indicate if the branch is =
likely to be taken or not. Example:=20
 #include <rte_branch_prediction.h>
 if (likely(x > 1))
   do_stuff();


Static Variables and Functions
------------------------------

All functions and variables that are local to a file must be declared as ``=
static`` because it can often help the compiler to do=20
some optimizations (such as, inlining the code).=20

Functions that must be inlined have to be declared as ``static inline`` and=
 can be defined in a .c or a .h file.=20

Const Attribute
---------------

Particular care must be taken with the use of the ``const`` attribute. It s=
hould be used as often as possible when a variable is read-only.=20

ASM Coding Rules
----------------

Assembly Syntax

NASM is used for assembly, with the syntax, therefore guidelines given here=
 are appropriate to this target.=20
[GNU as is intended to support both syntax variants, but that is not docume=
nted here]. The following general guidelines are valid in any case.=20
 globals, extern and macros are to be defined at the top of the file=20
 labels should stay explicit, and are left aligned=20
 code is indented with a tabulation, no spaces=20
 instruction and operands should be separated by a tab too=20
 code should be separated in blocks=20
 blocks, when possible, should start with a comment explanation=20

Sample code:=20
 ; comment header
=20
 ; export this symbol
 [GLOBAL entry]
=20
 ; external variables and functions
 [EXTERN variable]
=20
 ; 16 bits code
 [BITS 16]
=20
 ; macros like
 BIOS_START  EQU     0x7C00
=20
 entry:
=20
       ; Clear interrupt flag
       cli
=20
       ; Set segment registers to 0
       xor     bx, bx
       mov     es, bx
       mov     fs, bx
       mov     gs, bx
       mov     ds, bx
       mov     ss, bx
       mov     sp, 0x7C00
       sti
=20
;; [...] snip [...]


Use of C-style macros is allowed. When compiling ASM code, a file is parsed=
 by the C preprocessor. It is then allowed to share some constants between =
C and assembly code, in a ``.h`` file.=20

Inline ASM in C code

The ``asm`` and ``volatile`` keywords do not have underscores. The AT&T syn=
tax should be used. Input and output operands should be named to avoid conf=
usion,=20
as shown in the following example::=20
 asm volatile("outb %[val], %[port]"
 : :
 [port] "dN" (port),
 [val] "a" (val));


Environment or Architecture-specific Sources

In DPDK and DPDK applications, some code is specific to an architecture (i6=
86, x86_64) or to an executive environment (bare-metal or linuxapp) and so =
on.=20

There are several ways to handle specific code:=20
 Use a ``#ifdef`` with the CONFIG option in the C code. This can be done wh=
en the differences are small and they can be embedded in the same C file::=
=20
   #ifdef RTE_ARCH_I686
   toto();
   #else
   titi();
   #endif

Use the CONFIG option in the Makefile. This is done when the differences ar=
e more significant. In this case, the code is split into
two separate files that are architecture or environment specific.=20

The same logic applies to header files.=20

By convention, a file is common if it is not located in a directory indicat=
ing that it is specific. For instance, a file located in a=20
subdir of "x86_64" directory is specific to this architecture. A file locat=
ed in a subdir of "linuxapp" is specific to this execution environment.=20
NOTE As in the linux kernel, the "CONFIG_" prefix is not used in C code. Th=
is is only needed in Makefiles or shell scripts.=20
Per Architecture Sources

The following config options can be used:=20
 CONFIG_RTE_ARCH is a string that contains the name of the architecture.=20
 CONFIG_RTE_ARCH_I686, CONFIG_RTE_ARCH_X86_64 or CONFIG_RTE_ARCH_X86_64_32 =
are defined only if we are building for those architectures.=20

Per Execution Environment Sources

The following config options can be used:=20
 CONFIG_RTE_EXEC_ENV is a string that contains the name of the executive en=
vironment.=20
 CONFIG_RTE_EXEC_ENV_BAREMETAL or CONFIG_RTE_EXEC_ENV_LINUXAPP are defined =
only if we are building for this execution environment.=20

Per Driver Sources
 RTE_LIBRTE_IGB_PMD or RTE_LIBRTE_IXGBE_PMD are defined only if we are usin=
g this driver.=20

Doxygen Documentation
---------------------

The API documentation is automatically generated in the DPDK framework. Tha=
t is why all files that are part of the public=20
API must be documented using Doxygen syntax.=20

The public API comprises functions of DPDK that can be used by an external =
application that will use the SDK. Only the Doxygen=20
syntax described in the coding rules (this document) should be used in the =
code. All the Doxygen features are described in the Doxygen manual online.=
=20

Documenting a Function

All public functions must be documented. The documentation is placed in the=
 header file, above the declaration of the function.=20
The definition of the function may be documented, but using standard commen=
ts (not in doxygen format).=20
Private functions can be documented using Doxygen. The following is an exam=
ple of function documentation:=20
 /**
  * Summary here; one sentence on one line (should not exceed 80 chars).
  *
  * A more detailed description goes here.
  *
  * A blank line forms a paragraph. There should be no trailing white-space
  * anywhere.
  *
  * @param first
  *   "@param" is a Doxygen directive to describe a function parameter. Lik=
e
  *   some other directives, it takes a term/summary on the same line and a
  *   description (this text) indented by 2 spaces on the next line. All
  *   descriptive text should wrap at 80 chars, without going over.
  *   Newlines are NOT supported within directives; if a newline would be
  *   before this text, it would be appended to the general description abo=
ve.
  * @param second
  *   There should be no newline between multiple directives (of the same
  *   type).
  *
  * @return
  *   "@return" is a different Doxygen directive to describe the return val=
ue
  *   of a function, if there is any.
  */
 int rte_foo(int first, int second)


Documenting Files

Each public file may start with a comment describing what the file does. Fo=
r example:=20
 /**
  * @file
  * This file describes the coding rules of RTE.
  *
  * It contains the coding rules of C code, ASM code, reStructured
  * Text documentation, and of course how to use doxygen to document
  * public API.
  */


Documenting Constants and Variables
 /**
  * The definition of a funny TRUE.
  */
 #define TRUE 0




 #define TRUE 1 /**< another way to document a macro */

 /**
  * Frequency of the HPET counter in Hz
  *
  * @see rte_eal_hpet_init()
  */
 extern uint64_t eal_hpet_resolution_hz;


Documenting Structures

Public structures should also be documented. The ``/**<`` sequence can be u=
sed to documented the fields of the structure, as shown in the following ex=
ample:=20
 /**
  * Structure describing a memzone, which is a contiguous portions of
  * physical memory identified by a name.
  */
 struct rte_memzone {
=20
 #define MEMZONE_NAMESIZE 32
   char name[MEMZONE_NAMESIZE]; /**< name of the memory zone */
=20
   phys_addr_t phys_addr;       /**< start physical address */
   void *addr;                  /**< start virtual address */
   uint64_t len;                /**< len of the memzone */
=20
   int socket_id;               /**< NUMA socket id */
 };


Using Lists

Using the minus character, it is possible to generate a bullet list. The mi=
nus signs must be column-aligned. If the minus sign is followed by a hash,=
=20
then it generates an enumerated list. Refer to the official Doxygen documen=
tation for more information.=20
 /**
  *  A list of events:
  *    - mouse events
  *         -# mouse move event
  *         -# mouse click event\n
  *            More info about the click event.
  *         -# mouse double click event
  *    - keyboard events
  *         -# key down event
  *         -# key up event
  *
  *  More text here.
  */


See Also Sections

The @see keyword can be used to highlight a link to an existing function, f=
ile, or URL. This directive should be placed on one line, without anything =
else, at the bottom of the documentation header.=20
 /**
  * (documentation of function, file, ...)
  *
  * @see rte_foo()
  * @see eal_memzone.c
  */
=20