rte_graph_feature_arc.h(3)
πΈ NAME πΈ
okay so bestie, meet the moment: the name is rte_graph_feature_arc.h π that's it, that's the name, that's the whole section. It's a section 3 page, so it hangs out in the Library Functions Manual β y'know, the place where the C library keeps all its lore. Periodt.
π¦ SYNOPSIS π¦
Before you can even look at the API you gotta #include the entire friend group. Nobody gets left out, everybody's invited, fr fr:
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rte_common.h>
#include <rte_compat.h>
#include <rte_debug.h>
#include <rte_graph.h>
#include <rte_rcu_qsbr.h>
π Data Structures π
Two structs, both absolutely main character energy, no notes:
struct rte_graph_feature_registerstruct rte_graph_feature_arc_register
β¨ Macros β¨
Four of them, here they are in all their glory β the definitions are literally exactly this, don't @ me:
#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZEβ the arc name length is just defined asRTE_NODE_NAMESIZE, that's the whole bit π#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT16_MAX)β the initializer value, straight up cast torte_graph_feature_arc_tfromUINT16_MAX#define RTE_GRAPH_FEATURE_REGISTER(reg)β takes areg, and the body is not written out here, so that's all we know π#define RTE_GRAPH_FEATURE_ARC_REGISTER(reg)β same situation, takes areg, no body shown
π§ Typedefs π§
The type glow-ups, in order:
typedef uint16_t rte_graph_feature_arc_tβ an arc is auint16_t, simple astypedef uint8_t rte_graph_feature_tβ a feature is auint8_ttypedef uint32_t rte_graph_feature_data_tβ feature data is auint32_ttypedef void(* rte_graph_feature_change_notifier_cb_t) (const char *arc_name, const char *feature_name, rte_node_t feature_node_id, uint32_t index, bool enable_disable, uint16_t app_cookie)β a change-notifier callback, returnsvoid, takesarc_name,feature_name,feature_node_id,index,enable_disableandapp_cookieπ«Άtypedef uint16_t(* rte_graph_feature_override_index_cb_t) (void)β an override-index callback, takes literally nothing, hands you back auint16_t
π Functions π
Quick vibe check before we dive in: every single one of these is __rte_experimental β so yes, they're the experimental girlies, treat them with the respect they deserve π₯ Here's the full roster, prototypes verbatim:
__rte_experimental int rte_graph_feature_arc_init (uint16_t num_feature_arcs)__rte_experimental int rte_graph_feature_arc_create (struct rte_graph_feature_arc_register *reg, rte_graph_feature_arc_t *_arc)__rte_experimental int rte_graph_feature_arc_lookup_by_name (const char *arc_name, rte_graph_feature_arc_t *_arc)__rte_experimental int rte_graph_feature_add (struct rte_graph_feature_register *feat_reg)__rte_experimental int rte_graph_feature_enable (rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, uint16_t app_cookie, struct rte_rcu_qsbr *qsbr)__rte_experimental int rte_graph_feature_disable (rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, struct rte_rcu_qsbr *qsbr)__rte_experimental int rte_graph_feature_lookup (rte_graph_feature_arc_t arc, const char *feature_name, rte_graph_feature_t *feature)__rte_experimental int rte_graph_feature_arc_destroy (rte_graph_feature_arc_t _arc)__rte_experimental int rte_graph_feature_arc_cleanup (void)__rte_experimental uint32_t rte_graph_feature_arc_num_features (rte_graph_feature_arc_t _arc)__rte_experimental uint32_t rte_graph_feature_arc_num_enabled_features (rte_graph_feature_arc_t _arc)__rte_experimental char * rte_graph_feature_arc_feature_to_name (rte_graph_feature_arc_t _arc, rte_graph_feature_t feature)__rte_experimental int rte_graph_feature_arc_feature_to_node (rte_graph_feature_arc_t _arc, rte_graph_feature_t feature, rte_node_t *node)__rte_experimental uint32_t rte_graph_feature_arc_names_get (char *arc_names[])
and that's just the signatures bestie β lowkey the fun part is what comes next π
π Detailed Description π
β οΈ Warning β οΈ β EXPERIMENTAL: literally all functions in this file may be changed or removed without prior notice. No cap. It's giving "we might delete your fave" energy. Proceed accordingly, bestie.
π Graph Feature Arc API π
Define APIs and structures/variables with respect to feature arc β¨
- Feature arc(s)
- Feature(s)
Okay so picture this. In a typical network stack, a protocol usually has to be enabled in the control plane before any packet gets steered toward it for processing in the dataplane. Example: incoming IPv4 packets are only routed after a valid IPv4 address has been assigned to the received interface. In other words β and this is the whole vibe β packets received on an interface often need to be steered to a protocol not based on the packet content, but based on whether the protocol is configured on the interface or not. π
Protocols can be enabled/disabled multiple times at runtime in the control plane. Protocols enabled on one interface may not be enabled on another interface. (Yes, they can be that different. It's giving independent main character energy. π¦)
When more than one protocol lives in a networking layer (say IPv4, IP tables, IPsec, etc.) it becomes imperative to steer packets β in the dataplane β across each protocol's processing in a defined sequential order. In the ingress direction, the stack decides to perform IPsec decryption first before IP validation, while in the egress direction IPsec encryption is performed after IP forwarding. And for IP tables? Users can enable rules in any protocol order, i.e. pre-routing or post-routing, etc. Which means protocols are configured differently at each networking layer and in each traffic direction. Periodt. π
A feature arc represents an ordered list of features/protocol nodes at the given networking layer and in a given direction. It gives you a high level abstraction to enable/disable features on an index at runtime, and a mechanism to steer packets across these feature nodes in a generic manner. Here, <italic>index</italic> corresponds to either interface index, route index, flow index or classification index etc., as it is deemed suitable to configure protocols at the networking layer. Some typical examples of protocols which are configured based on:
- Interface Index (like IPv4 VRF, Port mirroring, Port based IPsec etc)
- Routes Index (like Route based IPsec etc)
- Flow index (like SDN)
- Classification Index (like ACL based protocol steering)
Feature arc also gives you a way to steer packets from in-built DPDK feature nodes to out-of-tree feature nodes and vice-versa without any code changes required in DPDK in-built node's fast path functions. Which means it lets an application override the default packet path defined by in-built DPDK nodes. Slay. π₯
Features enabled on one index may not be enabled on another index, hence packets received on interface "X" should be treated independently from packets received on interface "Y".
A given feature might consume packet (if it's configured to consume) or may forward it to the next enabled feature. For instance, "IPsec input" feature may consume/drop all packets with "Protect" policy action while all packets with policy action as "Bypass" may be forwarded to next enabled feature (within the same feature arc).
A feature arc in a graph is represented via start_node and end_feature_node. Feature nodes are added between start_node and end_feature_node. Packets enter the feature arc path via start_node while they exit from end_feature_node. Packet steering from start_node to feature nodes is controlled in the control plane via rte_graph_feature_enable(), rte_graph_feature_disable().
This library facilitates rte graph based applications to implement the stack functionalities described above by providing an "edge" to the next enabled feature node in the fast path. π«Ά
In order to use feature-arc APIs, applications need to do the following in the control plane:
- Create feature arc object using
RTE_GRAPH_FEATURE_ARC_REGISTER() - New feature nodes (In-built or out-of-tree) can be added to an arc via
RTE_GRAPH_FEATURE_REGISTER().RTE_GRAPH_FEATURE_REGISTER()hasrte_graph_feature_register::runs_afterandrte_graph_feature_register::runs_beforeto specify protocol ordering constraints. - Before calling
rte_graph_create(),rte_graph_feature_arc_init()API must be called. Ifrte_graph_feature_arc_init()is not called by the application, the feature arc library has no affect. - Features can be enabled/disabled on any index at runtime via
rte_graph_feature_enable(),rte_graph_feature_disable(). - Feature arc can be destroyed via
rte_graph_feature_arc_destroy()
If a given feature likes to control a number of indexes (which is higher than rte_graph_feature_arc_register::max_indexes) it can do so by setting rte_graph_feature_register::override_index_cb(). As part of rte_graph_feature_arc_init(), all rte_graph_feature_register::override_index_cb(), if set, are called and the maximum value returned by any of the features is used for rte_graph_feature_arc_create().
Before enabling a feature, the control plane might allocate certain resources (like VRF table for IP lookup or IPsec SA for inbound policy, etc). A reference of the allocated resource can be passed from control plane to dataplane via the app_cookie argument in rte_graph_feature_enable(). A corresponding dataplane API rte_graph_feature_data_app_cookie_get() can be used to retrieve the same cookie in the fast path. πͺ (it's literally called a cookie, iconic)
When a feature is disabled, resources allocated during feature enable can be safely released via registering a callback in rte_graph_feature_register::notifier_cb(). See the fast path synchronization section below for more details.
If the current feature node is not consuming the packet, it might want to send it to the next enabled feature. Depending upon whether the current node is a:
<italic>start_node</italic>(viarte_graph_feature_data_first_feature_get())- feature node added between
start_nodeandend_node(viarte_graph_feature_data_next_feature_get()) <italic>end_feature_node</italic>(must not call any feature arc steering APIs) as from this node the packet exits the feature arc
The above APIs deal with the fast path object: <italic>feature_data</italic> (struct rte_graph_feature_data), which is unique for every index per feature within a feature arc. It holds three data fields: next node edge, next enabled feature data and app_cookie.
rte_mbuf carries [feature_data] into a feature arc specific mbuf dynamic field. See rte_graph_feature_arc_mbuf_dynfields and rte_graph_feature_arc_mbuf_dynfields_get() for more details.
πβοΈ Fast path synchronization πβοΈ
Any feature enable/disable in the control plane does not require stopping of worker cores. rte_graph_feature_enable()/rte_graph_feature_disable() APIs are almost thread-safe, avoiding any RCU usage. The only condition when a race condition could occur is when the application is trying to enable/disable a feature very fast for a [feature, index] combination. In that case, the application should use the rte_graph_feature_enable(), rte_graph_feature_disable() APIs with the RCU argument.
RCU synchronization may also be required when the application needs to free resources (using rte_graph_feature_register::notifier_cb()) which it may have allocated during feature enable. Resources can be freed only when no worker core is acting on it.
If the RCU argument to rte_graph_feature_enable(), rte_graph_feature_disable() is non-NULL, as part of the APIs:
rte_rcu_qsbr_synchronize()is called to synchronize all worker cores- If set,
rte_graph_feature_register::notifier_cb()is called, in which the application can safely release resources associated with[feature, index]
It is the application's responsibility to pass a valid RCU argument to the APIs. It is recommended that the application calls rte_rcu_qsbr_quiescent() after every iteration of rte_graph_walk(). π§
π§ Constraints π§
rte_graph_feature_arc_init(),rte_graph_feature_arc_create()andrte_graph_feature_add()must be called beforerte_graph_create().rte_graph_feature_enable(),rte_graph_feature_disable()should be called afterrte_graph_create()- Not more than 63 features can be added to a feature arc. There is no limit to the number of feature arcs, i.e. the number of
RTE_GRAPH_FEATURE_ARC_REGISTER() - There is also no limit for the number of indexes (
rte_graph_feature_arc_register::max_indexes). There is also a provision for eachRTE_GRAPH_FEATURE_REGISTER()to override the number of indexes viarte_graph_feature_register::override_index_cb() - A feature node cannot be part of more than one arc, due to performance reasons. (one arc only, no polyamory, sorry π)
β¨ Optional Usage β¨
Feature arc is added as an optional functionality to the graph library, hence an application may choose not to use it by skipping the explicit call to rte_graph_feature_arc_init(). In that case, feature arc would be a no-op for the application.
Definition in file rte_graph_feature_arc.h.
π Macro Definition Documentation π
#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE
Length of feature arc name β¨
Definition at line 206 of file rte_graph_feature_arc.h.
#define RTE_GRAPH_FEATURE_ARC_INITIALIZER
((rte_graph_feature_arc_t)UINT16_MAX)
Initializer values for ARC, Feature, Feature data π«Ά
Definition at line 209 of file rte_graph_feature_arc.h.
#define RTE_GRAPH_FEATURE_REGISTER( reg)
Value:
RTE_INIT(__rte_graph_feature_register_##reg) \
{ \
__rte_graph_feature_register(®, __func__, __LINE__); \
}
Constructor to register a feature to an arc πΈ
Definition at line 346 of file rte_graph_feature_arc.h.
#define RTE_GRAPH_FEATURE_ARC_REGISTER( reg)
Value:
RTE_INIT(__rte_graph_feature_arc_register_##reg) \
{ \
__rte_graph_feature_arc_register(®, __func__, __LINE__); \
}
Constructor to register a feature arc π
Definition at line 353 of file rte_graph_feature_arc.h.
π¦ Typedef Documentation π¦
typedef uint16_t rte_graph_feature_arc_t
rte_graph feature arc object π
Definition at line 214 of file rte_graph_feature_arc.h.
typedef uint8_t rte_graph_feature_t
rte_graph feature object β¨
Definition at line 217 of file rte_graph_feature_arc.h.
typedef uint32_t rte_graph_feature_data_t
rte_graph feature data object π
Definition at line 220 of file rte_graph_feature_arc.h.
typedef void(* rte_graph_feature_change_notifier_cb_t) (const char *arc_name, const char *feature_name, rte_node_t feature_node_id, uint32_t index, bool enable_disable, uint16_t app_cookie)
feature notifier callback β called when a feature is enabled/disabled π
Definition at line 223 of file rte_graph_feature_arc.h.
typedef uint16_t(* rte_graph_feature_override_index_cb_t) (void)
cb for overriding arc->max_indexes via RTE_GRAPH_FEATURE_REGISTER() π―
Definition at line 231 of file rte_graph_feature_arc.h.
π₯ Function Documentation π₯
rte_graph_feature_arc_init()
__rte_experimental int rte_graph_feature_arc_init(uint16_t num_feature_arcs)
bestie this is THE setup moment, the main character entrance, the "let's get this party started" of the whole feature arc universe π
Here's everything it does:
- Initializes feature arc module and alloc associated memory β¨
- creates feature arc for every
RTE_GRAPH_FEATURE_ARC_REGISTER() - Add feature node to a feature arc for every
RTE_GRAPH_FEATURE_REGISTER() - Replaces all
RTE_NODE_REGISTER()->process()functions for- Every
start_node/end_feature_nodeprovided in arc registration - Every feature node provided in feature registration
- Every
Parameters
num_feature_arcsβ Number of feature arcs that application wants to create by explicitly using "rte_graph_feature_arc_create()" API.
okay so real talk about this count, because the math is lowkey important:
Number of RTE_GRAPH_FEATURE_ARC_REGISTER() should be excluded from this count as API internally calculates number of RTE_GRAPH_FEATURE_ARC_REGISTER().
So, total number of supported arcs = num_feature_arcs + NUMBER_OF(RTE_GRAPH_FEATURE_ARC_REGISTER())
Returns
0: Success, <0: Failure
and yes rte_graph_feature_arc_init(0) is a valid call, which will accommodates constructor based arc registration π«Ά
rte_graph_feature_arc_create()
__rte_experimental int rte_graph_feature_arc_create(struct rte_graph_feature_arc_register * reg, rte_graph_feature_arc_t * _arc)
Create a feature arc. π¦
This API can be skipped if RTE_GRAPH_FEATURE_ARC_REGISTER() is used β so like, if the constructor already did it, you're excused, go sit down.
Parameters
regβ Pointer to structrte_graph_feature_arc_register_arcβ Feature arc object
Returns
0: Success, <0: Failure
rte_graph_feature_arc_lookup_by_name()
__rte_experimental int rte_graph_feature_arc_lookup_by_name(const char * arc_name, rte_graph_feature_arc_t * _arc)
Get feature arc object with name π iconic lookup behavior, no notes.
Parameters
arc_nameβ Feature arc name provided to successfulrte_graph_feature_arc_create()_arcβ Feature arc object returned. Valid only when API returns SUCCESS
Returns
0: Success, <0: Failure.
rte_graph_feature_add()
__rte_experimental int rte_graph_feature_add(struct rte_graph_feature_register * feat_reg)
Add a feature to already created feature arc. adding features like they're stickers on a water bottle π
This API is not required in case RTE_GRAPH_FEATURE_REGISTER() is used
Parameters
feat_regβ Pointer to structrte_graph_feature_register
okay so the rules of engagement, listen up:
- Must be called before
rte_graph_create() rte_graph_feature_add()is not allowed after call torte_graph_feature_enable()so all features must be added before they can be enabled- When called by application, then
feature_node_idshould be appropriately set asfreg->feature_node_id = freg->feature_node->id;
Returns
0: Success, <0: Failure
rte_graph_feature_enable()
__rte_experimental int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char * feature_name, uint16_t app_cookie, struct rte_rcu_qsbr * qsbr)
Enable feature within a feature arc β¨
Must be called after rte_graph_create().
Parameters
_arcβ Feature arc object returned byrte_graph_feature_arc_create()orrte_graph_feature_arc_lookup_by_name()indexβ Application specific index. Can be corresponding tointerface_id/port_idetcfeature_nameβ Name of the node which is already added viarte_graph_feature_add()app_cookieβ Application specific data which is retrieved in fast pathqsbrβ RCU QSBR object. After enabling feature, API callsrte_rcu_qsbr_synchronize()followed by call to structrte_graph_feature_register::notifier_cb(), if it is set, to notify feature caller. This object can be passedNULLas well if no RCU synchronization is required
Returns
0: Success, <0: Failure
rte_graph_feature_disable()
__rte_experimental int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char * feature_name, struct rte_rcu_qsbr * qsbr)
Disable already enabled feature within a feature arc π the feature said "and scene"
Must be called after rte_graph_create(). API is NOT Thread-safe
Parameters
_arcβ Feature arc object returned byrte_graph_feature_arc_create()orrte_graph_feature_arc_lookup_by_name()indexβ Application specific index. Can be corresponding tointerface_id/port_idetcfeature_nameβ Name of the node which is already added viarte_graph_feature_add()qsbrβ RCU QSBR object. After disabling feature, API callsrte_rcu_qsbr_synchronize()followed by call to structRTE_GRAPH_FEATURE_ARC_REGISTER::notifier_cb(), if it is set, to notify feature caller. This object can be passedNULLas well if no RCU synchronization is required
Returns
0: Success, <0: Failure
rte_graph_feature_lookup()
__rte_experimental int rte_graph_feature_lookup(rte_graph_feature_arc_t arc, const char * feature_name, rte_graph_feature_t * feature)
Get rte_graph_feature_t object from feature name π
Parameters
arcβ Feature arc object returned byrte_graph_feature_arc_create()orrte_graph_feature_arc_lookup_by_name()feature_nameβ Feature name provided torte_graph_feature_add()featureβ Feature object
Returns
0: Success, <0: Failure
rte_graph_feature_arc_destroy()
__rte_experimental int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc)
Delete feature_arc object π it's giving cleanup era
Parameters
_arcβ Feature arc object returned byrte_graph_feature_arc_create()orrte_graph_feature_arc_lookup_by_name()
Returns
0: Success, <0: Failure
rte_graph_feature_arc_cleanup()
__rte_experimental int rte_graph_feature_arc_cleanup(void )
Cleanup all feature arcs π§Ή every single one, no arcs left behind
Returns
0: Success, <0: Failure
rte_graph_feature_arc_num_features()
__rte_experimental uint32_t rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc)
Slow path API to know how many features are added (NOT enabled) within a feature arc. added β enabled, queen, don't get it twisted π
Parameters
_arcβ Feature arc object
Returns
: Number of added features to arc
rte_graph_feature_arc_num_enabled_features()
__rte_experimental uint32_t rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc)
Slow path API to know how many features are currently enabled within a feature arc across all indexes. If a single feature is enabled on all interfaces, this API would return "number_of_interfaces" as count (but not "1") β okay so this one counts per-index, not per-feature, and that's the whole vibe check π¦
Parameters
_arcβ Feature arc object
Returns
: Number of enabled features across all indexes
rte_graph_feature_arc_feature_to_name()
__rte_experimental char * rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, rte_graph_feature_t feature)
Slow path API to get feature node name from rte_graph_feature_t object π·οΈ
Parameters
_arcβ Feature arc objectfeatureβ Feature object
Returns
: Name of the feature node
rte_graph_feature_arc_feature_to_node()
__rte_experimental int rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, rte_graph_feature_t feature, rte_node_t * node)
Slow path API to get corresponding rte_node_t from rte_graph_feature_t π₯
Parameters
_arcβ Feature arc objectfeatureβ Feature objectnodeβrte_node_tof feature node, Valid only when API returns SUCCESS
Returns
: 0 on success, < 0 on failure
rte_graph_feature_arc_names_get()
__rte_experimental uint32_t rte_graph_feature_arc_names_get(char * arc_names[])
Slow path API to dump valid feature arc names π
Parameters
arc_namesβ Buffer to copy the arc names. TheNULLvalue is allowed in that case, the function returns the size of the array that needs to be allocated.
Returns
When next_nodes == NULL, it returns the size of the array else number of item copied.
ngl the docs literally saynext_nodesin that Returns line even though the parameter isarc_namesπ i'm just the messenger, bestie, i kept it exactly as written
π Author π
Generated automatically by Doxygen for DPDK from the source code.
and that's a wrap on rte_graph_feature_arc.h(3), bestie!! source/version said DPDK, Version 25.11.3, and the date-side credit is the rte_graph_feature_arc.h(3) page itself β go touch some feature arcs, you ate π
β¨π«Ά
π¦ where this page comes from
- ubuntu resolute: dpdk-doc 25.11.3-0ubuntu0.26.04.1 Β· BSD-3-Clause
- ubuntu stonking: dpdk-doc 25.11.3-1 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms