Commit 9a225f81 authored by Marcin Szycik's avatar Marcin Szycik Committed by Tony Nguyen
Browse files

ice: Support GTP-U and GTP-C offload in switchdev



Add support for creating filters for GTP-U and GTP-C in switchdev mode. Add
support for parsing GTP-specific options (QFI and PDU type) and TEID.

By default, a filter for GTP-U will be added. To add a filter for GTP-C,
specify enc_dst_port = 2123, e.g.:

tc filter add dev $GTP0 ingress prio 1 flower enc_key_id 1337 \
enc_dst_port 2123 action mirred egress redirect dev $VF1_PR

Note: GTP-U with outer IPv6 offload is not supported yet.
Note: GTP-U with no payload offload is not supported yet.

Signed-off-by: default avatarMarcin Szycik <marcin.szycik@linux.intel.com>
Reviewed-by: default avatarMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: default avatarSandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent e5dd661b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#include <net/gre.h>
#include <net/udp_tunnel.h>
#include <net/vxlan.h>
#include <net/gtp.h>
#if IS_ENABLED(CONFIG_DCB)
#include <scsi/iscsi_proto.h>
#endif /* CONFIG_DCB */
+29 −2
Original line number Diff line number Diff line
@@ -1804,16 +1804,43 @@ static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw)
	return bld;
}

static bool ice_is_gtp_u_profile(u16 prof_idx)
{
	return (prof_idx >= ICE_PROFID_IPV6_GTPU_TEID &&
		prof_idx <= ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER) ||
	       prof_idx == ICE_PROFID_IPV4_GTPU_TEID;
}

static bool ice_is_gtp_c_profile(u16 prof_idx)
{
	switch (prof_idx) {
	case ICE_PROFID_IPV4_GTPC_TEID:
	case ICE_PROFID_IPV4_GTPC_NO_TEID:
	case ICE_PROFID_IPV6_GTPC_TEID:
	case ICE_PROFID_IPV6_GTPC_NO_TEID:
		return true;
	default:
		return false;
	}
}

/**
 * ice_get_sw_prof_type - determine switch profile type
 * @hw: pointer to the HW structure
 * @fv: pointer to the switch field vector
 * @prof_idx: profile index to check
 */
