[PATCH v3 net-next] octeontx2-af: add NPC TEID matching for GTP-U and GTP-C flows

Ratheesh Kannoth <[email protected]>
Newsgroups gmane.linux.network,gmane.linux.kernel
Message-ID <[email protected]>
From: Suman Ghosh <[email protected]>

Add NPC_GTPU_TEID and NPC_GTPC_TEID key fields and wire them through
the AF MCAM path so ethtool Rx flow rules can match on the TEID of
GTP-U and GTP-C packets.

In otx2_prepare_flow_request(), when a UDP or TCP v4/v6 ntuple rule
targets the well-known GTP-U (2152) or GTP-C (2123) destination port,
take the TEID value and mask from h_ext.data[1] and install the
corresponding LE layer match in NPC.  Expose the new fields in debugfs
MCAM dumps.

Signed-off-by: Suman Ghosh <[email protected]>
Signed-off-by: Geetha sowjanya <[email protected]>
Signed-off-by: Sunil Goutham <[email protected]>
Signed-off-by: Ratheesh Kannoth <[email protected]>

---
v2 -> v3: Addressed Sashiko comments
	https://sashiko.dev/#/patchset/20260812051215.456258-1-rkannoth%40marvell.com
v1 -> v2: Addressed Sashiko comments
	https://sashiko.dev/#/patchset/20260810050436.1822566-1-rkannoth%40marvell.com
---
 .../net/ethernet/marvell/octeontx2/af/mbox.h  |  2 +
 .../net/ethernet/marvell/octeontx2/af/npc.h   |  2 +
 .../marvell/octeontx2/af/rvu_debugfs.c        |  8 ++++
 .../marvell/octeontx2/af/rvu_npc_fs.c         | 40 ++++++++++++++++++-
 .../marvell/octeontx2/nic/otx2_flows.c        | 29 +++++++++++++-
 5 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 73f743e4a83d..7cf07f15bdae 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -1849,6 +1849,8 @@ struct flow_msg {
 	u8 icmp_code;
 	__be16 tcp_flags;
 	u16 sq_id;
+	__be32 gtpu_teid;
+	__be32 gtpc_teid;
 };
 
 struct npc_install_flow_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index 719b3618eeb5..187a50047617 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -226,6 +226,8 @@ enum key_fields {
 	NPC_TYPE_ICMP,
 	NPC_CODE_ICMP,
 	NPC_TCP_FLAGS,
+	NPC_GTPU_TEID,
+	NPC_GTPC_TEID,
 	NPC_HEADER_FIELDS_MAX,
 	NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */
 	NPC_PF_FUNC, /* Valid when Tx */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 3456313d3b3c..c0b0e4d14696 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -3437,6 +3437,14 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
 			seq_printf(s, "%d ", rule->packet.icmp_code);
 			seq_printf(s, "mask 0x%x\n", rule->mask.icmp_code);
 			break;
+		case NPC_GTPU_TEID:
+			seq_printf(s, "%u ", ntohl(rule->packet.gtpu_teid));
+			seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.gtpu_teid));
+			break;
+		case NPC_GTPC_TEID:
+			seq_printf(s, "%u ", ntohl(rule->packet.gtpc_teid));
+			seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.gtpc_teid));
+			break;
 		default:
 			seq_puts(s, "\n");
 			break;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
index d422bdd5e8f8..84be78ab7351 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
@@ -56,6 +56,8 @@ static const char * const npc_flow_names[] = {
 	[NPC_TYPE_ICMP] = "icmp type",
 	[NPC_CODE_ICMP] = "icmp code",
 	[NPC_TCP_FLAGS] = "tcp flags",
+	[NPC_GTPU_TEID]	= "gtp-u teid ",
+	[NPC_GTPC_TEID]	= "gtp-c teid ",
 	[NPC_UNKNOWN]	= "unknown",
 };
 
@@ -661,6 +663,8 @@ do {									       \
 	NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2);
 	NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2);
 	NPC_SCAN_HDR(NPC_VLAN_TAG3, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6, 2);
+	NPC_SCAN_HDR(NPC_GTPU_TEID, NPC_LID_LE, NPC_LT_LE_GTPU, 4, 4);
+	NPC_SCAN_HDR(NPC_GTPC_TEID, NPC_LID_LE, NPC_LT_LE_GTPC, 4, 4);
 	NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6);
 
 	NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4);
@@ -720,7 +724,7 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
 		*features |= BIT_ULL(NPC_IPPROTO_ICMP6);
 	}
 
-	/* for ESP, check if corresponding layer type is present in the key */
+	/* for ESP check if corresponding layer type is present in the key */
 	if (npc_check_field(rvu, blkaddr, NPC_LE, intf))
 		*features |= BIT_ULL(NPC_IPPROTO_ESP);
 
@@ -1113,6 +1117,14 @@ void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata,
 		npc_update_entry(rvu, NPC_LE, mdata, NPC_LT_LE_ESP,
 				 0, ~0ULL, 0, intf);
 
