* [RFC PATCH 0/2] Add jump flow support and queue menegment with new snippets
@ 2025-06-24 7:15 Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 1/2] examples/flow_filtering: add match port affinity snippet Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 2/2] examples/flow_filtering: add jump flow Shani Peretz
0 siblings, 2 replies; 3+ messages in thread
From: Shani Peretz @ 2025-06-24 7:15 UTC (permalink / raw)
To: dev; +Cc: Shani Peretz
This patch series adds port affinity matching for bonded ports and
refactors queue management to support the new port affinity snippets.
This refactoring also enables other snippets that require access to
the queue number to utilize it more easily.
It also introduces support for jumping to specific flow groups,
with three new snippets demonstrating this feature.
Shani Peretz (2):
examples/flow_filtering: add match port affinity snippet
examples/flow_filtering: add jump flow
examples/flow_filtering/common.h | 2 +
examples/flow_filtering/flow_skeleton.c | 2 +-
examples/flow_filtering/jump_flow.c | 40 +++++++
examples/flow_filtering/jump_flow.h | 13 +++
examples/flow_filtering/main.c | 9 +-
examples/flow_filtering/meson.build | 5 +
.../snippets/snippet_match_gre.c | 2 +-
.../snippets/snippet_match_gre.h | 2 +-
.../snippets/snippet_match_ipv4.c | 4 +-
.../snippets/snippet_match_ipv4.h | 2 +-
.../snippets/snippet_match_mpls.c | 2 +-
.../snippets/snippet_match_mpls.h | 2 +-
.../snippets/snippet_match_nsh.c | 74 ++++++++++++
.../snippets/snippet_match_nsh.h | 36 ++++++
.../snippets/snippet_match_port_affinity.c | 110 ++++++++++++++++++
.../snippets/snippet_match_port_affinity.h | 39 +++++++
.../snippets/snippet_match_roce_ib_bth.c | 69 +++++++++++
.../snippets/snippet_match_roce_ib_bth.h | 35 ++++++
.../snippets/snippet_re_route_to_kernel.c | 3 +-
.../snippets/snippet_re_route_to_kernel.h | 2 +-
.../snippets/snippet_switch_granularity.c | 55 +++++++++
.../snippets/snippet_switch_granularity.h | 36 ++++++
22 files changed, 529 insertions(+), 15 deletions(-)
create mode 100644 examples/flow_filtering/jump_flow.c
create mode 100644 examples/flow_filtering/jump_flow.h
create mode 100644 examples/flow_filtering/snippets/snippet_match_nsh.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_nsh.h
create mode 100644 examples/flow_filtering/snippets/snippet_match_port_affinity.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_port_affinity.h
create mode 100644 examples/flow_filtering/snippets/snippet_match_roce_ib_bth.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_roce_ib_bth.h
create mode 100644 examples/flow_filtering/snippets/snippet_switch_granularity.c
create mode 100644 examples/flow_filtering/snippets/snippet_switch_granularity.h
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/2] examples/flow_filtering: add match port affinity snippet
2025-06-24 7:15 [RFC PATCH 0/2] Add jump flow support and queue menegment with new snippets Shani Peretz
@ 2025-06-24 7:15 ` Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 2/2] examples/flow_filtering: add jump flow Shani Peretz
1 sibling, 0 replies; 3+ messages in thread
From: Shani Peretz @ 2025-06-24 7:15 UTC (permalink / raw)
To: dev; +Cc: Shani Peretz, Ori Kam
This snippet demonstrates port affinity matching in bonded ports,
ensuring packets are sent back through their ingress port.
The NR_QUEUES constant was moved to common.h to support mapping
four TX queues (0-3) to two port affinities (0,1→1 and 2,3→2).
Signed-off-by: Shani Peretz <shperetz@nvidia.com>
---
examples/flow_filtering/common.h | 2 +
examples/flow_filtering/flow_skeleton.c | 2 +-
examples/flow_filtering/main.c | 9 +-
examples/flow_filtering/meson.build | 1 +
.../snippets/snippet_match_gre.c | 2 +-
.../snippets/snippet_match_gre.h | 2 +-
.../snippets/snippet_match_ipv4.c | 4 +-
.../snippets/snippet_match_ipv4.h | 2 +-
.../snippets/snippet_match_mpls.c | 2 +-
.../snippets/snippet_match_mpls.h | 2 +-
.../snippets/snippet_match_port_affinity.c | 110 ++++++++++++++++++
.../snippets/snippet_match_port_affinity.h | 39 +++++++
.../snippets/snippet_re_route_to_kernel.c | 3 +-
.../snippets/snippet_re_route_to_kernel.h | 2 +-
14 files changed, 167 insertions(+), 15 deletions(-)
create mode 100644 examples/flow_filtering/snippets/snippet_match_port_affinity.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_port_affinity.h
diff --git a/examples/flow_filtering/common.h b/examples/flow_filtering/common.h
index 3a73520723..9d579aff74 100644
--- a/examples/flow_filtering/common.h
+++ b/examples/flow_filtering/common.h
@@ -5,6 +5,8 @@
#ifndef COMMON_H
#define COMMON_H
+#define NR_QUEUES 4
+
extern bool enable_promiscuous_mode;
extern bool enable_flow_isolation;
extern struct rte_flow_attr flow_attr;
diff --git a/examples/flow_filtering/flow_skeleton.c b/examples/flow_filtering/flow_skeleton.c
index 471302d8b3..7e57b13b55 100644
--- a/examples/flow_filtering/flow_skeleton.c
+++ b/examples/flow_filtering/flow_skeleton.c
@@ -59,7 +59,7 @@ generate_flow_skeleton(uint16_t port_id, struct rte_flow_error *error, int use_t
struct rte_flow_action actions[MAX_ACTION_NUM] = {0};
struct rte_flow_item patterns[MAX_PATTERN_NUM] = {0};
- snippet_skeleton_flow_create_actions(actions);
+ snippet_skeleton_flow_create_actions(port_id, actions);
snippet_skeleton_flow_create_patterns(patterns);
/* >8 End of setting the common action and pattern structures. */
diff --git a/examples/flow_filtering/main.c b/examples/flow_filtering/main.c
index 13ad17a712..8ea6596ed4 100644
--- a/examples/flow_filtering/main.c
+++ b/examples/flow_filtering/main.c
@@ -40,7 +40,6 @@ static int use_template_api = 1;
static volatile bool force_quit;
static uint16_t port_id;
-static uint16_t nr_queues = 5;
struct rte_mempool *mbuf_pool;
struct rte_flow *flow;
@@ -67,7 +66,7 @@ main_loop(void)
/* Reading the packets from all queues. */
while (!force_quit) {
- for (i = 0; i < nr_queues; i++) {
+ for (i = 0; i < NR_QUEUES; i++) {
nb_rx = rte_eth_rx_burst(port_id,
i, mbufs, 32);
if (nb_rx) {
@@ -179,7 +178,7 @@ init_port(void)
port_conf.txmode.offloads &= dev_info.tx_offload_capa;
printf(":: initializing port: %d\n", port_id);
ret = rte_eth_dev_configure(port_id,
- nr_queues, nr_queues, &port_conf);
+ NR_QUEUES, NR_QUEUES, &port_conf);
if (ret < 0) {
rte_exit(EXIT_FAILURE,
":: cannot configure device: err=%d, port=%u\n",
@@ -190,7 +189,7 @@ init_port(void)
rxq_conf.offloads = port_conf.rxmode.offloads;
/* Configuring number of RX and TX queues connected to single port. */
- for (i = 0; i < nr_queues; i++) {
+ for (i = 0; i < NR_QUEUES; i++) {
ret = rte_eth_rx_queue_setup(port_id, i, 512,
rte_eth_dev_socket_id(port_id),
&rxq_conf,
@@ -205,7 +204,7 @@ init_port(void)
txq_conf = dev_info.default_txconf;
txq_conf.offloads = port_conf.txmode.offloads;
- for (i = 0; i < nr_queues; i++) {
+ for (i = 0; i < NR_QUEUES; i++) {
ret = rte_eth_tx_queue_setup(port_id, i, 512,
rte_eth_dev_socket_id(port_id),
&txq_conf);
diff --git a/examples/flow_filtering/meson.build b/examples/flow_filtering/meson.build
index 6413dbc947..3be2bb1ef5 100644
--- a/examples/flow_filtering/meson.build
+++ b/examples/flow_filtering/meson.build
@@ -15,6 +15,7 @@ sources = files(
'snippets/snippet_match_ipv4.c',
'snippets/snippet_match_gre.c',
'snippets/snippet_match_mpls.c',
+ 'snippets/snippet_match_port_affinity.c',
'snippets/snippet_re_route_to_kernel.c',
)
diff --git a/examples/flow_filtering/snippets/snippet_match_gre.c b/examples/flow_filtering/snippets/snippet_match_gre.c
index b1d6edaad0..8c290328ec 100644
--- a/examples/flow_filtering/snippets/snippet_match_gre.c
+++ b/examples/flow_filtering/snippets/snippet_match_gre.c
@@ -15,7 +15,7 @@ snippet_init_gre(void)
}
static void
-snippet_match_gre_create_actions(struct rte_flow_action *action)
+snippet_match_gre_create_actions(__rte_unused uint16_t port_id, struct rte_flow_action *action)
{
/* Create one action that moves the packet to the selected queue. */
struct rte_flow_action_queue *queue = calloc(1, sizeof(struct rte_flow_action_queue));
diff --git a/examples/flow_filtering/snippets/snippet_match_gre.h b/examples/flow_filtering/snippets/snippet_match_gre.h
index 25f9fd5dd8..11054ba144 100644
--- a/examples/flow_filtering/snippets/snippet_match_gre.h
+++ b/examples/flow_filtering/snippets/snippet_match_gre.h
@@ -19,7 +19,7 @@ snippet_init_gre(void);
#define snippet_init snippet_init_gre
static void
-snippet_match_gre_create_actions(struct rte_flow_action *action);
+snippet_match_gre_create_actions(uint16_t port_id, struct rte_flow_action *action);
#define snippet_skeleton_flow_create_actions snippet_match_gre_create_actions
static void
diff --git a/examples/flow_filtering/snippets/snippet_match_ipv4.c b/examples/flow_filtering/snippets/snippet_match_ipv4.c
index 4082dc660d..7f8aba66bb 100644
--- a/examples/flow_filtering/snippets/snippet_match_ipv4.c
+++ b/examples/flow_filtering/snippets/snippet_match_ipv4.c
@@ -7,8 +7,8 @@
#include <rte_errno.h>
#include <rte_flow.h>
-#include "snippet_match_ipv4.h"
#include "../common.h"
+#include "snippet_match_ipv4.h"
void
snippet_init_ipv4(void)
@@ -17,7 +17,7 @@ snippet_init_ipv4(void)
}
void
-snippet_ipv4_flow_create_actions(struct rte_flow_action *action)
+snippet_ipv4_flow_create_actions(__rte_unused uint16_t port_id, struct rte_flow_action *action)
{
/*
* create the action sequence.
diff --git a/examples/flow_filtering/snippets/snippet_match_ipv4.h b/examples/flow_filtering/snippets/snippet_match_ipv4.h
index 8d169589b0..93f284ad23 100644
--- a/examples/flow_filtering/snippets/snippet_match_ipv4.h
+++ b/examples/flow_filtering/snippets/snippet_match_ipv4.h
@@ -17,7 +17,7 @@ snippet_init_ipv4(void);
#define snippet_init snippet_init_ipv4
void
-snippet_ipv4_flow_create_actions(struct rte_flow_action *action);
+snippet_ipv4_flow_create_actions(uint16_t port_id, struct rte_flow_action *action);
#define snippet_skeleton_flow_create_actions snippet_ipv4_flow_create_actions
void
diff --git a/examples/flow_filtering/snippets/snippet_match_mpls.c b/examples/flow_filtering/snippets/snippet_match_mpls.c
index df499fcdb7..494a2d873d 100644
--- a/examples/flow_filtering/snippets/snippet_match_mpls.c
+++ b/examples/flow_filtering/snippets/snippet_match_mpls.c
@@ -19,7 +19,7 @@ snippet_init_mpls(void)
}
static void
-snippet_mpls_create_actions(struct rte_flow_action *actions)
+snippet_mpls_create_actions(__rte_unused uint16_t port_id, struct rte_flow_action *actions)
{
/* Create one action that moves the packet to the selected queue. */
struct rte_flow_action_queue *queue;
diff --git a/examples/flow_filtering/snippets/snippet_match_mpls.h b/examples/flow_filtering/snippets/snippet_match_mpls.h
index ed08b736eb..791e96efa1 100644
--- a/examples/flow_filtering/snippets/snippet_match_mpls.h
+++ b/examples/flow_filtering/snippets/snippet_match_mpls.h
@@ -19,7 +19,7 @@ snippet_init_mpls(void);
#define snippet_init snippet_init_mpls
static void
-snippet_mpls_create_actions(struct rte_flow_action *actions);
+snippet_mpls_create_actions(uint16_t port_id, struct rte_flow_action *actions);
#define snippet_skeleton_flow_create_actions snippet_mpls_create_actions
static void
diff --git a/examples/flow_filtering/snippets/snippet_match_port_affinity.c b/examples/flow_filtering/snippets/snippet_match_port_affinity.c
new file mode 100644
index 0000000000..8d946ec797
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_port_affinity.c
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#include <stdlib.h>
+#include <rte_flow.h>
+
+#include "../common.h"
+#include "snippet_match_port_affinity.h"
+
+void
+snippet_init_match_port_affinity(void)
+{
+ init_default_snippet();
+}
+
+static void
+map_tx_queue_to_aggregated_port(uint16_t port_id)
+{
+ int ret;
+ uint16_t queues[] = {0, 1, 2, 3};
+ uint16_t affinities[] = {1, 1, 2, 2};
+ int i;
+
+ ret = rte_eth_dev_stop(port_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_dev_stop:err=%d, port=%u\n",
+ ret, port_id);
+
+ ret = rte_eth_dev_count_aggr_ports(port_id);
+ if (ret < 0) {
+ printf("Failed to count the aggregated ports: (%s)\n",
+ strerror(-ret));
+ return;
+ }
+
+ /* Configure TxQ index 0,1 with tx affinity 1 and TxQ index 2,3 with tx affinity 2 */
+ for (i = 0; i < NR_QUEUES; i++) {
+ ret = rte_eth_dev_map_aggr_tx_affinity(port_id, queues[i], affinities[i]);
+ if (ret != 0) {
+ printf("Failed to map tx queue with an aggregated port: %s\n",
+ rte_strerror(-ret));
+ return;
+ }
+ printf(":: tx queue %d mapped to aggregated port %d with affinity %d\n",
+ queues[i], port_id, affinities[i]);
+ }
+
+ ret = rte_eth_dev_start(port_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_dev_start:err=%d, port=%u\n",
+ ret, port_id);
+}
+
+void
+snippet_match_port_affinity_create_actions(uint16_t port_id, struct rte_flow_action *action)
+{
+ /* Configure affinity in TxQ */
+ map_tx_queue_to_aggregated_port(port_id);
+
+ struct rte_flow_action_queue *queue = calloc(1, sizeof(struct rte_flow_action_queue));
+ if (queue == NULL) {
+ printf("Failed to allocate memory for queue\n");
+ return;
+ }
+ queue->index = 1;
+ /* Create the Queue action. */
+ action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+ action[0].conf = queue;
+ action[1].type = RTE_FLOW_ACTION_TYPE_END;
+}
+
+void
+snippet_match_port_affinity_create_patterns(struct rte_flow_item *pattern)
+{
+ struct rte_flow_item_aggr_affinity *affinity_spec =
+ calloc(1, sizeof(struct rte_flow_item_aggr_affinity));
+ if (affinity_spec == NULL) {
+ fprintf(stderr, "Failed to allocate memory for affinity_spec\n");
+ return;
+ }
+
+ struct rte_flow_item_aggr_affinity *affinity_mask =
+ calloc(1, sizeof(struct rte_flow_item_aggr_affinity));
+ if (affinity_mask == NULL) {
+ fprintf(stderr, "Failed to allocate memory for affinity_mask\n");
+ return;
+ }
+
+ affinity_spec->affinity = 2; /* Set the request affinity value. */
+ affinity_mask->affinity = 0xff; /* Set the mask for the affinity value. */
+
+ /* Create a rule that matches the port affinity values */
+ pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ // pattern[0].spec = eth;
+ // pattern[0].mask = NULL;
+ pattern[1].type = RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY;
+ pattern[1].spec = affinity_spec;
+ pattern[1].mask = affinity_mask;
+ pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+}
+
+struct rte_flow_template_table *
+snippet_match_port_affinity_create_table(__rte_unused uint16_t port_id,
+ __rte_unused struct rte_flow_error *error)
+{
+ return NULL;
+}
diff --git a/examples/flow_filtering/snippets/snippet_match_port_affinity.h b/examples/flow_filtering/snippets/snippet_match_port_affinity.h
new file mode 100644
index 0000000000..5e9f032763
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_port_affinity.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef SNIPPET_MATCH_PORT_AFFINITY_H
+#define SNIPPET_MATCH_PORT_AFFINITY_H
+
+/* Port Affinity Match
+ * indicates in the DPDK level the physical port a packet belongs to.
+ * This capability is available by using a new pattern item type for aggregated port affinity,
+ * its value reflects the physical port affinity of the received packets.
+ * Additionally, the tx_affinity setting was added by calling rte_eth_dev_map_aggr_tx_affinity(),
+ * its value reflects the physical port the packets will be sent to.
+ * This new capability is enables the app to receive the ingress port of a packet,
+ * and send the ACK out on the same port when dual ports devices are configured as a bond in Linux.
+ * This feature is used in conjunction with link aggregation, also known as port bonding,
+ * where multiple physical ports are combined into a single logical interface.
+ */
+
+#define MAX_PATTERN_NUM 3 /* Maximal number of patterns for this example. */
+#define MAX_ACTION_NUM 2 /* Maximal number of actions for this example. */
+
+void
+snippet_init_match_port_affinity(void);
+#define snippet_init snippet_init_match_port_affinity
+
+void
+snippet_match_port_affinity_create_actions(uint16_t port_id, struct rte_flow_action *action);
+#define snippet_skeleton_flow_create_actions snippet_match_port_affinity_create_actions
+
+void
+snippet_match_port_affinity_create_patterns(struct rte_flow_item *pattern);
+#define snippet_skeleton_flow_create_patterns snippet_match_port_affinity_create_patterns
+
+struct rte_flow_template_table *
+snippet_match_port_affinity_create_table(uint16_t port_id, struct rte_flow_error *error);
+#define snippet_skeleton_flow_create_table snippet_match_port_affinity_create_table
+
+#endif /* SNIPPET_MATCH_PORT_AFFINITY_H */
diff --git a/examples/flow_filtering/snippets/snippet_re_route_to_kernel.c b/examples/flow_filtering/snippets/snippet_re_route_to_kernel.c
index 1e5a875164..15214a0244 100644
--- a/examples/flow_filtering/snippets/snippet_re_route_to_kernel.c
+++ b/examples/flow_filtering/snippets/snippet_re_route_to_kernel.c
@@ -19,7 +19,8 @@ snippet_init_re_route_to_kernel(void)
}
void
-snippet_re_route_to_kernel_create_actions(struct rte_flow_action *action)
+snippet_re_route_to_kernel_create_actions(__rte_unused uint16_t port_id,
+ struct rte_flow_action *action)
{
action[0].type = RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL;
action[1].type = RTE_FLOW_ACTION_TYPE_END;
diff --git a/examples/flow_filtering/snippets/snippet_re_route_to_kernel.h b/examples/flow_filtering/snippets/snippet_re_route_to_kernel.h
index 9845cc839d..47df34d711 100644
--- a/examples/flow_filtering/snippets/snippet_re_route_to_kernel.h
+++ b/examples/flow_filtering/snippets/snippet_re_route_to_kernel.h
@@ -20,7 +20,7 @@ snippet_init_re_route_to_kernel(void);
#define snippet_init snippet_init_re_route_to_kernel
static void
-snippet_re_route_to_kernel_create_actions(struct rte_flow_action *action);
+snippet_re_route_to_kernel_create_actions(uint16_t port_id, struct rte_flow_action *action);
#define snippet_skeleton_flow_create_actions snippet_re_route_to_kernel_create_actions
static void
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 2/2] examples/flow_filtering: add jump flow
2025-06-24 7:15 [RFC PATCH 0/2] Add jump flow support and queue menegment with new snippets Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 1/2] examples/flow_filtering: add match port affinity snippet Shani Peretz
@ 2025-06-24 7:15 ` Shani Peretz
1 sibling, 0 replies; 3+ messages in thread
From: Shani Peretz @ 2025-06-24 7:15 UTC (permalink / raw)
To: dev; +Cc: Shani Peretz, Ori Kam
Added the option to jump to a specific group.
snippets that are not supported on the root table can now call
create_jump_flow to jump to other group.
Added three new snippets that uses the jump flow:
- match Network Service Header (NSH) snippet
- match RoCE IB BTH opcode/dest_qp snippet
- Switch Granularity rule matching snippet
Signed-off-by: Shani Peretz <shperetz@nvidia.com>
---
examples/flow_filtering/jump_flow.c | 40 ++++++++++
examples/flow_filtering/jump_flow.h | 13 ++++
examples/flow_filtering/meson.build | 4 +
.../snippets/snippet_match_nsh.c | 74 +++++++++++++++++++
.../snippets/snippet_match_nsh.h | 36 +++++++++
.../snippets/snippet_match_roce_ib_bth.c | 69 +++++++++++++++++
.../snippets/snippet_match_roce_ib_bth.h | 35 +++++++++
.../snippets/snippet_switch_granularity.c | 55 ++++++++++++++
.../snippets/snippet_switch_granularity.h | 36 +++++++++
9 files changed, 362 insertions(+)
create mode 100644 examples/flow_filtering/jump_flow.c
create mode 100644 examples/flow_filtering/jump_flow.h
create mode 100644 examples/flow_filtering/snippets/snippet_match_nsh.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_nsh.h
create mode 100644 examples/flow_filtering/snippets/snippet_match_roce_ib_bth.c
create mode 100644 examples/flow_filtering/snippets/snippet_match_roce_ib_bth.h
create mode 100644 examples/flow_filtering/snippets/snippet_switch_granularity.c
create mode 100644 examples/flow_filtering/snippets/snippet_switch_granularity.h
diff --git a/examples/flow_filtering/jump_flow.c b/examples/flow_filtering/jump_flow.c
new file mode 100644
index 0000000000..268c0d597e
--- /dev/null
+++ b/examples/flow_filtering/jump_flow.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#include <stdlib.h>
+#include <rte_flow.h>
+
+#include "jump_flow.h"
+
+
+struct rte_flow *
+create_jump_flow(uint16_t port_id, uint16_t group_id, struct rte_flow_error *error)
+{
+ struct rte_flow_action actions[2] = {0};
+ struct rte_flow_item patterns[2] = {0};
+ struct rte_flow *flow = NULL;
+
+ struct rte_flow_attr flow_attr = {
+ .ingress = 1,
+ .group = 0,
+ };
+
+ struct rte_flow_action_jump jump = {
+ .group = group_id,
+ };
+
+ /* Set up jump action to target group */
+ actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ actions[0].conf = &jump;
+ actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+ /* match on ethernet */
+ patterns[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ patterns[1].type = RTE_FLOW_ITEM_TYPE_END;
+
+ /* Validate the rule and create it. */
+ if (rte_flow_validate(port_id, &flow_attr, patterns, actions, error) == 0)
+ flow = rte_flow_create(port_id, &flow_attr, patterns, actions, error);
+ return flow;
+}
diff --git a/examples/flow_filtering/jump_flow.h b/examples/flow_filtering/jump_flow.h
new file mode 100644
index 0000000000..ebbec85533
--- /dev/null
+++ b/examples/flow_filtering/jump_flow.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef JUMP_FLOW_H
+#define JUMP_FLOW_H
+
+
+struct rte_flow *
+create_jump_flow(uint16_t port_id, uint16_t group_id, struct rte_flow_error *error);
+
+
+#endif /* JUMP_FLOW_H */
diff --git a/examples/flow_filtering/meson.build b/examples/flow_filtering/meson.build
index 3be2bb1ef5..3b644c7029 100644
--- a/examples/flow_filtering/meson.build
+++ b/examples/flow_filtering/meson.build
@@ -12,11 +12,15 @@ deps += ['argparse']
sources = files(
'main.c',
'flow_skeleton.c',
+ 'jump_flow.c',
'snippets/snippet_match_ipv4.c',
'snippets/snippet_match_gre.c',
'snippets/snippet_match_mpls.c',
+ 'snippets/snippet_match_nsh.c',
'snippets/snippet_match_port_affinity.c',
+ 'snippets/snippet_match_roce_ib_bth.c',
'snippets/snippet_re_route_to_kernel.c',
+ 'snippets/snippet_switch_granularity.c'
)
# The code snippets are not utilized.
diff --git a/examples/flow_filtering/snippets/snippet_match_nsh.c b/examples/flow_filtering/snippets/snippet_match_nsh.c
new file mode 100644
index 0000000000..262d0c8d81
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_nsh.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#include <stdlib.h>
+#include <rte_flow.h>
+
+#include "../common.h"
+#include "../jump_flow.h"
+#include "snippet_match_nsh.h"
+
+static void
+snippet_init_nsh(void)
+{
+ flow_attr.transfer = 1;
+ flow_attr.group = 1;
+ flow_attr.priority = 0;
+}
+
+static void
+snippet_match_nsh_create_actions(uint16_t port_id, struct rte_flow_action *action)
+{
+ /* jump to group 1 */
+ struct rte_flow_error error;
+ create_jump_flow(port_id, 1, &error);
+
+ struct rte_flow_action_port_id *portid = calloc(1, sizeof(struct rte_flow_action_port_id));
+ if (portid == NULL)
+ fprintf(stderr, "Failed to allocate memory for port_id\n");
+
+ /* To match on NSH to port_id 1. */
+ portid->id = 1;
+
+ action[0].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
+ action[0].conf = portid;
+ action[1].type = RTE_FLOW_ACTION_TYPE_END;
+}
+
+static void
+snippet_match_nsh_create_patterns(struct rte_flow_item *pattern)
+{
+ struct rte_flow_item_udp *spec;
+ struct rte_flow_item_udp *mask;
+
+ spec = calloc(1, sizeof(struct rte_flow_item_udp));
+ if (spec == NULL)
+ fprintf(stderr, "Failed to allocate memory for spec\n");
+
+ mask = calloc(1, sizeof(struct rte_flow_item_udp));
+ if (mask == NULL)
+ fprintf(stderr, "Failed to allocate memory for mask\n");
+
+ /* Set the patterns. */
+ pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+
+ pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+ spec->hdr.dst_port = RTE_BE16(250);
+ mask->hdr.dst_port = RTE_BE16(0xffff);
+ pattern[2].spec = spec;
+ pattern[2].mask = mask;
+
+ pattern[3].type = RTE_FLOW_ITEM_TYPE_VXLAN_GPE;
+ pattern[4].type = RTE_FLOW_ITEM_TYPE_NSH;
+ pattern[5].type = RTE_FLOW_ITEM_TYPE_ETH;
+ pattern[6].type = RTE_FLOW_ITEM_TYPE_END;
+}
+
+static struct rte_flow_template_table *
+snippet_nsh_flow_create_table(__rte_unused uint16_t port_id,
+ __rte_unused struct rte_flow_error *error)
+{
+ return NULL;
+}
diff --git a/examples/flow_filtering/snippets/snippet_match_nsh.h b/examples/flow_filtering/snippets/snippet_match_nsh.h
new file mode 100644
index 0000000000..8df37c2b13
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_nsh.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef SNIPPET_MATCH_NSH_H
+#define SNIPPET_MATCH_NSH_H
+
+/* Network Service Header (NSH)
+ * provides a mechanism for metadata exchange along the instantiated service paths.
+ * The NSH is the Service Function Chaining (SFC) encapsulation required to support the
+ * SFC architecture.
+ * NSH, a data-plane protocol can be matched now using the existed item: RTE_FLOW_ITEM_TYPE_NSH.
+ * Currently this is supported ONLY when NSH follows VXLAN-GPE,
+ * and the "l3_vxlan_en=1" and "dv_flow_en=1" (Default) is set.
+ */
+
+#define MAX_PATTERN_NUM 7 /* Maximal number of patterns for this example. */
+#define MAX_ACTION_NUM 2 /* Maximal number of actions for this example. */
+
+static void
+snippet_init_nsh(void);
+#define snippet_init snippet_init_nsh
+
+static void
+snippet_match_nsh_create_actions(uint16_t port_id, struct rte_flow_action *actions);
+#define snippet_skeleton_flow_create_actions snippet_match_nsh_create_actions
+
+static void
+snippet_match_nsh_create_patterns(struct rte_flow_item *pattern);
+#define snippet_skeleton_flow_create_patterns snippet_match_nsh_create_patterns
+
+static struct rte_flow_template_table *
+snippet_nsh_flow_create_table(uint16_t port_id, struct rte_flow_error *error);
+#define snippet_skeleton_flow_create_table snippet_nsh_flow_create_table
+
+#endif /* SNIPPET_MATCH_NSH_H */
diff --git a/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.c b/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.c
new file mode 100644
index 0000000000..f3c7e3eb70
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.c
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#include <stdlib.h>
+#include <rte_flow.h>
+
+#include "../common.h"
+#include "../jump_flow.h"
+#include "snippet_match_roce_ib_bth.h"
+
+static void
+snippet_init_roce_ib_bth(void)
+{
+ flow_attr.ingress = 1;
+ flow_attr.group = 1;
+ flow_attr.priority = 1;
+}
+
+static void
+snippet_match_roce_ib_bth_create_actions(uint16_t port_id, struct rte_flow_action *action)
+{
+ /* jump to group 1 */
+ struct rte_flow_error error;
+ create_jump_flow(port_id, 1, &error);
+
+ /* Create one action that moves the packet to the selected queue. */
+ struct rte_flow_action_queue *queue = calloc(1, sizeof(struct rte_flow_action_queue));
+ if (queue == NULL)
+ fprintf(stderr, "Failed to allocate memory for queue\n");
+
+ /* Set the selected queue. */
+ queue->index = 1;
+
+ /* Set the action move packet to the selected queue. */
+ action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+ action[0].conf = queue;
+ action[1].type = RTE_FLOW_ACTION_TYPE_END;
+}
+
+static void
+snippet_match_roce_ib_bth_create_patterns(struct rte_flow_item *pattern)
+{
+ struct rte_flow_item_ib_bth *bth;
+
+ bth = calloc(1, sizeof(struct rte_flow_item_ib_bth));
+ if (bth == NULL)
+ fprintf(stderr, "Failed to allocate memory for bth\n");
+
+ bth->hdr.opcode = 0x81;
+ bth->hdr.dst_qp[0] = 0x0;
+ bth->hdr.dst_qp[1] = 0xab;
+ bth->hdr.dst_qp[2] = 0xd4;
+
+ /* Set the patterns. */
+ pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+ pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+ pattern[3].type = RTE_FLOW_ITEM_TYPE_IB_BTH;
+ pattern[3].spec = bth;
+ pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+}
+
+static struct rte_flow_template_table *
+snippet_match_roce_ib_bth_create_table(__rte_unused uint16_t port_id,
+ __rte_unused struct rte_flow_error *error)
+{
+ return NULL;
+}
diff --git a/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.h b/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.h
new file mode 100644
index 0000000000..a93ced3248
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_match_roce_ib_bth.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef SNIPPET_MATCH_ROCE_IB_BTH_H
+#define SNIPPET_MATCH_ROCE_IB_BTH_H
+
+/* Matching RoCE IB BTH opcode/dest_qp
+ * IB BTH fields (opcode, and dst_qp) can be matched now using the new IB BTH item:
+ * RTE_FLOW_ITEM_TYPE_IB_BTH.
+ * Currently, this item is supported on group > 1, and supports only the RoCEv2 packet.
+ * The input BTH match item is defaulted to match one RoCEv2 packet.
+ */
+
+#define MAX_PATTERN_NUM 5 /* Maximal number of patterns for this example. */
+#define MAX_ACTION_NUM 2 /* Maximal number of actions for this example. */
+
+static void
+snippet_init_roce_ib_bth(void);
+#define snippet_init snippet_init_roce_ib_bth
+
+static void
+snippet_match_roce_ib_bth_create_actions(uint16_t port_id, struct rte_flow_action *action);
+#define snippet_skeleton_flow_create_actions snippet_match_roce_ib_bth_create_actions
+
+static void
+snippet_match_roce_ib_bth_create_patterns(struct rte_flow_item *pattern);
+#define snippet_skeleton_flow_create_patterns snippet_match_roce_ib_bth_create_patterns
+
+static struct rte_flow_template_table *
+snippet_match_roce_ib_bth_create_table(__rte_unused uint16_t port_id,
+__rte_unused struct rte_flow_error *error);
+#define snippet_skeleton_flow_create_table snippet_match_roce_ib_bth_create_table
+
+#endif /* SNIPPET_MATCH_ROCE_IB_BTH_H */
diff --git a/examples/flow_filtering/snippets/snippet_switch_granularity.c b/examples/flow_filtering/snippets/snippet_switch_granularity.c
new file mode 100644
index 0000000000..414870bf89
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_switch_granularity.c
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+#include <stdlib.h>
+#include <rte_flow.h>
+
+#include "../common.h"
+#include "../jump_flow.h"
+#include "snippet_switch_granularity.h"
+
+static void
+snippet_init_switch_granularity(void)
+{
+ flow_attr.ingress = 0;
+ flow_attr.transfer = 1;
+ flow_attr.group = 1;
+ flow_attr.priority = 1;
+}
+
+static void
+snippet_match_switch_granularity_create_actions(uint16_t port_id, struct rte_flow_action *action)
+{
+ /* jump to group 1 */
+ struct rte_flow_error error;
+ create_jump_flow(port_id, 1, &error);
+
+ struct rte_flow_action_ethdev *represented_port = calloc(1,
+ sizeof(struct rte_flow_action_ethdev));
+ if (represented_port == NULL)
+ fprintf(stderr, "Failed to allocate memory for represented_port\n");
+
+ represented_port->port_id = 0;
+ action[0].type = RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT;
+ action[0].conf = represented_port;
+ action[1].type = RTE_FLOW_ACTION_TYPE_END;
+}
+
+static void
+snippet_match_switch_granularity_create_patterns(struct rte_flow_item *pattern)
+{
+ /* Set the patterns. */
+ pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ pattern[1].type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT;
+ pattern[1].spec = NULL;
+ pattern[1].mask = NULL;
+ pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+}
+
+static struct rte_flow_template_table *
+create_table_switch_granularity(__rte_unused uint16_t port_id,
+ __rte_unused struct rte_flow_error *error)
+{
+ return NULL;
+}
diff --git a/examples/flow_filtering/snippets/snippet_switch_granularity.h b/examples/flow_filtering/snippets/snippet_switch_granularity.h
new file mode 100644
index 0000000000..edc15c3ed7
--- /dev/null
+++ b/examples/flow_filtering/snippets/snippet_switch_granularity.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 NVIDIA Corporation & Affiliates
+ */
+
+ #ifndef SNIPPET_SWITCH_GRANULARITY_H
+ #define SNIPPET_SWITCH_GRANULARITY_H
+
+/* Switch Granularity Rule Matching
+ * supports the represented_port item in pattern.
+ * If the spec and the mask are both set to NULL, the source vPort
+ * will not be added to the matcher, it will match patterns for all
+ * vPort to reduce rule count and memory consumption.
+ * When testpmd starts with a PF, a VF-rep0 and a VF-rep1,
+ * the snippets will redirect packets from VF0 and VF1 to the wire
+ */
+
+ #define MAX_PATTERN_NUM 3 /* Maximal number of patterns for this example. */
+ #define MAX_ACTION_NUM 2 /* Maximal number of actions for this example. */
+
+static void
+snippet_init_switch_granularity(void);
+#define snippet_init snippet_init_switch_granularity
+
+static void
+snippet_match_switch_granularity_create_actions(uint16_t port_id, struct rte_flow_action *action);
+#define snippet_skeleton_flow_create_actions snippet_match_switch_granularity_create_actions
+
+static void
+snippet_match_switch_granularity_create_patterns(struct rte_flow_item *pattern);
+#define snippet_skeleton_flow_create_patterns snippet_match_switch_granularity_create_patterns
+
+static struct rte_flow_template_table *
+create_table_switch_granularity(uint16_t port_id, struct rte_flow_error *error);
+#define snippet_skeleton_flow_create_table create_table_switch_granularity
+
+ #endif /* SNIPPET_SWITCH_GRANULARITY_H */
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-06-24 7:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-24 7:15 [RFC PATCH 0/2] Add jump flow support and queue menegment with new snippets Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 1/2] examples/flow_filtering: add match port affinity snippet Shani Peretz
2025-06-24 7:15 ` [RFC PATCH 2/2] examples/flow_filtering: add jump flow Shani Peretz
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).