From: Nitin Saxena <nsaxena@marvell.com>
To: Jerin Jacob <jerinj@marvell.com>,
Kiran Kumar K <kirankumark@marvell.com>,
Nithin Dabilpuram <ndabilpuram@marvell.com>,
Zhirun Yan <yanzhirun_163@163.com>,
Robin Jarry <rjarry@redhat.com>,
Christophe Fontaine <cfontain@redhat.com>
Cc: <dev@dpdk.org>, Nitin Saxena <nsaxena16@gmail.com>
Subject: [PATCH v6 3/4] ip4: add ip4 output feature arc
Date: Fri, 3 Jan 2025 11:36:06 +0530 [thread overview]
Message-ID: <20250103060612.2671836-4-nsaxena@marvell.com> (raw)
In-Reply-To: <20250103060612.2671836-1-nsaxena@marvell.com>
Added ip4 output arc to allow applications to hook feature nodes in ip4
egress direction
Signed-off-by: Nitin Saxena <nsaxena@marvell.com>
---
lib/node/ethdev_ctrl.c | 8 +
lib/node/interface_tx_feature.c | 133 ++++++++++++
lib/node/interface_tx_feature_priv.h | 33 +++
lib/node/ip4_rewrite.c | 298 ++++++++++++++++++++++++++-
lib/node/meson.build | 1 +
lib/node/node_private.h | 1 +
lib/node/rte_node_ip4_api.h | 4 +
7 files changed, 474 insertions(+), 4 deletions(-)
create mode 100644 lib/node/interface_tx_feature.c
create mode 100644 lib/node/interface_tx_feature_priv.h
diff --git a/lib/node/ethdev_ctrl.c b/lib/node/ethdev_ctrl.c
index cd52e8be08..93ef7fbb95 100644
--- a/lib/node/ethdev_ctrl.c
+++ b/lib/node/ethdev_ctrl.c
@@ -14,6 +14,7 @@
#include "ethdev_tx_priv.h"
#include "ip4_rewrite_priv.h"
#include "ip6_rewrite_priv.h"
+#include "interface_tx_feature_priv.h"
#include "node_private.h"
static struct ethdev_ctrl {
@@ -24,6 +25,7 @@ int
rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs,
uint16_t nb_graphs)
{
+ struct rte_node_register *if_tx_feature_node;
struct rte_node_register *ip4_rewrite_node;
struct rte_node_register *ip6_rewrite_node;
struct ethdev_tx_node_main *tx_node_data;
@@ -35,6 +37,7 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs,
int i, j, rc;
uint32_t id;
+ if_tx_feature_node = if_tx_feature_node_get();
ip4_rewrite_node = ip4_rewrite_node_get();
ip6_rewrite_node = ip6_rewrite_node_get();
tx_node_data = ethdev_tx_node_data_get();
@@ -125,6 +128,11 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf, uint16_t nb_confs,
if (rc < 0)
return rc;
+ /* Add this tx port node to if_tx_feature_node */
+ rte_node_edge_update(if_tx_feature_node->id, RTE_EDGE_ID_INVALID,
+ &next_nodes, 1);
+ rc = if_tx_feature_node_set_next(port_id,
+ rte_node_edge_count(if_tx_feature_node->id) - 1);
}
ctrl.nb_graphs = nb_graphs;
diff --git a/lib/node/interface_tx_feature.c b/lib/node/interface_tx_feature.c
new file mode 100644
index 0000000000..35ac00f21e
--- /dev/null
+++ b/lib/node/interface_tx_feature.c
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_graph_feature_arc_worker.h>
+#include <rte_malloc.h>
+
+#include "rte_node_ip4_api.h"
+#include "node_private.h"
+#include "interface_tx_feature_priv.h"
+
+#define IF_TX_FEATURE_LAST_NEXT_INDEX(ctx) \
+ (((struct if_tx_feature_node_ctx *)ctx)->last_index)
+/*
+ * @internal array for mapping port to next node index
+ */
+struct if_tx_feature_node_main {
+ uint16_t next_index[RTE_MAX_ETHPORTS];
+};
+
+struct if_tx_feature_node_ctx {
+ uint16_t last_index;
+};
+
+static struct if_tx_feature_node_main *if_tx_feature_nm;
+
+int
+if_tx_feature_node_set_next(uint16_t port_id, uint16_t next_index)
+{
+ if (if_tx_feature_nm == NULL) {
+ if_tx_feature_nm = rte_zmalloc(
+ "if_tx_feature_nm", sizeof(struct if_tx_feature_node_main),
+ RTE_CACHE_LINE_SIZE);
+ if (if_tx_feature_nm == NULL)
+ return -ENOMEM;
+ }
+ if_tx_feature_nm->next_index[port_id] = next_index;
+
+ return 0;
+}
+
+static int
+if_tx_feature_node_init(const struct rte_graph *graph, struct rte_node *node)
+{
+ RTE_SET_USED(graph);
+
+ /* pkt_drop */
+ IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx) = 0;
+
+ return 0;
+}
+
+static uint16_t
+if_tx_feature_node_process(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ uint16_t held = 0, next;
+ void **to_next, **from;
+ uint16_t last_spec = 0;
+ rte_edge_t next_index;
+ struct rte_mbuf *mbuf;
+ int i;
+
+ /* Speculative next */
+ next_index = IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx);
+
+ from = objs;
+ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
+ for (i = 0; i < nb_objs; i++) {
+
+ mbuf = (struct rte_mbuf *)objs[i];
+
+ /* port-tx node starts from next edge 1*/
+ next = if_tx_feature_nm->next_index[mbuf->port];
+
+ if (unlikely(next_index != next)) {
+ /* Copy things successfully speculated till now */
+ rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
+ from += last_spec;
+ to_next += last_spec;
+ held += last_spec;
+ last_spec = 0;
+
+ rte_node_enqueue_x1(graph, node, next, from[0]);
+ from += 1;
+ } else {
+ last_spec += 1;
+ }
+ }
+ /* !!! Home run !!! */
+ if (likely(last_spec == nb_objs)) {
+ rte_node_next_stream_move(graph, node, next_index);
+ return nb_objs;
+ }
+ held += last_spec;
+ rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
+ rte_node_next_stream_put(graph, node, next_index, held);
+
+ IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx) = next;
+
+ return nb_objs;
+}
+
+static struct rte_node_register if_tx_feature_node = {
+ .process = if_tx_feature_node_process,
+ .init = if_tx_feature_node_init,
+ .name = "interface_tx",
+ .nb_edges = 1,
+ .next_nodes = {
+ [0] = "pkt_drop",
+ },
+};
+
+struct rte_node_register *
+if_tx_feature_node_get(void)
+{
+ return &if_tx_feature_node;
+}
+
+RTE_NODE_REGISTER(if_tx_feature_node);
+
+/* if_tx feature node */
+struct rte_graph_feature_register if_tx_feature = {
+ .feature_name = RTE_IP4_OUTPUT_END_FEATURE_NAME,
+ .arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
+ .feature_process_fn = if_tx_feature_node_process,
+ .feature_node = &if_tx_feature_node,
+};
diff --git a/lib/node/interface_tx_feature_priv.h b/lib/node/interface_tx_feature_priv.h
new file mode 100644
index 0000000000..846191572d
--- /dev/null
+++ b/lib/node/interface_tx_feature_priv.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+#ifndef __INCLUDE_IF_TX_FEATURE_PRIV_H__
+#define __INCLUDE_IF_TX_FEATURE_PRIV_H__
+
+#include <rte_common.h>
+
+extern struct rte_graph_feature_register if_tx_feature;
+
+/**
+ * @internal
+ *
+ * Get the ipv4 rewrite node.
+ *
+ * @return
+ * Pointer to the ipv4 rewrite node.
+ */
+struct rte_node_register *if_tx_feature_node_get(void);
+
+/**
+ * @internal
+ *
+ * Set the Edge index of a given port_id.
+ *
+ * @param port_id
+ * Ethernet port identifier.
+ * @param next_index
+ * Edge index of the Given Tx node.
+ */
+int if_tx_feature_node_set_next(uint16_t port_id, uint16_t next_index);
+
+#endif /* __INCLUDE_INTERFCE_TX_FEATURE_PRIV_H */
diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c
index 34a920df5e..ab64aa0a3c 100644
--- a/lib/node/ip4_rewrite.c
+++ b/lib/node/ip4_rewrite.c
@@ -6,6 +6,7 @@
#include <rte_ether.h>
#include <rte_graph.h>
#include <rte_graph_worker.h>
+#include <rte_graph_feature_arc_worker.h>
#include <rte_ip.h>
#include <rte_malloc.h>
#include <rte_vect.h>
@@ -14,15 +15,27 @@
#include "ip4_rewrite_priv.h"
#include "node_private.h"
+#include "interface_tx_feature_priv.h"
+
+#ifndef RTE_IP4_OUTPUT_ARC_INDEXES
+#define RTE_IP4_OUTPUT_ARC_INDEXES RTE_MAX_ETHPORTS
+#endif
struct ip4_rewrite_node_ctx {
/* Dynamic offset to mbuf priv1 */
int mbuf_priv1_off;
+ /* Dynamic offset to feature arc field */
+ int arc_dyn_off;
/* Cached next index */
uint16_t next_index;
+ /* tx interface of last mbuf */
+ uint16_t last_tx_if;
+ /* Cached feature arc handle */
+ rte_graph_feature_arc_t output_feature_arc;
};
static struct ip4_rewrite_node_main *ip4_rewrite_nm;
+static int port_to_next_index_diff;
#define IP4_REWRITE_NODE_LAST_NEXT(ctx) \
(((struct ip4_rewrite_node_ctx *)ctx)->next_index)
@@ -30,16 +43,175 @@ static struct ip4_rewrite_node_main *ip4_rewrite_nm;
#define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \
(((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off)
-static uint16_t
-ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
- void **objs, uint16_t nb_objs)
+#define IP4_REWRITE_NODE_FEAT_OFF(ctx) \
+ (((struct ip4_rewrite_node_ctx *)ctx)->arc_dyn_off)
+
+#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \
+ (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc)
+
+#define IP4_REWRITE_NODE_LAST_TX_IF(ctx) \
+ (((struct ip4_rewrite_node_ctx *)ctx)->last_tx_if)
+
+static __rte_always_inline void
+check_output_feature_arc_x1(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
+ struct rte_mbuf *mbuf0, uint16_t *next0,
+ uint16_t *last_next_index,
+ rte_graph_feature_data_t *feature_data, const int dyn)
+{
+ struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL;
+ uint16_t port0;
+
+ /* make sure packets are not being sent to pkt_drop node */
+ if (unlikely(!(*next0)))
+ return;
+
+ port0 = (*next0) - port_to_next_index_diff;
+
+ /* get pointer to feature arc mbuf */
+ d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, dyn);
+
+ /* Check if last packet's tx port not same as current */
+ if (unlikely(*tx_if != port0)) {
+ if (unlikely(rte_graph_feature_data_first_feature_get(arc, port0,
+ &d0->feature_data))) {
+ *next0 = rte_graph_feature_data_edge_get(arc, d0->feature_data);
+ mbuf0->port = port0;
+ }
+
+ *last_next_index = *next0;
+ *tx_if = port0;
+ *feature_data = d0->feature_data;
+ } else {
+ if (unlikely(rte_graph_feature_data_is_valid(*feature_data))) {
+ *next0 = *last_next_index;
+ mbuf0->port = *tx_if;
+ d0->feature_data = *feature_data;
+ }
+ }
+}
+
+static __rte_always_inline void
+check_output_feature_arc_x4(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
+ struct rte_mbuf *mbuf0, struct rte_mbuf *mbuf1,
+ struct rte_mbuf *mbuf2, struct rte_mbuf *mbuf3,
+ uint16_t *next0, uint16_t *next1, uint16_t *next2,
+ uint16_t *next3, uint16_t *last_next_index,
+ rte_graph_feature_data_t *feature_data, const int dyn)
+{
+ struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL, *d1 = NULL, *d2 = NULL, *d3 = NULL;
+ uint16_t port0, port1, port2, port3;
+ uint16_t xor = 0;
+
+ /* If no ip4_rewrite_set_next() is called yet */
+ if (unlikely(!port_to_next_index_diff))
+ return;
+
+ /* get pointer to feature arc dyn field */
+ d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, dyn);
+ d1 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf1, dyn);
+ d2 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf2, dyn);
+ d3 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf3, dyn);
+
+ /*
+ * Check if all four packets are going to same next_index/port
+ */
+ xor = ((*tx_if) + port_to_next_index_diff) ^ (*next0);
+ xor += (*next0) ^ (*next1);
+ xor += (*next1) ^ (*next2);
+ xor += (*next2) ^ (*next3);
+
+ if (xor) {
+ /* packets tx ports are not same, check first feature for each mbuf
+ * make sure next0 != 0 which is pkt_drop
+ */
+ port0 = (*next0) - port_to_next_index_diff;
+ port1 = (*next1) - port_to_next_index_diff;
+ port2 = (*next2) - port_to_next_index_diff;
+ port3 = (*next3) - port_to_next_index_diff;
+ if (unlikely((*next0 >= port_to_next_index_diff) &&
+ rte_graph_feature_data_first_feature_get(arc, port0,
+ &d0->feature_data))) {
+ /* update next0 from feature arc */
+ *next0 = rte_graph_feature_data_edge_get(arc, d0->feature_data);
+ mbuf0->port = port0;
+
+ *tx_if = port0;
+ *last_next_index = *next0;
+ *feature_data = d0->feature_data;
+ }
+
+ if (unlikely((*next1 >= port_to_next_index_diff) &&
+ rte_graph_feature_data_first_feature_get(arc, port1,
+ &d1->feature_data))) {
+ port1 = (*next1) - port_to_next_index_diff;
+ *next1 = rte_graph_feature_data_edge_get(arc, d1->feature_data);
+ mbuf1->port = port1;
+ *tx_if = port1;
+ *last_next_index = *next1;
+ *feature_data = d1->feature_data;
+ }
+
+ if (unlikely((*next2 >= port_to_next_index_diff) &&
+ rte_graph_feature_data_first_feature_get(arc, port2,
+ &d2->feature_data))) {
+ port2 = (*next2) - port_to_next_index_diff;
+ *next2 = rte_graph_feature_data_edge_get(arc, d2->feature_data);
+ mbuf2->port = port2;
+ *tx_if = port2;
+ *last_next_index = *next2;
+ *feature_data = d2->feature_data;
+ }
+
+ if (unlikely((*next3 >= port_to_next_index_diff) &&
+ rte_graph_feature_data_first_feature_get(arc, port3,
+ &d3->feature_data))) {
+ port3 = (*next3) - port_to_next_index_diff;
+ *next3 = rte_graph_feature_data_edge_get(arc, d3->feature_data);
+ mbuf3->port = port3;
+ *tx_if = port3;
+ *last_next_index = *next3;
+ *feature_data = d3->feature_data;
+ }
+ } else {
+ /* All packets are same as last tx port. Check if feature enabled
+ * on last packet is valid or not. If invalid no need to
+ * change any next[0-3]
+ * Also check packet is not being sent to pkt_drop node
+ */
+ if (unlikely(rte_graph_feature_data_is_valid(*feature_data) &&
+ (*next0 != 0))) {
+ *next0 = *last_next_index;
+ *next1 = *last_next_index;
+ *next2 = *last_next_index;
+ *next3 = *last_next_index;
+
+ d0->feature_data = *feature_data;
+ d1->feature_data = *feature_data;
+ d2->feature_data = *feature_data;
+ d3->feature_data = *feature_data;
+
+ mbuf0->port = *tx_if;
+ mbuf1->port = *tx_if;
+ mbuf2->port = *tx_if;
+ mbuf3->port = *tx_if;
+ }
+ }
+}
+
+static __rte_always_inline uint16_t
+__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs,
+ const int dyn, const int check_enabled_features,
+ const int feat_dyn,
+ struct rte_graph_feature_arc *out_feature_arc)
{
struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh;
- const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
uint16_t next0, next1, next2, next3, next_index;
struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3;
uint16_t n_left_from, held = 0, last_spec = 0;
+ rte_graph_feature_data_t feature_data;
+ uint16_t last_tx_if, last_next_index;
void *d0, *d1, *d2, *d3;
void **to_next, **from;
rte_xmm_t priv01;
@@ -57,6 +229,27 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
for (i = 0; i < 4 && i < n_left_from; i++)
rte_prefetch0(pkts[i]);
+ if (check_enabled_features) {
+ rte_graph_feature_arc_prefetch(out_feature_arc);
+
+ last_tx_if = IP4_REWRITE_NODE_LAST_TX_IF(node->ctx);
+
+ /* If feature is enabled on last_tx_if, prefetch data
+ * corresponding to first feature
+ */
+ if (unlikely(rte_graph_feature_data_first_feature_get(out_feature_arc,
+ last_tx_if,
+ &feature_data)))
+ rte_graph_feature_arc_feature_data_prefetch(out_feature_arc,
+ feature_data);
+
+ /* Reset last_tx_if and last_next_index to call feature arc APIs
+ * for initial packets in every node loop
+ */
+ last_tx_if = UINT16_MAX;
+ last_next_index = UINT16_MAX;
+ }
+
/* Get stream for the speculated next node */
to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
/* Update Ethernet header of pkts */
@@ -78,6 +271,7 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
pkts += 4;
n_left_from -= 4;
+
priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u;
priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u;
priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u;
@@ -132,6 +326,16 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
ip3->time_to_live = priv23.u16[5] - 1;
ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7];
+ /* Once all mbufs are updated with next hop data.
+ * check if any feature is enabled to override
+ * next edges
+ */
+ if (check_enabled_features)
+ check_output_feature_arc_x4(out_feature_arc, &last_tx_if,
+ mbuf0, mbuf1, mbuf2, mbuf3,
+ &next0, &next1, &next2, &next3,
+ &last_next_index, &feature_data, feat_dyn);
+
/* Enqueue four to next node */
rte_edge_t fix_spec =
((next_index == next0) && (next0 == next1) &&
@@ -225,6 +429,11 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
ip0->hdr_checksum = chksum;
ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1;
+ if (check_enabled_features)
+ check_output_feature_arc_x1(out_feature_arc, &last_tx_if,
+ mbuf0, &next0, &last_next_index,
+ &feature_data, feat_dyn);
+
if (unlikely(next_index ^ next0)) {
/* Copy things successfully speculated till now */
rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
@@ -252,12 +461,49 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
/* Save the last next used */
IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index;
+ if (check_enabled_features)
+ IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = last_tx_if;
+
return nb_objs;
}
+static uint16_t
+ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ struct rte_graph_feature_arc *arc = NULL;
+ rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx));
+ const int feat_dyn = IP4_REWRITE_NODE_FEAT_OFF(node->ctx);
+ const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
+
+ arc = rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx));
+ if (unlikely(arc && rte_graph_feature_arc_is_any_feature_enabled(arc)))
+ return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn,
+ 1 /* check features */, feat_dyn, arc);
+
+ return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn,
+ 0/* don't check features*/,
+ 0 /* don't care */,
+ NULL /* don't care*/);
+}
+
+static uint16_t
+ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
+
+ return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn,
+ 0/* don't check features*/,
+ 0 /* don't care */,
+ NULL/* don't care */);
+}
+
+
static int
ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
{
+ rte_graph_feature_arc_t feature_arc;
static bool init_once;
RTE_SET_USED(graph);
@@ -268,9 +514,27 @@ ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
&node_mbuf_priv1_dynfield_desc);
if (node_mbuf_priv1_dynfield_offset < 0)
return -rte_errno;
+
+ /* Create ipv4-output feature arc, if not created
+ */
+ if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
+ &feature_arc) < 0) {
+ node_err("ip4_rewrite", "Feature arc \"%s\" not found",
+ RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
+ } else {
+ node_err("ip4_rewrite", "Feature arc \"%s\" found",
+ RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
+ }
+
init_once = true;
}
IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset;
+ IP4_REWRITE_NODE_FEAT_OFF(node->ctx) = rte_graph_feature_arc_mbuf_dynfield_offset_get();
+ IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc;
+
+ /* By default, set cached next node to pkt_drop */
+ IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = 0;
+ IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = 0;
node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized");
@@ -280,6 +544,8 @@ ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
int
ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
{
+ static int once;
+
if (ip4_rewrite_nm == NULL) {
ip4_rewrite_nm = rte_zmalloc(
"ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
@@ -287,6 +553,10 @@ ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
if (ip4_rewrite_nm == NULL)
return -ENOMEM;
}
+ if (!once) {
+ port_to_next_index_diff = next_index - port_id;
+ once = 1;
+ }
ip4_rewrite_nm->next_index[port_id] = next_index;
return 0;
@@ -345,3 +615,23 @@ ip4_rewrite_node_get(void)
}
RTE_NODE_REGISTER(ip4_rewrite_node);
+
+/* IP4 output arc */
+static struct rte_graph_feature_arc_register ip4_output_arc = {
+ .arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
+
+ /* This arc works on all ethdevs */
+ .max_indexes = RTE_IP4_OUTPUT_ARC_INDEXES,
+
+ .start_node = &ip4_rewrite_node,
+
+ /* overwrites start_node->process() function with following only if
+ * application calls rte_graph_feature_arc_init()
+ */
+ .start_node_feature_process_fn = ip4_rewrite_feature_node_process,
+
+ /* end feature node of an arc*/
+ .end_feature = &if_tx_feature,
+};
+
+RTE_GRAPH_FEATURE_ARC_REGISTER(ip4_output_arc);
diff --git a/lib/node/meson.build b/lib/node/meson.build
index 0bed97a96c..11e03d9ef6 100644
--- a/lib/node/meson.build
+++ b/lib/node/meson.build
@@ -24,6 +24,7 @@ sources = files(
'pkt_cls.c',
'pkt_drop.c',
'udp4_input.c',
+ 'interface_tx_feature.c'
)
headers = files(
'rte_node_eth_api.h',
diff --git a/lib/node/node_private.h b/lib/node/node_private.h
index 4fafab19be..9488df225c 100644
--- a/lib/node/node_private.h
+++ b/lib/node/node_private.h
@@ -13,6 +13,7 @@
#include <rte_mbuf_dyn.h>
#include <rte_graph_worker_common.h>
+#include <rte_graph_feature_arc_worker.h>
extern int rte_node_logtype;
#define RTE_LOGTYPE_NODE rte_node_logtype
diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h
index 950751a525..8cfae14b46 100644
--- a/lib/node/rte_node_ip4_api.h
+++ b/lib/node/rte_node_ip4_api.h
@@ -24,6 +24,10 @@
extern "C" {
#endif
+/** IP4 output arc */
+#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "rte_ip4_output_arc"
+#define RTE_IP4_OUTPUT_END_FEATURE_NAME "rte_if_tx_feature"
+
/**
* IP4 lookup next nodes.
*/
--
2.43.0
next prev parent reply other threads:[~2025-01-03 6:06 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena
2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena
2024-09-11 4:41 ` Kiran Kumar Kokkilagadda
2024-10-10 4:42 ` Nitin Saxena
2024-09-07 7:31 ` [RFC PATCH 2/3] graph: add feature arc option in graph create Nitin Saxena
2024-09-07 7:31 ` [RFC PATCH 3/3] graph: add IPv4 output feature arc Nitin Saxena
2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand
2024-10-08 14:26 ` [EXTERNAL] " Nitin Saxena
2024-10-14 11:11 ` Nitin Saxena
2024-10-16 9:24 ` David Marchand
2024-10-16 9:38 ` Robin Jarry
2024-10-16 13:50 ` Nitin Saxena
2024-10-17 7:03 ` Nitin Saxena
2024-10-17 7:50 ` Robin Jarry
2024-10-17 8:32 ` [EXTERNAL] " Christophe Fontaine
2024-10-17 10:56 ` Nitin Saxena
2024-10-17 8:48 ` [EXTERNAL] " Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 1/5] graph: add feature arc support Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 2/5] graph: add feature arc option in graph create Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 3/5] graph: add IPv4 output feature arc Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 4/5] test/graph_feature_arc: add functional tests Nitin Saxena
2024-10-08 13:30 ` [RFC PATCH v2 5/5] docs: add programming guide for feature arc Nitin Saxena
2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena
2024-10-09 13:29 ` [PATCH v3 1/5] graph: add feature arc support Nitin Saxena
2024-10-09 13:29 ` [PATCH v3 2/5] graph: add feature arc option in graph create Nitin Saxena
2024-10-09 13:30 ` [PATCH v3 3/5] graph: add IPv4 output feature arc Nitin Saxena
2024-10-09 13:30 ` [PATCH v3 4/5] test/graph_feature_arc: add functional tests Nitin Saxena
2024-10-09 13:30 ` [PATCH v3 5/5] docs: add programming guide for feature arc Nitin Saxena
2024-10-09 14:21 ` [PATCH v3 0/5] add feature arc in rte_graph Christophe Fontaine
2024-10-10 4:13 ` [EXTERNAL] " Nitin Saxena
2024-10-09 17:37 ` Stephen Hemminger
2024-10-10 4:24 ` [EXTERNAL] " Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 1/5] graph: add feature arc support Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 2/5] graph: add feature arc option in graph create Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 3/5] graph: add IPv4 output feature arc Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 4/5] test/graph_feature_arc: add functional tests Nitin Saxena
2024-10-10 13:31 ` [PATCH v4 5/5] docs: add programming guide for feature arc Nitin Saxena
2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena
2024-10-14 14:33 ` [PATCH v5 1/5] graph: add feature arc support Nitin Saxena
2024-10-14 14:33 ` [PATCH v5 2/5] graph: add feature arc option in graph create Nitin Saxena
2024-10-14 14:33 ` [PATCH v5 3/5] graph: add IPv4 output feature arc Nitin Saxena
2024-10-14 14:33 ` [PATCH v5 4/5] test/graph_feature_arc: add functional tests Nitin Saxena
2024-10-14 19:54 ` Stephen Hemminger
2024-10-14 14:33 ` [PATCH v5 5/5] docs: add programming guide for feature arc Nitin Saxena
2025-01-03 6:06 ` [PATCH v6 0/4] add feature arc in rte_graph Nitin Saxena
2025-01-03 6:06 ` [PATCH v6 1/4] graph: add API to override node process function Nitin Saxena
2025-01-03 6:06 ` [PATCH v6 2/4] graph: add feature arc abstraction Nitin Saxena
2025-01-03 6:06 ` Nitin Saxena [this message]
2025-01-03 6:06 ` [PATCH v6 4/4] app/graph: add custom feature nodes for ip4 output arc Nitin Saxena
[not found] ` <SJ0PR18MB5111B56B4323FB3DFD147801B6152@SJ0PR18MB5111.namprd18.prod.outlook.com>
2025-01-03 14:59 ` Feature arc slides Nitin Saxena
2025-01-06 0:15 ` Stephen Hemminger
2025-01-07 12:37 ` Nitin Saxena
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250103060612.2671836-4-nsaxena@marvell.com \
--to=nsaxena@marvell.com \
--cc=cfontain@redhat.com \
--cc=dev@dpdk.org \
--cc=jerinj@marvell.com \
--cc=kirankumark@marvell.com \
--cc=ndabilpuram@marvell.com \
--cc=nsaxena16@gmail.com \
--cc=rjarry@redhat.com \
--cc=yanzhirun_163@163.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).