+	if (features & BIT_ULL(NPC_GTPU_TEID))
+		npc_update_entry(rvu, NPC_LE, mdata, NPC_LT_LE_GTPU,
+				 0, ~0ULL, 0, intf);
+
+	if (features & BIT_ULL(NPC_GTPC_TEID))
+		npc_update_entry(rvu, NPC_LE, mdata, NPC_LT_LE_GTPC,
+				 0, ~0ULL, 0, intf);
+
 	if (features & BIT_ULL(NPC_LXMB)) {
 		output->lxmb = is_broadcast_ether_addr(pkt->dmac) ? 2 : 1;
 		npc_update_entry(rvu, NPC_LXMB, mdata, output->lxmb, 0,
@@ -1209,6 +1221,10 @@ do {									      \
 
 	NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0,
 		       mask->next_header, 0);
+	NPC_WRITE_FLOW(NPC_GTPU_TEID, gtpu_teid, ntohl(pkt->gtpu_teid), 0,
+		       ntohl(mask->gtpu_teid), 0);
+	NPC_WRITE_FLOW(NPC_GTPC_TEID, gtpc_teid, ntohl(pkt->gtpc_teid), 0,
+		       ntohl(mask->gtpc_teid), 0);
 	npc_update_ipv6_flow(rvu, mdata, features, pkt, mask, output, intf);
 	npc_update_vlan_features(rvu, mdata, features, intf);
 
@@ -1769,6 +1785,28 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
 
 	req->entry = npc_cn20k_vidx2idx(req->entry);
 
+	if ((req->features & BIT_ULL(NPC_GTPU_TEID)) &&
+	    !npc_check_field(rvu, blkaddr, NPC_GTPU_TEID, req->intf)) {
+		if (is_pffunc_af(req->hdr.pcifunc))
+			dev_warn(rvu->dev,
+				 "%s: mkex profile does not extract GTP-U TEID\n",
+				 __func__);
+		rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc,
+						    allocated, req->entry);
+		return NPC_FLOW_NOT_SUPPORTED;
+	}
+
+	if ((req->features & BIT_ULL(NPC_GTPC_TEID)) &&
+	    !npc_check_field(rvu, blkaddr, NPC_GTPC_TEID, req->intf)) {
+		if (is_pffunc_af(req->hdr.pcifunc))
+			dev_warn(rvu->dev,
+				 "%s: mkex profile does not extract GTP-C TEID\n",
+				 __func__);
+		rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc,
+						    allocated, req->entry);
+		return NPC_FLOW_NOT_SUPPORTED;
+	}
+
 	/* If DMAC is not extracted in MKEX, rules installed by AF
 	 * can rely on L2MB bit set by hardware protocol checker for
 	 * broadcast and multicast addresses.
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 99d78fc5a2c4..b374d8811bc8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -11,6 +11,8 @@
 #include "otx2_common.h"
 
 #define OTX2_DEFAULT_ACTION	0x1
+#define GTPU_PORT		2152
+#define GTPC_PORT		2123
 
 struct otx2_flow {
 	struct ethtool_rx_flow_spec flow_spec;
@@ -1036,6 +1038,7 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
 		return -EOPNOTSUPP;
 	}
 	if (fsp->flow_type & FLOW_EXT) {
+		int skip_user_def = false;
 		u16 vlan_etype;
 
 		if (fsp->m_ext.vlan_etype) {
@@ -1076,7 +1079,31 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
 			req->features |= BIT_ULL(NPC_OUTER_VID);
 		}
 
-		if (fsp->m_ext.data[1]) {
+		/* GTP TEID uses FLOW_EXT data[1]; VLAN/MAC use other fields. */
+		if (fsp->m_ext.data[1] &&
+		    fsp->h_ext.data[1] != cpu_to_be32(OTX2_DEFAULT_ACTION)) {
+			switch (flow_type) {
+			case UDP_V4_FLOW:
+			case UDP_V6_FLOW:
+				if (ntohs(pmask->dport) == 0xFFFF &&
+				    ntohs(pkt->dport) == GTPU_PORT) {
+					/* Check for GTP-U packets */
+					skip_user_def = true;
+					pkt->gtpu_teid = fsp->h_ext.data[1];
+					pmask->gtpu_teid = fsp->m_ext.data[1];
+					req->features |= BIT_ULL(NPC_GTPU_TEID);
+				} else if (ntohs(pmask->dport) == 0xFFFF &&
+					   ntohs(pkt->dport) == GTPC_PORT) {
+					/* Check for GTP-C packets */
+					skip_user_def = true;
+					pkt->gtpc_teid = fsp->h_ext.data[1];
+					pmask->gtpc_teid = fsp->m_ext.data[1];
+					req->features |= BIT_ULL(NPC_GTPC_TEID);
+				}
+			}
+		}
+
+		if (fsp->m_ext.data[1] && !skip_user_def) {
 			if (flow_type == IP_USER_FLOW) {
 				if (be32_to_cpu(fsp->h_ext.data[1]) != IPV4_FLAG_MORE)
 					return -EINVAL;
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.