Skip to main content

coding-style

Coding style rules and guidelines for Gatekeeper (following DPDK coding style). Use when writing, modifying, reviewing, or refactoring C code, header files, and build configurations in this repository.

Aller à l'installation

Informations de source

Dépôt
AltraMayor/gatekeeper
Dernière activité de la source
18 septembre 2026 à 15:00
Langue détectée de SKILL.md
anglais
Étoiles
1 645
Forks
254

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
coding-style
description
Coding style rules and guidelines for Gatekeeper (following DPDK coding style). Use when writing, modifying, reviewing, or refactoring C code, header files, and build configurations in this repository.
# Gatekeeper Coding Style Guide Gatekeeper strictly follows the **DPDK Coding Style**, which is based on the Linux Kernel coding guidelines and the FreeBSD 7.2 Kernel Developer's Manual (`style(9)`), adapted for high-performance packet processing. ## Reference - **Original DPDK Coding Style Documentation**: https://doc.dpdk.org/guides/contributing/coding_style.html All agents writing, modifying, or reviewing C code in Gatekeeper must adhere to the rules and conventions below. --- ## Agent Verification Checklist When generating or editing code, verify: - [ ] **Indentation**: Hard tabs only for indentation (8-column width). Spaces used *only* for alignment. No spaces before tabs. - [ ] **Line Length**: Lines do not exceed 80 characters (hard limit: 100 characters when strictly necessary for readability). - [ ] **Whitespace**: No trailing whitespace on any line. Exactly one newline at the end of the file (no blank lines at file end). - [ ] **Comments**: Only C-style comments `/* ... */` used. No C++ `//` comments. - [ ] **Header Includes**: Ordered cleanly: libc/system first, DPDK (`rte_*`) second, third-party libraries third, local Gatekeeper headers last. - [ ] **Header Guards**: Formatted as `#ifndef _FILE_H_`, `#define _FILE_H_`, and `#endif /* _FILE_H_ */`. - [ ] **Pointers & Asterisks**: Asterisk attached to variable name: `struct foo *ptr;`, not `struct foo* ptr`. - [ ] **NULL Checks**: Explicit comparisons against `NULL`: `if (p == NULL)` or `if (p != NULL)`. Never `if (!p)`. - [ ] **Return Statements**: No parentheses around return value: `return 0;`, never `return (0);`. - [ ] **Function Definitions**: Return type on its own line preceding the function name. Opening brace `{` on its own line. - [ ] **Control Flow**: Space after keywords (`if`, `while`, `for`, `switch`). Single-statement bodies omit braces. `else` on the same line as closing brace `} else {`. - [ ] **Casts & sizeof**: No space after cast `(type)val` or `sizeof(val)`. `sizeof` always has parentheses. No casting of `void *` pointers. --- ## 1. Indentation and Whitespace ### 1.1 Tabs vs Spaces - Indentation uses **hard tabs** (`\t`). A tab stop is assumed to be **8 characters wide**. - **Spaces are only for alignment** (e.g., aligning multiline expressions to matching parentheses, or aligning structure fields). - Never use spaces for indentation. Never place spaces before tabs. ### 1.2 Line Length - Preferred line length is **at most 80 characters**, including comments. - Lines up to **100 characters** are acceptable when splitting harms readability. - When wrapping a long statement, put the operator at the end of the line and indent the continuation line. ### 1.3 Control Statement Continuations - When continuing conditions across multiple lines in `if`, `while`, or `for` statements, indent the continuation line with **two tabs** (or align with spaces to the opening parenthesis) so it is clearly distinguished from the statement body: ```c /* Good: double tab distinguishes condition from body */ if (really_long_condition_variable_1 == really_long_condition_variable_2 && flag_is_set) { x = y + z; a = b + c; } /* Good: aligning with spaces to opening parenthesis */ if (really_long_condition_variable_1 == really_long_condition_variable_2 && flag_is_set) { x = y + z; a = b + c; } ``` ### 1.4 Trailing Whitespace and Newlines - Do not leave trailing whitespace at the end of any line. - Files must end with a single newline character. Do not leave blank lines at the end of a file. --- ## 2. Comments ### 2.1 Comment Style - Use standard C comments `/* ... */`. **Do not use C++ style single-line comments (`//`)**. - Single-line comments: ```c /* Most single-line comments look like this. */ /* * VERY important single-line comments look like this. */ ``` - Multi-line comments: ```c /* * Multi-line comments look like this. Make them real sentences. Fill * them so they look like real paragraphs. */ ``` - Doxygen-like comments (`/** ... */`) must be used for documenting public APIs, interfaces, and exported functions. ### 2.2 License Header - Every file must begin with a license header comment. - Followed by a blank line before any `#include` or preprocessor directives. --- ## 3. Preprocessor Directives and Headers ### 3.1 Header Include Order Group includes into blocks separated by a single blank line, ordered as follows: 1. Standard C library / POSIX system headers (`<stdio.h>`, `<stdlib.h>`, `<arpa/inet.h>`) 2. DPDK headers (`<rte_eal.h>`, `<rte_thash.h>`, `<rte_ether.h>`) 3. Third-party library headers (e.g. Lua, BPF) 4. Local application-specific headers (`"gatekeeper_net.h"`, `"gatekeeper_flow.h"`) System and library headers use angle brackets `<...>`; local repository headers use double quotes `"..."`: ```c #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <rte_debug.h> #include <rte_ether.h> #include <rte_thash.h> #include "gatekeeper_net.h" #include "gatekeeper_main.h" #include "gatekeeper_flow.h" ``` ### 3.2 Header Guards Headers must be protected against multiple inclusion using the standard format: ```c #ifndef _GATEKEEPER_FLOW_H_ #define _GATEKEEPER_FLOW_H_ /* Code */ #endif /* _GATEKEEPER_FLOW_H_ */ ``` ### 3.3 Macros - Macro names for constants and "unsafe" macros (those with side effects) must be in **ALL_UPPERCASE**. - Always enclose expressions in outer parentheses: ```c #define MAX_ITEMS (100) #define CALC_OFFSET(base, idx) ((base) + ((idx) * sizeof(uint32_t))) ``` - Compound statements in macros must be wrapped in `do { ... } while (0)` without a trailing semicolon: ```c #define UPDATE_COUNTERS(cnt, delta) do { \ (cnt)->pkts += (delta); \ (cnt)->bytes += (delta) * 64; \ } while (0) ``` - Prefer `enum` for sequential constants and `static inline` functions for logic over macros whenever possible for type-safety and compiler checking. ### 3.4 Conditional Compilation - Minimize `#ifdef` and conditional compilation. - If conditionally compiled regions exceed 20 lines or involve nested directives, add a comment after `#else` and `#endif`: ```c #ifdef CONFIG_FEATURE_X /* ... large block ... */ #else /* !CONFIG_FEATURE_X */ /* ... */ #endif /* CONFIG_FEATURE_X */ ``` --- ## 4. Types, Naming, and Declarations ### 4.1 Integer Types - Always use fixed-width integer types from `<stdint.h>`: `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `int8_t`, `int16_t`, `int32_t`, `int64_t`. - Do not use old BSD-style types like `u_int32_t` or `u_char`. ### 4.2 Variable and Identifier Naming - Variable and function names must be in **lowercase with underscores** (`snake_case`). - **Never** use `CamelCase` or `ALL_UPPERCASE` for variable or function names. - Public/exported symbols should follow the project namespace conventions. ### 4.3 Pointer Declarations - The asterisk `*` attaches to the variable name, not the type name: ```c int *x; /* Correct: space before asterisk, no space after */ int* x; /* Bad */ int * const x; /* Correct: space after asterisk when qualifier follows */ ``` ### 4.4 Local Variable Declarations - Multiple declarations per line are allowed, but do not exceed line length. - If variables are initialized at declaration, put only **one variable per line**, or initialize only the last variable: ```c /* Bad: multiple initializations on one line */ int i = 0, j = 0, k = 0; /* Good: one variable per line with initializer */ char a = 0; char b = 0; /* Good: only the last variable initialized */ float x, y = 0.0; ``` ### 4.5 Structures and Unions - **Avoid typedefs for structures**. Use `struct foo` directly instead of `typedef struct { ... } foo_t;`: ```c /* Good */ struct gatekeeper_flow { uint32_t id; }; struct gatekeeper_flow flow; /* Bad */ typedef struct { uint32_t id; } gatekeeper_flow_t; ``` - **Member Ordering**: 1. Order members by **use** (frequently accessed members together). 2. Order by **size descending** (largest types first: 64-bit, then 32-bit, 16-bit, 8-bit) to minimize alignment padding. 3. Order alphabetically within the same size category. - Each member on its own line; align member names with spaces: ```c struct flow_entry { struct flow_entry *next; /* List link */ uint64_t pkts; /* Packet counter */ uint32_t src; /* IPv4 source */ uint32_t dst; /* IPv4 destination */ uint16_t port; /* Layer 4 port */ uint8_t proto; /* Protocol number */ }; ``` ### 4.6 Enumerations - Enumeration constants must be **ALL_UPPERCASE**. - Enums should be used in preference to series of `#define` constants. --- ## 5. Functions ### 5.1 Function Definitions - The **return type must be on its own line** preceding the function name. - The **opening brace `{` must be on its own line** at column 0. - Function body is indented with 1 tab: ```c /* Correct function definition */ int flow_cmp(const struct ip_flow *flow1, const struct ip_flow *flow2) { if (flow1->proto != flow2->proto) return flow1->proto == RTE_ETHER_TYPE_IPV4 ? -1 : 1; return memcmp(flow1, flow2, sizeof(*flow1)); } ``` ```c /* Bad: return type on same line, brace on same line */ int flow_cmp(const struct ip_flow *flow1, const struct ip_flow *flow2) { /* ... */ } ``` ### 5.2 Function Prototypes - Prototypes keep the return type and function name on the **same line**: ```c int flow_cmp(const struct ip_flow *flow1, const struct ip_flow *flow2); ``` - Parameter names must be included with their types (e.g. `void func(int fd);`, not `void func(int);`). - Do not use old K&R function declarations or `__P` macros. ### 5.3 Static and Inline Functions - Any function local to a single `.c` file **must be declared `static`**. - Functions declared in headers must be `static inline`: ```c static inline bool flow_equal(const struct ip_flow *flow1, const struct ip_flow *flow2) { return flow_cmp(flow1, flow2) == 0; } ``` - Prefer plain `static inline` and let the compiler optimize. Avoid `__rte_always_inline` unless strictly justified (e.g. constant-folding intrinsics or measured benchmarks). - Mark cold paths (error recovery, slow path initialization) with `__rte_noinline` to reduce instruction cache pressure. --- ## 6. Control Statements and Loops ### 6.1 Keyword Spacing - Always place a single space after control keywords: `if`, `while`, `for`, `switch`, `return`. - Never put a space between a function name and opening parenthesis: ```c if (ret < 0) /* Correct */ if(ret < 0) /* Bad */ func(arg1, arg2); /* Correct */ func (arg1, arg2); /* Bad */ ``` ### 6.2 Braces for Control Blocks - **Omit braces** for single-statement control blocks: ```c /* Good */ if (flow == NULL) return -EINVAL; /* Bad */ if (flow == NULL) { return -EINVAL; } ``` - Use braces if the single statement spans multiple lines, or for nested control statements. - The `else` keyword is placed on the same line as the closing brace: ```c if (test) { stmt1; stmt2; } else if (other) { stmt3; } else { stmt4; } ``` ### 6.3 Loops - Infinite loops use `for (;;)`, not `while (1)`: ```c for (;;) { /* Loop body */ if (done) break; } ``` ### 6.4 Switch Statements - Indent the `switch` statement, but do not indent the `case` labels. Indent the case body by 1 tab: ```c switch (proto) { case IPPROTO_TCP: handle_tcp(pkt); break; case IPPROTO_UDP: handle_udp(pkt); break; case IPPROTO_ICMP: handle_icmp(pkt); /* FALLTHROUGH */ default:
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub