DPDK patches and discussions
 help / color / mirror / Atom feed
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 4/4] app/graph: add custom feature nodes for ip4 output arc
Date: Fri, 3 Jan 2025 11:36:07 +0530	[thread overview]
Message-ID: <20250103060612.2671836-5-nsaxena@marvell.com> (raw)
In-Reply-To: <20250103060612.2671836-1-nsaxena@marvell.com>

- Added cmdline argument "--enable-graph-feature-arc" to call
  rte_graph_feature_arc_init() before rte_graph_create() which creates
  in-built arcs and feature nodes
- Added custom feature nodes in app/graph which are added to ip4 output
  arc.
- Custom features can be enabled/disabled at runtime on any ethdev via
  CLI.

graph> help feature
graph> feature enable <arc name> <feature name> <port-id>
graph> feature disable <arc name> <feature name> <port-id>
graph> graph stats show

Signed-off-by: Nitin Saxena <nsaxena@marvell.com>
---
 app/graph/commands.list     |   6 ++
 app/graph/feature.c         | 141 ++++++++++++++++++++++++++++++
 app/graph/feature.h         |  13 +++
 app/graph/graph.c           |   4 +
 app/graph/ip4_output_hook.c | 169 ++++++++++++++++++++++++++++++++++++
 app/graph/main.c            |  15 +++-
 app/graph/meson.build       |   2 +
 app/graph/module_api.h      |   2 +
 8 files changed, 351 insertions(+), 1 deletion(-)
 create mode 100644 app/graph/feature.c
 create mode 100644 app/graph/feature.h
 create mode 100644 app/graph/ip4_output_hook.c

diff --git a/app/graph/commands.list b/app/graph/commands.list
index c027f73b0e..49d81f50ae 100644
--- a/app/graph/commands.list
+++ b/app/graph/commands.list
@@ -31,3 +31,9 @@ help ipv6_lookup                                         # Print help on ipv6_lo
 neigh add ipv4 <IPv4>ip <STRING>mac                      # Add static neighbour for IPv4
 neigh add ipv6 <IPv6>ip <STRING>mac                      # Add static neighbour for IPv6
 help neigh                                               # Print help on neigh commands
+
+feature arcs                                             # show all feature arcs
+feature <STRING>name show                                # Show feature arc details
+feature enable <STRING>arc_name <STRING>feature_name <UINT16>interface   # Enable feature on interface
+feature disable <STRING>arc_name <STRING>feature_name <UINT16>interface  # Disable feature on interface
+help feature                                             # Print help on feature command
diff --git a/app/graph/feature.c b/app/graph/feature.c
new file mode 100644
index 0000000000..2cf21b11ce
--- /dev/null
+++ b/app/graph/feature.c
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_socket.h>
+#include <rte_ethdev.h>
+
+#include "module_api.h"
+
+static const char
+cmd_feature_arcs_help[] = "feature arcs    # Display all feature arcs";
+
+static const char
+cmd_feature_show_help[] = "feature <arc_name> show   # Display features within an arc";
+
+static const char
+cmd_feature_enable_help[] = "feature enable <arc name> <feature name> <port-id>";
+
+static const char
+cmd_feature_disable_help[] = "feature disable <arc name> <feature name> <port-id>";
+
+static void
+feature_show(const char *arc_name)
+{
+	rte_graph_feature_arc_t _arc;
+	uint32_t length, count, i;
+
+	length = strlen(conn->msg_out);
+	conn->msg_out += length;
+
+	if (rte_graph_feature_arc_lookup_by_name(arc_name, &_arc) < 0)
+		return;
+
+	count = rte_graph_feature_arc_num_features(_arc);
+
+	if (count) {
+		snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s%s%s\n",
+			 "----------------------------- feature arc: ",
+			 rte_graph_feature_arc_get(_arc)->feature_arc_name,
+			 " -----------------------------");
+		for (i = 0; i < count; i++)
+			snprintf(conn->msg_out + strlen(conn->msg_out),
+				 conn->msg_out_len_max, "%s\n",
+				 rte_graph_feature_arc_feature_to_name(_arc, i));
+	}
+	length = strlen(conn->msg_out);
+	conn->msg_out_len_max -= length;
+}
+
+static void
+feature_arcs_show(void)
+{
+	uint32_t length, count, i;
+	char **names;
+
+	length = strlen(conn->msg_out);
+	conn->msg_out += length;
+
+	count = rte_graph_feature_arc_names_get(NULL);
+
+	if (count) {
+		names = malloc(count);
+		if (!names) {
+			snprintf(conn->msg_out, conn->msg_out_len_max, "Failed to allocate memory\n");
+			return;
+		}
+		count = rte_graph_feature_arc_names_get(names);
+		snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n",
+			 "----------------------------- feature arcs -----------------------------");
+		for (i = 0; i < count; i++)
+			feature_show(names[i]);
+		free(names);
+	}
+	length = strlen(conn->msg_out);
+	conn->msg_out_len_max -= length;
+}
+
+void
+cmd_feature_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
+		   __rte_unused void *data)
+{
+	struct cmd_feature_result *res = parsed_result;
+
+	feature_show(res->name);
+}
+
+
+void
+cmd_feature_arcs_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
+			__rte_unused void *data)
+{
+		feature_arcs_show();
+}
+
+void
+cmd_feature_enable_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
+			  __rte_unused void *data)
+{
+	struct cmd_feature_enable_result *res = parsed_result;
+	rte_graph_feature_arc_t arc;
+
+	if (!rte_graph_feature_arc_lookup_by_name(res->arc_name, &arc))
+		rte_graph_feature_enable(arc, res->interface, res->feature_name,
+					 res->interface, NULL);
+}
+
+void
+cmd_feature_disable_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
+			   __rte_unused void *data)
+{
+	struct cmd_feature_disable_result *res = parsed_result;
+	rte_graph_feature_arc_t arc;
+
+	if (!rte_graph_feature_arc_lookup_by_name(res->arc_name, &arc))
+		rte_graph_feature_disable(arc, res->interface, res->feature_name, NULL);
+
+}
+
+void
+cmd_help_feature_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
+			__rte_unused void *data)
+{
+	size_t len;
+
+	len = strlen(conn->msg_out);
+	conn->msg_out += len;
+	snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n%s\n%s\n",
+		 "----------------------------- feature command help -----------------------------",
+		 cmd_feature_arcs_help, cmd_feature_show_help, cmd_feature_enable_help,
+		 cmd_feature_disable_help);
+
+	len = strlen(conn->msg_out);
+	conn->msg_out_len_max -= len;
+}
diff --git a/app/graph/feature.h b/app/graph/feature.h
new file mode 100644
index 0000000000..76393dabc6
--- /dev/null
+++ b/app/graph/feature.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#ifndef APP_GRAPH_FEATURE_H
+#define APP_GRAPH_FEATURE_H
+
+#include <cmdline_parse.h>
+#include <rte_graph_feature_arc_worker.h>
+
+int feature_enable(const char *arc_name, const char *feature_name, uint16_t portid);
+int feature_disable(const char *arc_name, const char *feature_name, uint16_t portid);
+#endif
diff --git a/app/graph/graph.c b/app/graph/graph.c
index 3af031cbaf..3ccd702ed9 100644
--- a/app/graph/graph.c
+++ b/app/graph/graph.c
@@ -12,6 +12,7 @@
 #include <cmdline_socket.h>
 #include <rte_ethdev.h>
 #include <rte_graph_worker.h>
+#include <rte_graph_feature_arc_worker.h>
 #include <rte_log.h>
 
 #include "graph_priv.h"
@@ -265,6 +266,9 @@ cmd_graph_start_parsed(__rte_unused void *parsed_result, __rte_unused struct cmd
 	uint32_t nb_graphs = 0, nb_conf, i;
 	int rc = -EINVAL;
 
+	if (app_graph_feature_arc_enabled())
+		rte_graph_feature_arc_init();
+
 	conf = graph_rxtx_node_config_get(&nb_conf, &nb_graphs);
 	for (i = 0; i < MAX_GRAPH_USECASES; i++) {
 		if (!strcmp(graph_config.usecases[i].name, "l3fwd")) {
diff --git a/app/graph/ip4_output_hook.c b/app/graph/ip4_output_hook.c
new file mode 100644
index 0000000000..1a389f1113
--- /dev/null
+++ b/app/graph/ip4_output_hook.c
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#include <rte_graph.h>
+#include <rte_graph_worker.h>
+#include <rte_graph_feature_arc_worker.h>
+
+#include "rte_node_ip4_api.h"
+
+#define IP4_OUTPUT_HOOK_FEATURE1_NAME "app_graph_ip4_output_hook_f1"
+#define IP4_OUTPUT_HOOK_FEATURE2_NAME "app_graph_ip4_output_hook_f2"
+
+struct output_hook_node_ctx {
+	rte_graph_feature_arc_t out_arc;
+	uint16_t last_index;
+};
+
+#define OUTPUT_HOOK_FEATURE_ARC(ctx) \
+	(((struct output_hook_node_ctx *)ctx)->out_arc)
+
+#define OUTPUT_HOOK_LAST_NEXT_INDEX(ctx) \
+	(((struct output_hook_node_ctx *)ctx)->last_index)
+
+static int
+__app_graph_ip4_output_hook_node_init(const struct rte_graph *graph, struct rte_node *node)
+{
+	rte_graph_feature_arc_t feature;
+
+	RTE_SET_USED(graph);
+
+	rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, &feature);
+
+	OUTPUT_HOOK_FEATURE_ARC(node->ctx) = feature;
+	/* pkt_drop */
+	OUTPUT_HOOK_LAST_NEXT_INDEX(node->ctx) = 0;
+
+	return 0;
+}
+
+static __rte_always_inline uint16_t
+__app_graph_ip4_output_hook_node_process(struct rte_graph *graph, struct rte_node *node,
+					 void **objs, uint16_t nb_objs)
+{
+	struct rte_graph_feature_arc *arc =
+		rte_graph_feature_arc_get(OUTPUT_HOOK_FEATURE_ARC(node->ctx));
+	int feat_dyn_off = rte_graph_feature_arc_mbuf_dynfield_offset_get();
+	struct rte_graph_feature_arc_mbuf_dynfields *mbfields = NULL;
+	rte_graph_feature_data_t fdata;
+	void **to_next, **from;
+	uint16_t last_spec = 0;
+	rte_edge_t next_index;
+	struct rte_mbuf *mbuf;
+	uint16_t held = 0;
+	uint16_t next;
+	int i;
+
+	/* Speculative next */
+	next_index = OUTPUT_HOOK_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];
+
+		/* Send mbuf to next enabled feature */
+		mbfields = rte_graph_feature_arc_mbuf_dynfields_get(mbuf, feat_dyn_off);
+		fdata = rte_graph_feature_data_next_feature_get(arc, mbfields->feature_data);
+		next = rte_graph_feature_data_edge_get(arc, fdata);
+
+		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);
+	OUTPUT_HOOK_LAST_NEXT_INDEX(node->ctx) = next;
+
+	return nb_objs;
+}
+
+static int
+app_graph_ip4_output_hook_node1_init(const struct rte_graph *graph, struct rte_node *node)
+{
+	return __app_graph_ip4_output_hook_node_init(graph, node);
+}
+
+static __rte_always_inline uint16_t
+app_graph_ip4_output_hook_node1_process(struct rte_graph *graph, struct rte_node *node,
+					void **objs, uint16_t nb_objs)
+{
+	return __app_graph_ip4_output_hook_node_process(graph, node, objs, nb_objs);
+}
+
+static struct rte_node_register app_graph_ip4_output_hook_node1 = {
+	.process = app_graph_ip4_output_hook_node1_process,
+	.init = app_graph_ip4_output_hook_node1_init,
+	.name = "app_graph_ip4_output_hook_node1",
+	.nb_edges = 1,
+	.next_nodes = {
+		[0] = "pkt_drop",
+	},
+};
+
+RTE_NODE_REGISTER(app_graph_ip4_output_hook_node1);
+
+static int
+app_graph_ip4_output_hook_node2_init(const struct rte_graph *graph, struct rte_node *node)
+{
+	return __app_graph_ip4_output_hook_node_init(graph, node);
+}
+
+static __rte_always_inline uint16_t
+app_graph_ip4_output_hook_node2_process(struct rte_graph *graph, struct rte_node *node,
+					void **objs, uint16_t nb_objs)
+{
+	return __app_graph_ip4_output_hook_node_process(graph, node, objs, nb_objs);
+}
+
+static struct rte_node_register app_graph_ip4_output_hook_node2 = {
+	.process = app_graph_ip4_output_hook_node2_process,
+	.init = app_graph_ip4_output_hook_node2_init,
+	.name = "app_graph_ip4_output_hook_node2",
+	.nb_edges = 1,
+	.next_nodes = {
+		[0] = "pkt_drop",
+	},
+};
+
+RTE_NODE_REGISTER(app_graph_ip4_output_hook_node2);
+
+/* if feature1 */
+struct rte_graph_feature_register app_graph_ip4_output_hook_feature1 = {
+	.feature_name = IP4_OUTPUT_HOOK_FEATURE1_NAME,
+	.arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
+	/* Same as regular function */
+	.feature_process_fn = app_graph_ip4_output_hook_node1_process,
+	.feature_node = &app_graph_ip4_output_hook_node1,
+	.runs_before =  IP4_OUTPUT_HOOK_FEATURE2_NAME,
+};
+
+/* if feature2 (same as f1) */
+struct rte_graph_feature_register app_graph_ip4_output_hook_feature2 = {
+	.feature_name = IP4_OUTPUT_HOOK_FEATURE2_NAME,
+	.arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
+	/* Same as regular function */
+	.feature_node = &app_graph_ip4_output_hook_node2,
+	.feature_process_fn = app_graph_ip4_output_hook_node2_process,
+};
+
+RTE_GRAPH_FEATURE_REGISTER(app_graph_ip4_output_hook_feature1);
+RTE_GRAPH_FEATURE_REGISTER(app_graph_ip4_output_hook_feature2);
diff --git a/app/graph/main.c b/app/graph/main.c
index 465376425c..56294f2693 100644
--- a/app/graph/main.c
+++ b/app/graph/main.c
@@ -28,6 +28,7 @@ static struct app_params {
 	struct conn_params conn;
 	char *script_name;
 	bool enable_graph_stats;
+	bool enable_feature_arc;
 } app = {
 	.conn = {
 		.welcome = "\nWelcome!\n\n",
@@ -42,6 +43,7 @@ static struct app_params {
 	},
 	.script_name = NULL,
 	.enable_graph_stats = false,
+	.enable_feature_arc = false,
 };
 
 static void
@@ -59,6 +61,7 @@ app_args_parse(int argc, char **argv)
 	struct option lgopts[] = {
 		{"help", 0, 0, 'H'},
 		{"enable-graph-stats", 0, 0, 'g'},
+		{"enable-graph-feature-arc", 0, 0, 'f'},
 	};
 	int h_present, p_present, s_present, n_args, i;
 	char *app_name = argv[0];
@@ -81,7 +84,7 @@ app_args_parse(int argc, char **argv)
 	p_present = 0;
 	s_present = 0;
 
-	while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) != EOF) {
+	while ((opt = getopt_long(argc, argv, "h:p:s:f", lgopts, &option_index)) != EOF) {
 		switch (opt) {
 		case 'h':
 			if (h_present) {
@@ -142,6 +145,10 @@ app_args_parse(int argc, char **argv)
 			       "--enable-graph-stats");
 			break;
 
+		case 'f':
+			app.enable_feature_arc = true;
+			break;
+
 		case 'H':
 		default:
 			printf(usage, app_name);
@@ -159,6 +166,12 @@ app_graph_stats_enabled(void)
 	return app.enable_graph_stats;
 }
 
+bool
+app_graph_feature_arc_enabled(void)
+{
+	return app.enable_feature_arc;
+}
+
 bool
 app_graph_exit(void)
 {
diff --git a/app/graph/meson.build b/app/graph/meson.build
index 344e4a418f..d7e8c431ea 100644
--- a/app/graph/meson.build
+++ b/app/graph/meson.build
@@ -24,6 +24,8 @@ sources = files(
         'mempool.c',
         'neigh.c',
         'utils.c',
+        'feature.c',
+        'ip4_output_hook.c'
 )
 
 cmd_h = custom_target('commands_hdr',
diff --git a/app/graph/module_api.h b/app/graph/module_api.h
index b872872dc1..25f88e28de 100644
--- a/app/graph/module_api.h
+++ b/app/graph/module_api.h
@@ -20,6 +20,7 @@
 #include "neigh.h"
 #include "route.h"
 #include "utils.h"
+#include "feature.h"
 
 /*
  * Externs
@@ -28,6 +29,7 @@ extern volatile bool force_quit;
 extern struct conn *conn;
 
 bool app_graph_stats_enabled(void);
+bool app_graph_feature_arc_enabled(void);
 bool app_graph_exit(void);
 
 #endif
-- 
2.43.0


  parent reply	other threads:[~2025-01-03  6:07 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           ` [PATCH v6 3/4] ip4: add ip4 output feature arc Nitin Saxena
2025-01-03  6:06           ` Nitin Saxena [this message]
     [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-5-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).