[v2] net/enic: support GTP header flow matching

Message ID 20211028063658.28246-1-johndale@cisco.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series [v2] net/enic: support GTP header flow matching |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/iol-spell-check-testing warning Testing issues
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/github-robot: build success github build: passed
ci/iol-x86_64-compile-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS

Commit Message

John Daley (johndale) Oct. 28, 2021, 6:36 a.m. UTC
  The GTP, GTP-U, GTP-C header fields can be matched, however NIC does not
support GTP tunneling so no items after the GTP header can be specified.
If a GTP-U or GTP-C item is specified without a preceding UDP item, the
UDP destination port is implicitly matched. For GTP, the destination UDP
port must be specified but its value is not enforced.

Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Hyong Youb Kim <hyonkim@cisco.com>
---
v2: Fixed specification of the max enic flowman item

 doc/guides/nics/enic.rst               |   2 +
 doc/guides/nics/features/enic.ini      |   3 +
 doc/guides/rel_notes/release_21_11.rst |   4 +
 drivers/net/enic/enic_fm_flow.c        | 124 ++++++++++++++++++++++++-
 4 files changed, 129 insertions(+), 4 deletions(-)
  

Patch

diff --git a/doc/guides/nics/enic.rst b/doc/guides/nics/enic.rst
index f2ee49fe82..5e2054fc8a 100644
--- a/doc/guides/nics/enic.rst
+++ b/doc/guides/nics/enic.rst
@@ -473,6 +473,8 @@  RTE_MBUF_F_RX_VLAN_STRIPPED mbuf flags would not be set. This mode is enabled wi
     packets and then receive them normally. These require 1400 series VIC adapters
     and latest firmware.
   - RAW items are limited to matching UDP tunnel headers like VXLAN.
+  - GTP, GTP-C and GTP-U header matching is enabled, however matching items within
+    the tunnel is not supported.
   - For 1400 VICs, all flows using the RSS action on a port use same hash
     configuration. The RETA is ignored. The queues used in the RSS group must be
     sequential. There is a performance hit if the number of queues is not a power of 2.
diff --git a/doc/guides/nics/features/enic.ini b/doc/guides/nics/features/enic.ini
index 3064336162..1177752c15 100644
--- a/doc/guides/nics/features/enic.ini
+++ b/doc/guides/nics/features/enic.ini
@@ -40,6 +40,9 @@  Usage doc            = Y
 
 [rte_flow items]
 eth                  = Y
+gtp                  = Y
+gtpc                 = Y
+gtpu                 = Y
 ipv4                 = Y
 ipv6                 = Y
 raw                  = Y
diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 1ccac87b73..2cee5347f3 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -154,6 +154,10 @@  New Features
   * Implement support for tunnel offload.
   * Updated HWRM API to version 1.10.2.44
 
+* **Updated Cisco enic driver.**
+
+  * Added rte_flow support for matching GTP, GTP-C and GTP-U headers.
+
 * **Updated Intel e1000 emulated driver.**
 
   * Added Intel e1000 support on Windows.
diff --git a/drivers/net/enic/enic_fm_flow.c b/drivers/net/enic/enic_fm_flow.c
index 2c60bb864e..48ea1d0ff9 100644
--- a/drivers/net/enic/enic_fm_flow.c
+++ b/drivers/net/enic/enic_fm_flow.c
@@ -22,9 +22,6 @@ 
 #define IP_DEFTTL  64   /* from RFC 1340. */
 #define IP6_VTC_FLOW 0x60000000
 
-/* Highest Item type supported by Flowman */
-#define FM_MAX_ITEM_TYPE RTE_FLOW_ITEM_TYPE_VXLAN
-
 /* Up to 1024 TCAM entries */
 #define FM_MAX_TCAM_TABLE_SIZE 1024
 
@@ -235,6 +232,7 @@  static enic_copy_item_fn enic_fm_copy_item_tcp;
 static enic_copy_item_fn enic_fm_copy_item_udp;
 static enic_copy_item_fn enic_fm_copy_item_vlan;
 static enic_copy_item_fn enic_fm_copy_item_vxlan;
+static enic_copy_item_fn enic_fm_copy_item_gtp;
 
 /* Ingress actions */
 static const enum rte_flow_action_type enic_fm_supported_ig_actions[] = {
@@ -346,6 +344,30 @@  static const struct enic_fm_items enic_fm_items[] = {
 			       RTE_FLOW_ITEM_TYPE_END,
 		},
 	},
+	[RTE_FLOW_ITEM_TYPE_GTP] = {
+		.copy_item = enic_fm_copy_item_gtp,
+		.valid_start_item = 0,
+		.prev_items = (const enum rte_flow_item_type[]) {
+			       RTE_FLOW_ITEM_TYPE_UDP,
+			       RTE_FLOW_ITEM_TYPE_END,
+		},
+	},
+	[RTE_FLOW_ITEM_TYPE_GTPC] = {
+		.copy_item = enic_fm_copy_item_gtp,
+		.valid_start_item = 1,
+		.prev_items = (const enum rte_flow_item_type[]) {
+			       RTE_FLOW_ITEM_TYPE_UDP,
+			       RTE_FLOW_ITEM_TYPE_END,
+		},
+	},
+	[RTE_FLOW_ITEM_TYPE_GTPU] = {
+		.copy_item = enic_fm_copy_item_gtp,
+		.valid_start_item = 1,
+		.prev_items = (const enum rte_flow_item_type[]) {
+			       RTE_FLOW_ITEM_TYPE_UDP,
+			       RTE_FLOW_ITEM_TYPE_END,
+		},
+	},
 };
 
 static int