static enum ice_prof_type
ice_get_sw_prof_type(struct ice_hw *hw, struct ice_fv *fv)
ice_get_sw_prof_type(struct ice_hw *hw, struct ice_fv *fv, u32 prof_idx)
{
	u16 i;

	if (ice_is_gtp_c_profile(prof_idx))
		return ICE_PROF_TUN_GTPC;

	if (ice_is_gtp_u_profile(prof_idx))
		return ICE_PROF_TUN_GTPU;

	for (i = 0; i < hw->blk[ICE_BLK_SW].es.fvw; i++) {
		/* UDP tunnel will have UDP_OF protocol ID and VNI offset */
		if (fv->ew[i].prot_id == (u8)ICE_PROT_UDP_OF &&
@@ -1860,7 +1887,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs,

		if (fv) {
			/* Determine field vector type */
			prof_type = ice_get_sw_prof_type(hw, fv);
			prof_type = ice_get_sw_prof_type(hw, fv, offset);

			if (req_profs & prof_type)
				set_bit((u16)offset, bm);
+5 −1
Original line number Diff line number Diff line
@@ -417,6 +417,8 @@ enum ice_tunnel_type {
	TNL_VXLAN = 0,
	TNL_GENEVE,
	TNL_GRETAP,
	TNL_GTPC,
	TNL_GTPU,
	__TNL_TYPE_CNT,
	TNL_LAST = 0xFF,
	TNL_ALL = 0xFF,
@@ -673,7 +675,9 @@ enum ice_prof_type {
	ICE_PROF_NON_TUN = 0x1,
	ICE_PROF_TUN_UDP = 0x2,
	ICE_PROF_TUN_GRE = 0x4,
	ICE_PROF_TUN_ALL = 0x6,
	ICE_PROF_TUN_GTPU = 0x8,
	ICE_PROF_TUN_GTPC = 0x10,
	ICE_PROF_TUN_ALL = 0x1E,
	ICE_PROF_ALL = 0xFF,
};

+19 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ enum ice_protocol_type {
	ICE_VXLAN,
	ICE_GENEVE,
	ICE_NVGRE,
	ICE_GTP,
	ICE_GTP_NO_PAY,
	ICE_VXLAN_GPE,
	ICE_SCTP_IL,
	ICE_PROTOCOL_LAST
@@ -52,6 +54,8 @@ enum ice_sw_tunnel_type {
	ICE_SW_TUN_VXLAN,
	ICE_SW_TUN_GENEVE,
	ICE_SW_TUN_NVGRE,
	ICE_SW_TUN_GTPU,
	ICE_SW_TUN_GTPC,
	ICE_ALL_TUNNELS /* All tunnel types including NVGRE */
};

@@ -182,6 +186,20 @@ struct ice_udp_tnl_hdr {
	__be32 vni;     /* only use lower 24-bits */
};

struct ice_udp_gtp_hdr {
	u8 flags;
	u8 msg_type;
	__be16 rsrvd_len;
	__be32 teid;
	__be16 rsrvd_seq_nbr;
	u8 rsrvd_n_pdu_nbr;
	u8 rsrvd_next_ext;
	u8 rsvrd_ext_len;
	u8 pdu_type;
	u8 qfi;
	u8 rsvrd;
};

struct ice_nvgre_hdr {
	__be16 flags;
	__be16 protocol;
@@ -198,6 +216,7 @@ union ice_prot_hdr {
	struct ice_sctp_hdr sctp_hdr;
	struct ice_udp_tnl_hdr tnl_hdr;
	struct ice_nvgre_hdr nvgre_hdr;
	struct ice_udp_gtp_hdr gtp_hdr;
};

/* This is mapping table entry that maps every word within a given protocol
+597 −18
Original line number Diff line number Diff line
@@ -726,6 +726,495 @@ static const u8 dummy_vlan_udp_ipv6_packet[] = {
	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
static const
struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_tcp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_UDP_OF,		34 },
	{ ICE_GTP,		42 },
	{ ICE_IPV4_IL,		62 },
	{ ICE_TCP_IL,		82 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv4_gtpu_ipv4_tcp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x08, 0x00,

	0x45, 0x00, 0x00, 0x58, /* IP 14 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
	0x00, 0x44, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
	0x00, 0x00, 0x00, 0x00,

	0x45, 0x00, 0x00, 0x28, /* IP 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x06, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* TCP 82 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */
static const
struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_udp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_UDP_OF,		34 },
	{ ICE_GTP,		42 },
	{ ICE_IPV4_IL,		62 },
	{ ICE_UDP_ILOS,		82 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv4_gtpu_ipv4_udp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x08, 0x00,

	0x45, 0x00, 0x00, 0x4c, /* IP 14 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
	0x00, 0x38, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
	0x00, 0x00, 0x00, 0x00,

	0x45, 0x00, 0x00, 0x1c, /* IP 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* UDP 82 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
static const
struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv6_tcp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_UDP_OF,		34 },
	{ ICE_GTP,		42 },
	{ ICE_IPV6_IL,		62 },
	{ ICE_TCP_IL,		102 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv4_gtpu_ipv6_tcp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x08, 0x00,

	0x45, 0x00, 0x00, 0x6c, /* IP 14 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
	0x00, 0x58, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
	0x00, 0x00, 0x00, 0x00,

	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
	0x00, 0x14, 0x06, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const
struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv6_udp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_UDP_OF,		34 },
	{ ICE_GTP,		42 },
	{ ICE_IPV6_IL,		62 },
	{ ICE_UDP_ILOS,		102 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv4_gtpu_ipv6_udp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x08, 0x00,

	0x45, 0x00, 0x00, 0x60, /* IP 14 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
	0x00, 0x4c, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
	0x00, 0x00, 0x00, 0x00,

	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
	0x00, 0x08, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const
struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv4_tcp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_UDP_OF,		54 },
	{ ICE_GTP,		62 },
	{ ICE_IPV4_IL,		82 },
	{ ICE_TCP_IL,		102 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv6_gtpu_ipv4_tcp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x86, 0xdd,

	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
	0x00, 0x44, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
	0x00, 0x44, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
	0x00, 0x00, 0x00, 0x00,

	0x45, 0x00, 0x00, 0x28, /* IP 82 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x06, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const
struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv4_udp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_UDP_OF,		54 },
	{ ICE_GTP,		62 },
	{ ICE_IPV4_IL,		82 },
	{ ICE_UDP_ILOS,		102 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv6_gtpu_ipv4_udp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x86, 0xdd,

	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
	0x00, 0x38, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
	0x00, 0x38, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
	0x00, 0x00, 0x00, 0x00,

	0x45, 0x00, 0x00, 0x1c, /* IP 82 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const
struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv6_tcp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_UDP_OF,		54 },
	{ ICE_GTP,		62 },
	{ ICE_IPV6_IL,		82 },
	{ ICE_TCP_IL,		122 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv6_gtpu_ipv6_tcp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x86, 0xdd,

	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
	0x00, 0x58, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
	0x00, 0x58, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
	0x00, 0x00, 0x00, 0x00,

	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
	0x00, 0x14, 0x06, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* TCP 122 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const
struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv6_udp_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_UDP_OF,		54 },
	{ ICE_GTP,		62 },
	{ ICE_IPV6_IL,		82 },
	{ ICE_UDP_ILOS,		122 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv6_gtpu_ipv6_udp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x86, 0xdd,

	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
	0x00, 0x4c, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
	0x00, 0x4c, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
	0x00, 0x00, 0x00, 0x00,

	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
	0x00, 0x08, 0x11, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* UDP 122 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

static const u8 dummy_ipv4_gtpu_ipv4_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x08, 0x00,

	0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */
	0x00, 0x00, 0x40, 0x00,
	0x40, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
	0x00, 0x00, 0x00, 0x00,

	0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x85,

	0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
	0x00, 0x00, 0x00, 0x00,

	0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */
	0x00, 0x00, 0x40, 0x00,
	0x40, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00,
};

static const
struct ice_dummy_pkt_offsets dummy_ipv4_gtp_no_pay_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_UDP_OF,		34 },
	{ ICE_GTP_NO_PAY,	42 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const
struct ice_dummy_pkt_offsets dummy_ipv6_gtp_no_pay_packet_offsets[] = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_UDP_OF,		54 },
	{ ICE_GTP_NO_PAY,	62 },
	{ ICE_PROTOCOL_LAST,	0 },
};

static const u8 dummy_ipv6_gtp_packet[] = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x86, 0xdd,

	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
	0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
	0x00, 0x00, 0x00, 0x00,

	0x30, 0x00, 0x00, 0x28, /* ICE_GTP 62 */
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00,
};

#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
	(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \
	 (DUMMY_ETH_HDR_LEN * \
@@ -4058,6 +4547,8 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
	{ ICE_VXLAN,		{ 8, 10, 12, 14 } },
	{ ICE_GENEVE,		{ 8, 10, 12, 14 } },
	{ ICE_NVGRE,		{ 0, 2, 4, 6 } },
	{ ICE_GTP,		{ 8, 10, 12, 14, 16, 18, 20, 22 } },
	{ ICE_GTP_NO_PAY,	{ 8, 10, 12, 14 } },
};

static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
@@ -4076,6 +4567,8 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
	{ ICE_VXLAN,		ICE_UDP_OF_HW },
	{ ICE_GENEVE,		ICE_UDP_OF_HW },
	{ ICE_NVGRE,		ICE_GRE_OF_HW },
	{ ICE_GTP,		ICE_UDP_OF_HW },
	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
};

/**
@@ -4745,6 +5238,8 @@ static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
	case ICE_SW_TUN_GENEVE:
	case ICE_SW_TUN_VXLAN:
	case ICE_SW_TUN_NVGRE:
	case ICE_SW_TUN_GTPU:
	case ICE_SW_TUN_GTPC:
		*mask = ICE_TUN_FLAG_MASK;
		return true;

@@ -4810,6 +5305,12 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
	case ICE_SW_TUN_NVGRE:
		prof_type = ICE_PROF_TUN_GRE;
		break;
	case ICE_SW_TUN_GTPU:
		prof_type = ICE_PROF_TUN_GTPU;
		break;
	case ICE_SW_TUN_GTPC:
		prof_type = ICE_PROF_TUN_GTPC;
		break;
	case ICE_SW_TUN_AND_NON_TUN:
	default:
		prof_type = ICE_PROF_ALL;
@@ -5010,17 +5511,17 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		      const u8 **pkt, u16 *pkt_len,
		      const struct ice_dummy_pkt_offsets **offsets)
{
	bool tcp = false, udp = false, ipv6 = false, vlan = false;
	bool ipv6_il = false;
	bool inner_tcp = false, inner_udp = false, outer_ipv6 = false;
	bool vlan = false, inner_ipv6 = false, gtp_no_pay = false;
	u16 i;

	for (i = 0; i < lkups_cnt; i++) {
		if (lkups[i].type == ICE_UDP_ILOS)
			udp = true;
			inner_udp = true;
		else if (lkups[i].type == ICE_TCP_IL)
			tcp = true;
			inner_tcp = true;
		else if (lkups[i].type == ICE_IPV6_OFOS)
			ipv6 = true;
			outer_ipv6 = true;
		else if (lkups[i].type == ICE_VLAN_OFOS)
			vlan = true;
		else if (lkups[i].type == ICE_ETYPE_OL &&
@@ -5028,29 +5529,103 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
			 lkups[i].m_u.ethertype.ethtype_id ==
				cpu_to_be16(0xFFFF))
			ipv6 = true;
			outer_ipv6 = true;
		else if (lkups[i].type == ICE_ETYPE_IL &&
			 lkups[i].h_u.ethertype.ethtype_id ==
				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
			 lkups[i].m_u.ethertype.ethtype_id ==
				cpu_to_be16(0xFFFF))
			ipv6_il = true;
			inner_ipv6 = true;
		else if (lkups[i].type == ICE_IPV6_IL)
			inner_ipv6 = true;
		else if (lkups[i].type == ICE_GTP_NO_PAY)
			gtp_no_pay = true;
	}

	if (tun_type == ICE_SW_TUN_GTPU) {
		if (outer_ipv6) {
			if (gtp_no_pay) {
				*pkt = dummy_ipv6_gtp_packet;
				*pkt_len = sizeof(dummy_ipv6_gtp_packet);
				*offsets = dummy_ipv6_gtp_no_pay_packet_offsets;
			} else if (inner_ipv6) {
				if (inner_udp) {
					*pkt = dummy_ipv6_gtpu_ipv6_udp_packet;
					*pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_udp_packet);
					*offsets = dummy_ipv6_gtpu_ipv6_udp_packet_offsets;
				} else {
					*pkt = dummy_ipv6_gtpu_ipv6_tcp_packet;
					*pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_tcp_packet);
					*offsets = dummy_ipv6_gtpu_ipv6_tcp_packet_offsets;
				}
			} else {
				if (inner_udp) {
					*pkt = dummy_ipv6_gtpu_ipv4_udp_packet;
					*pkt_len = sizeof(dummy_ipv6_gtpu_ipv4_udp_packet);
					*offsets = dummy_ipv6_gtpu_ipv4_udp_packet_offsets;
				} else {
					*pkt = dummy_ipv6_gtpu_ipv4_tcp_packet;
				*pkt_len = sizeof(dummy_ipv6_gtpu_ipv4_tcp_packet);
					*offsets = dummy_ipv6_gtpu_ipv4_tcp_packet_offsets;
				}
			}
		} else {
			if (gtp_no_pay) {
				*pkt = dummy_ipv4_gtpu_ipv4_packet;
				*pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
				*offsets = dummy_ipv4_gtp_no_pay_packet_offsets;
			} else if (inner_ipv6) {
				if (inner_udp) {
					*pkt = dummy_ipv4_gtpu_ipv6_udp_packet;
					*pkt_len = sizeof(dummy_ipv4_gtpu_ipv6_udp_packet);
					*offsets = dummy_ipv4_gtpu_ipv6_udp_packet_offsets;
				} else {
					*pkt = dummy_ipv4_gtpu_ipv6_tcp_packet;
					*pkt_len = sizeof(dummy_ipv4_gtpu_ipv6_tcp_packet);
					*offsets = dummy_ipv4_gtpu_ipv6_tcp_packet_offsets;
				}
			} else {
				if (inner_udp) {
					*pkt = dummy_ipv4_gtpu_ipv4_udp_packet;
					*pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_udp_packet);
					*offsets = dummy_ipv4_gtpu_ipv4_udp_packet_offsets;
				} else {
					*pkt = dummy_ipv4_gtpu_ipv4_tcp_packet;
					*pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_tcp_packet);
					*offsets = dummy_ipv4_gtpu_ipv4_tcp_packet_offsets;
				}
			}
		}
		return;
	}

	if (tun_type == ICE_SW_TUN_GTPC) {
		if (outer_ipv6) {
			*pkt = dummy_ipv6_gtp_packet;
			*pkt_len = sizeof(dummy_ipv6_gtp_packet);
			*offsets = dummy_ipv6_gtp_no_pay_packet_offsets;
		} else {
			*pkt = dummy_ipv4_gtpu_ipv4_packet;
			*pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
			*offsets = dummy_ipv4_gtp_no_pay_packet_offsets;
		}
		return;
	}

	if (tun_type == ICE_SW_TUN_NVGRE) {
		if (tcp && ipv6_il) {
		if (inner_tcp && inner_ipv6) {
			*pkt = dummy_gre_ipv6_tcp_packet;
			*pkt_len = sizeof(dummy_gre_ipv6_tcp_packet);
			*offsets = dummy_gre_ipv6_tcp_packet_offsets;
			return;
		}
		if (tcp) {
		if (inner_tcp) {
			*pkt = dummy_gre_tcp_packet;
			*pkt_len = sizeof(dummy_gre_tcp_packet);
			*offsets = dummy_gre_tcp_packet_offsets;
			return;
		}
		if (ipv6_il) {
		if (inner_ipv6) {
			*pkt = dummy_gre_ipv6_udp_packet;
			*pkt_len = sizeof(dummy_gre_ipv6_udp_packet);
			*offsets = dummy_gre_ipv6_udp_packet_offsets;
@@ -5064,19 +5639,19 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,

	if (tun_type == ICE_SW_TUN_VXLAN ||
	    tun_type == ICE_SW_TUN_GENEVE) {
		if (tcp && ipv6_il) {
		if (inner_tcp && inner_ipv6) {
			*pkt = dummy_udp_tun_ipv6_tcp_packet;
			*pkt_len = sizeof(dummy_udp_tun_ipv6_tcp_packet);
			*offsets = dummy_udp_tun_ipv6_tcp_packet_offsets;
			return;
		}
		if (tcp) {
		if (inner_tcp) {
			*pkt = dummy_udp_tun_tcp_packet;
			*pkt_len = sizeof(dummy_udp_tun_tcp_packet);
			*offsets = dummy_udp_tun_tcp_packet_offsets;
			return;
		}
		if (ipv6_il) {
		if (inner_ipv6) {
			*pkt = dummy_udp_tun_ipv6_udp_packet;
			*pkt_len = sizeof(dummy_udp_tun_ipv6_udp_packet);
			*offsets = dummy_udp_tun_ipv6_udp_packet_offsets;
@@ -5088,7 +5663,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		return;
	}

	if (udp && !ipv6) {
	if (inner_udp && !outer_ipv6) {
		if (vlan) {
			*pkt = dummy_vlan_udp_packet;
			*pkt_len = sizeof(dummy_vlan_udp_packet);
@@ -5099,7 +5674,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		*pkt_len = sizeof(dummy_udp_packet);
		*offsets = dummy_udp_packet_offsets;
		return;
	} else if (udp && ipv6) {
	} else if (inner_udp && outer_ipv6) {
		if (vlan) {
			*pkt = dummy_vlan_udp_ipv6_packet;
			*pkt_len = sizeof(dummy_vlan_udp_ipv6_packet);
@@ -5110,7 +5685,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		*pkt_len = sizeof(dummy_udp_ipv6_packet);
		*offsets = dummy_udp_ipv6_packet_offsets;
		return;
	} else if ((tcp && ipv6) || ipv6) {
	} else if ((inner_tcp && outer_ipv6) || outer_ipv6) {
		if (vlan) {
			*pkt = dummy_vlan_tcp_ipv6_packet;
			*pkt_len = sizeof(dummy_vlan_tcp_ipv6_packet);
@@ -5216,6 +5791,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		case ICE_GENEVE:
			len = sizeof(struct ice_udp_tnl_hdr);
			break;
		case ICE_GTP_NO_PAY:
		case ICE_GTP:
			len = sizeof(struct ice_udp_gtp_hdr);
			break;
		default:
			return -EINVAL;
		}
Loading