summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing Xu <ting.xu@intel.com>2021-09-16 08:37:25 +0000
committerDamjan Marion <dmarion@me.com>2022-03-15 16:15:19 +0000
commit3a3668201734fddb614cba025fafc4578ddf5482 (patch)
treec8dddf2ac1a050825eb8a00804a9fa4170e2a0e0
parent218e4ec5302a88d4400cc3b0897310f4d59675be (diff)
flow: add generic flow pattern for 5G flow enhancement
In order to support the requirement of RSS and packet steering of new protocols, such as GTPU PDU-type and QFI, for 5G UPF, a generic pattern is introduced in vnet flow. The generic flow pattern is based on DDP (Dynamic Device Personalization) function and Parser Library module in DPDK. Using generic flow pattern, we do not need to create new packet and field type and offset in API parser for every new protocols. We can create flows for any protocol immediately as long as supported by DDP. The generic flow can be used to support 5G related protocols in different scenarios. The input of this generic pattern are two binary strings for spec and mask. Spec is the binary presentation of the target packet type, and mask is used to mark the target fields. In this patch DPDK plugins is enabled for POC. Next step we will enable generic flow in native IAVF, which is the main target. Here is an example. If we want to create a flow for GTPU QFI, spec is: 00000000000100000000000208004500003C00000000001100000101010102020202000 008680028000034FF001C00000000000000850100010045000014000000000000000001 01010102020202 mask is: 00000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000007F0000000000000000000000000000 00000000000000 A naming API POC is created via VAPI to help create the rule with the target packet format similar to Scapy. It is based on a function module called PacketForge. In this way, the user no need to create binary string spec and mask by themselves. Type: feature Signed-off-by: Ting Xu <ting.xu@intel.com> Change-Id: Id3444f95c158bdcdfeeee19d795cd9ecbeeec07c
-rw-r--r--src/plugins/dpdk/device/flow.c16
-rw-r--r--src/vnet/flow/flow.h50
-rw-r--r--src/vnet/flow/flow_cli.c53
3 files changed, 87 insertions, 32 deletions
diff --git a/src/plugins/dpdk/device/flow.c b/src/plugins/dpdk/device/flow.c
index 19d504e5514..91541f40163 100644
--- a/src/plugins/dpdk/device/flow.c
+++ b/src/plugins/dpdk/device/flow.c
@@ -142,6 +142,7 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
struct rte_flow_item_l2tpv3oip l2tp[2] = { };
struct rte_flow_item_esp esp[2] = { };
struct rte_flow_item_ah ah[2] = { };
+ struct rte_flow_item_raw generic[2] = {};
struct rte_flow_action_mark mark = { 0 };
struct rte_flow_action_queue queue = { 0 };
struct rte_flow_action_rss rss = { 0 };
@@ -165,6 +166,20 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
u8 protocol = IP_PROTOCOL_RESERVED;
int rv = 0;
+ /* Handle generic flow first */
+ if (f->type == VNET_FLOW_TYPE_GENERIC)
+ {
+ generic[0].pattern = f->generic.pattern.spec;
+ generic[1].pattern = f->generic.pattern.mask;
+
+ vec_add2 (items, item, 1);
+ item->type = RTE_FLOW_ITEM_TYPE_RAW;
+ item->spec = generic;
+ item->mask = generic + 1;
+
+ goto pattern_end;
+ }
+
enum
{
FLOW_UNKNOWN_CLASS,
@@ -653,6 +668,7 @@ dpdk_flow_ops_fn (vnet_main_t * vnm, vnet_flow_dev_op_t op, u32 dev_instance,
case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
case VNET_FLOW_TYPE_IP4_IPSEC_ESP:
case VNET_FLOW_TYPE_IP4_IPSEC_AH:
+ case VNET_FLOW_TYPE_GENERIC:
if ((rv = dpdk_flow_add (xd, flow, fe)))
goto done;
break;
diff --git a/src/vnet/flow/flow.h b/src/vnet/flow/flow.h
index 4945f4367c7..313e85c45f9 100644
--- a/src/vnet/flow/flow.h
+++ b/src/vnet/flow/flow.h
@@ -24,26 +24,28 @@
#include <vnet/ip/ip6_packet.h>
#include <vnet/ethernet/packet.h>
-#define foreach_flow_type \
- /* l2 flow*/ \
- _(ETHERNET, ethernet, "ethernet") \
- /* l3 IP flow */ \
- _(IP4, ip4, "ipv4") \
- _(IP6, ip6, "ipv6") \
- /* IP tunnel flow */ \
- _(IP4_L2TPV3OIP, ip4_l2tpv3oip, "ipv4-l2tpv3oip") \
- _(IP4_IPSEC_ESP, ip4_ipsec_esp, "ipv4-ipsec-esp") \
- _(IP4_IPSEC_AH, ip4_ipsec_ah, "ipv4-ipsec-ah") \
- /* l4 flow*/ \
- _(IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \
- _(IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \
- _(IP4_N_TUPLE_TAGGED, ip4_n_tuple_tagged, "ipv4-n-tuple-tagged") \
- _(IP6_N_TUPLE_TAGGED, ip6_n_tuple_tagged, "ipv6-n-tuple-tagged") \
- /* L4 tunnel flow*/ \
- _(IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \
- _(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \
- _(IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \
- _(IP4_GTPU, ip4_gtpu, "ipv4-gtpu")
+#define foreach_flow_type \
+ /* l2 flow*/ \
+ _ (ETHERNET, ethernet, "ethernet") \
+ /* l3 IP flow */ \
+ _ (IP4, ip4, "ipv4") \
+ _ (IP6, ip6, "ipv6") \
+ /* IP tunnel flow */ \
+ _ (IP4_L2TPV3OIP, ip4_l2tpv3oip, "ipv4-l2tpv3oip") \
+ _ (IP4_IPSEC_ESP, ip4_ipsec_esp, "ipv4-ipsec-esp") \
+ _ (IP4_IPSEC_AH, ip4_ipsec_ah, "ipv4-ipsec-ah") \
+ /* l4 flow*/ \
+ _ (IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \
+ _ (IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \
+ _ (IP4_N_TUPLE_TAGGED, ip4_n_tuple_tagged, "ipv4-n-tuple-tagged") \
+ _ (IP6_N_TUPLE_TAGGED, ip6_n_tuple_tagged, "ipv6-n-tuple-tagged") \
+ /* L4 tunnel flow*/ \
+ _ (IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \
+ _ (IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \
+ _ (IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \
+ _ (IP4_GTPU, ip4_gtpu, "ipv4-gtpu") \
+ /* generic flow */ \
+ _ (GENERIC, generic, "generic")
#define foreach_flow_entry_ethernet \
_fe(ethernet_header_t, eth_hdr)
@@ -104,6 +106,8 @@
foreach_flow_entry_ip4_n_tuple \
_fe(u32, teid)
+#define foreach_flow_entry_generic _fe (generic_pattern_t, pattern)
+
#define foreach_flow_action \
_(0, COUNT, "count") \
_(1, MARK, "mark") \
@@ -190,6 +194,12 @@ typedef struct
u8 mask;
} ip_prot_and_mask_t;
+typedef struct
+{
+ u8 spec[1024];
+ u8 mask[1024];
+} generic_pattern_t;
+
typedef enum
{
VNET_FLOW_TYPE_UNKNOWN,
diff --git a/src/vnet/flow/flow_cli.c b/src/vnet/flow/flow_cli.c
index e2a3141c551..f3e6c3912bd 100644
--- a/src/vnet/flow/flow_cli.c
+++ b/src/vnet/flow/flow_cli.c
@@ -223,6 +223,11 @@ show_flow_entry (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_output (vm, "%-10s: %u", "index", f->index);
vlib_cli_output (vm, "%-10s: %s", "type", flow_type_strings[f->type]);
vlib_cli_output (vm, "%-10s: %U", "match", format_flow, f);
+ if (f->type == VNET_FLOW_TYPE_GENERIC)
+ {
+ vlib_cli_output (vm, "%s: %s", "spec", f->generic.pattern.spec);
+ vlib_cli_output (vm, "%s: %s", "mask", f->generic.pattern.mask);
+ }
/* *INDENT-OFF* */
hash_foreach (hw_if_index, private_data, f->private_data,
({
@@ -243,6 +248,11 @@ no_args:
pool_foreach (f, fm->global_flow_pool)
{
vlib_cli_output (vm, "%U\n", format_flow, f);
+ if (f->type == VNET_FLOW_TYPE_GENERIC)
+ {
+ vlib_cli_output (vm, "%s: %s", "spec", f->generic.pattern.spec);
+ vlib_cli_output (vm, "%s: %s", "mask", f->generic.pattern.mask);
+ }
}
/* *INDENT-ON* */
@@ -371,6 +381,8 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
bool ipsec_esp_set = false, ipsec_ah_set = false;
u8 *rss_type[3] = { };
u8 *type_str = NULL;
+ u8 *spec = NULL;
+ u8 *mask = NULL;
clib_memset (&flow, 0, sizeof (vnet_flow_t));
flow.index = ~0;
@@ -389,6 +401,10 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
action = FLOW_ENABLE;
else if (unformat (line_input, "disable"))
action = FLOW_DISABLE;
+ else if (unformat (line_input, "spec %s", &spec))
+ ;
+ else if (unformat (line_input, "mask %s", &mask))
+ ;
else if (unformat (line_input, "eth-type %U",
unformat_ethernet_type_host_byte_order, &eth_type))
flow_class = FLOW_ETHERNET_CLASS;
@@ -573,6 +589,11 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
break;
default:
+ if (spec && mask)
+ {
+ type = VNET_FLOW_TYPE_GENERIC;
+ break;
+ }
return clib_error_return (0,
"Please specify a supported flow type");
}
@@ -660,6 +681,13 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
break;
}
}
+ if (type == VNET_FLOW_TYPE_GENERIC)
+ {
+ clib_memcpy (flow.generic.pattern.spec, spec,
+ sizeof (flow.generic.pattern.spec));
+ clib_memcpy (flow.generic.pattern.mask, mask,
+ sizeof (flow.generic.pattern.mask));
+ }
flow.type = type;
rv = vnet_flow_add (vnm, &flow, &flow_index);
@@ -689,18 +717,19 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (test_flow_command, static) = {
- .path = "test flow",
- .short_help = "test flow [add|del|enable|disable] [index <id>] "
- "[src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] "
- "[ip6-src-ip <ip-addr/mask>] [ip6-dst-ip <ip-addr/mask>] "
- "[src-port <port/mask>] [dst-port <port/mask>] "
- "[proto <ip-proto>] "
- "[gtpc teid <teid>] [gtpu teid <teid>] [vxlan <vni>] "
- "[session id <session>] [spi <spi>]"
- "[next-node <node>] [mark <id>] [buffer-advance <len>] "
- "[redirect-to-queue <queue>] [drop] "
- "[rss function <name>] [rss types <flow type>]",
- .function = test_flow,
+ .path = "test flow",
+ .short_help = "test flow [add|del|enable|disable] [index <id>] "
+ "[src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] "
+ "[ip6-src-ip <ip-addr/mask>] [ip6-dst-ip <ip-addr/mask>] "
+ "[src-port <port/mask>] [dst-port <port/mask>] "
+ "[proto <ip-proto>] "
+ "[gtpc teid <teid>] [gtpu teid <teid>] [vxlan <vni>] "
+ "[session id <session>] [spi <spi>]"
+ "[spec <spec string>] [mask <mask string>]"
+ "[next-node <node>] [mark <id>] [buffer-advance <len>] "
+ "[redirect-to-queue <queue>] [drop] "
+ "[rss function <name>] [rss types <flow type>]",
+ .function = test_flow,
};
/* *INDENT-ON* */