@@ -629,6 +651,100 @@  enic_fm_copy_item_vxlan(struct copy_item_args *arg)
 	return 0;
 }
 
+static int
+enic_fm_copy_item_gtp(struct copy_item_args *arg)
+{
+	const struct rte_flow_item *item = arg->item;
+	const struct rte_flow_item_gtp *spec = item->spec;
+	const struct rte_flow_item_gtp *mask = item->mask;
+	struct fm_tcam_match_entry *entry = arg->fm_tcam_entry;
+	struct fm_header_set *fm_data, *fm_mask;
+	int off;
+	uint16_t udp_gtp_uc_port = 0;
+
+	ENICPMD_FUNC_TRACE();
+	/* Only 2 header levels (outer and inner) allowed */
+	if (arg->header_level > 0)
+		return -EINVAL;
+
+	fm_data = &entry->ftm_data.fk_hdrset[0];
+	fm_mask = &entry->ftm_mask.fk_hdrset[0];
+
+	switch (item->type) {
+	case RTE_FLOW_ITEM_TYPE_GTP:
+	{
+		/* For vanilla GTP, the UDP destination port must be specified
+		 * but value of the port is not enforced here.
+		 */
+		if (!(fm_data->fk_metadata & FKM_UDP) ||
+		    !(fm_data->fk_header_select & FKH_UDP) ||
+		    fm_data->l4.udp.fk_dest == 0)
+			return -EINVAL;
+		if (!(fm_mask->fk_metadata & FKM_UDP) ||
+		    !(fm_mask->fk_header_select & FKH_UDP) ||
+		    fm_mask->l4.udp.fk_dest != 0xFFFF)
+			return -EINVAL;
+		break;
+	}
+	case RTE_FLOW_ITEM_TYPE_GTPC:
+	{
+		udp_gtp_uc_port = RTE_GTPC_UDP_PORT;
+		break;
+	}
+	case RTE_FLOW_ITEM_TYPE_GTPU:
+	{
+		udp_gtp_uc_port = RTE_GTPU_UDP_PORT;
+		break;
+	}
+	default:
+		RTE_ASSERT(0);
+	}
+
+	/* The GTP-C or GTP-U UDP destination port must be matched. */
+	if (udp_gtp_uc_port) {
+		if (fm_data->fk_metadata & FKM_UDP &&
+		    fm_data->fk_header_select & FKH_UDP &&
+		    rte_be_to_cpu_16(fm_data->l4.udp.fk_dest) !=
+		    udp_gtp_uc_port)
+			return -EINVAL;
+		if (fm_mask->fk_metadata & FKM_UDP &&
+		    fm_mask->fk_header_select & FKH_UDP &&
+		    fm_mask->l4.udp.fk_dest != 0xFFFF)
+			return -EINVAL;
+
+		/* In any case, add match for GTP-C GTP-U UDP dst port */
+		fm_data->fk_metadata |= FKM_UDP;
+		fm_data->fk_header_select |= FKH_UDP;
+		fm_data->l4.udp.fk_dest = udp_gtp_uc_port;
+		fm_mask->fk_metadata |= FKM_UDP;
+		fm_mask->fk_header_select |= FKH_UDP;
+		fm_mask->l4.udp.fk_dest = 0xFFFF;
+	}
+
+	/* NIC does not support GTP tunnels. No Items are allowed after this.
+	 * This prevents the specificaiton of further items.
+	 */
+	arg->header_level = 0;
+
+	/* Match all if no spec */
+	if (!spec)
+		return 0;
+	if (!mask)
+		mask = &rte_flow_item_gtp_mask;
+
+	/*
+	 * Use the raw L4 buffer to match GTP as fm_header_set does not have
+	 * GTP header. UDP dst port must be specifiec. Using the raw buffer
+	 * does not affect such UDP item, since we skip UDP in the raw buffer.
+	 */
+	fm_data->fk_header_select |= FKH_L4RAW;
+	fm_mask->fk_header_select |= FKH_L4RAW;
+	off = sizeof(fm_data->l4.udp);
+	memcpy(&fm_data->l4.rawdata[off], spec, sizeof(*spec));
+	memcpy(&fm_mask->l4.rawdata[off], mask, sizeof(*mask));
+	return 0;
+}
+
 /*
  * Currently, raw pattern match is very limited. It is intended for matching
  * UDP tunnel header (e.g. vxlan or geneve).
@@ -863,7 +979,7 @@  enic_fm_copy_entry(struct enic_flowman *fm,
 
 		item_info = &enic_fm_items[item->type];
 
-		if (item->type > FM_MAX_ITEM_TYPE ||
+		if (item->type >= RTE_DIM(enic_fm_items) ||
 		    item_info->copy_item == NULL) {
 			return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ITEM,