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

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
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <net/gre.h> #include <net/gre.h>
#include <net/udp_tunnel.h> #include <net/udp_tunnel.h>
#include <net/vxlan.h> #include <net/vxlan.h>
#include <net/gtp.h>
#if IS_ENABLED(CONFIG_DCB) #if IS_ENABLED(CONFIG_DCB)
#include <scsi/iscsi_proto.h> #include <scsi/iscsi_proto.h>
#endif /* CONFIG_DCB */ #endif /* CONFIG_DCB */
......
...@@ -1804,16 +1804,43 @@ static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw) ...@@ -1804,16 +1804,43 @@ static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw)
return bld; 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 * ice_get_sw_prof_type - determine switch profile type
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @fv: pointer to the switch field vector * @fv: pointer to the switch field vector
* @prof_idx: profile index to check
*/ */
static enum ice_prof_type 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; 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++) { for (i = 0; i < hw->blk[ICE_BLK_SW].es.fvw; i++) {
/* UDP tunnel will have UDP_OF protocol ID and VNI offset */ /* UDP tunnel will have UDP_OF protocol ID and VNI offset */
if (fv->ew[i].prot_id == (u8)ICE_PROT_UDP_OF && 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, ...@@ -1860,7 +1887,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs,
if (fv) { if (fv) {
/* Determine field vector type */ /* 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) if (req_profs & prof_type)
set_bit((u16)offset, bm); set_bit((u16)offset, bm);
......
...@@ -417,6 +417,8 @@ enum ice_tunnel_type { ...@@ -417,6 +417,8 @@ enum ice_tunnel_type {
TNL_VXLAN = 0, TNL_VXLAN = 0,
TNL_GENEVE, TNL_GENEVE,
TNL_GRETAP, TNL_GRETAP,
TNL_GTPC,
TNL_GTPU,
__TNL_TYPE_CNT, __TNL_TYPE_CNT,
TNL_LAST = 0xFF, TNL_LAST = 0xFF,
TNL_ALL = 0xFF, TNL_ALL = 0xFF,
...@@ -673,7 +675,9 @@ enum ice_prof_type { ...@@ -673,7 +675,9 @@ enum ice_prof_type {
ICE_PROF_NON_TUN = 0x1, ICE_PROF_NON_TUN = 0x1,
ICE_PROF_TUN_UDP = 0x2, ICE_PROF_TUN_UDP = 0x2,
ICE_PROF_TUN_GRE = 0x4, 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, ICE_PROF_ALL = 0xFF,
}; };
......
...@@ -41,6 +41,8 @@ enum ice_protocol_type { ...@@ -41,6 +41,8 @@ enum ice_protocol_type {
ICE_VXLAN, ICE_VXLAN,
ICE_GENEVE, ICE_GENEVE,
ICE_NVGRE, ICE_NVGRE,
ICE_GTP,
ICE_GTP_NO_PAY,
ICE_VXLAN_GPE, ICE_VXLAN_GPE,
ICE_SCTP_IL, ICE_SCTP_IL,
ICE_PROTOCOL_LAST ICE_PROTOCOL_LAST
...@@ -52,6 +54,8 @@ enum ice_sw_tunnel_type { ...@@ -52,6 +54,8 @@ enum ice_sw_tunnel_type {
ICE_SW_TUN_VXLAN, ICE_SW_TUN_VXLAN,
ICE_SW_TUN_GENEVE, ICE_SW_TUN_GENEVE,
ICE_SW_TUN_NVGRE, ICE_SW_TUN_NVGRE,
ICE_SW_TUN_GTPU,
ICE_SW_TUN_GTPC,
ICE_ALL_TUNNELS /* All tunnel types including NVGRE */ ICE_ALL_TUNNELS /* All tunnel types including NVGRE */
}; };
...@@ -182,6 +186,20 @@ struct ice_udp_tnl_hdr { ...@@ -182,6 +186,20 @@ struct ice_udp_tnl_hdr {
__be32 vni; /* only use lower 24-bits */ __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 { struct ice_nvgre_hdr {
__be16 flags; __be16 flags;
__be16 protocol; __be16 protocol;
...@@ -198,6 +216,7 @@ union ice_prot_hdr { ...@@ -198,6 +216,7 @@ union ice_prot_hdr {
struct ice_sctp_hdr sctp_hdr; struct ice_sctp_hdr sctp_hdr;
struct ice_udp_tnl_hdr tnl_hdr; struct ice_udp_tnl_hdr tnl_hdr;
struct ice_nvgre_hdr nvgre_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 /* This is mapping table entry that maps every word within a given protocol
......
...@@ -726,6 +726,495 @@ static const u8 dummy_vlan_udp_ipv6_packet[] = { ...@@ -726,6 +726,495 @@ static const u8 dummy_vlan_udp_ipv6_packet[] = {
0x00, 0x00, /* 2 bytes for 4 byte alignment */ 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 \ #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \ (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \
(DUMMY_ETH_HDR_LEN * \ (DUMMY_ETH_HDR_LEN * \
...@@ -4058,6 +4547,8 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { ...@@ -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_VXLAN, { 8, 10, 12, 14 } },
{ ICE_GENEVE, { 8, 10, 12, 14 } }, { ICE_GENEVE, { 8, 10, 12, 14 } },
{ ICE_NVGRE, { 0, 2, 4, 6 } }, { 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] = { 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] = { ...@@ -4076,6 +4567,8 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
{ ICE_VXLAN, ICE_UDP_OF_HW }, { ICE_VXLAN, ICE_UDP_OF_HW },
{ ICE_GENEVE, ICE_UDP_OF_HW }, { ICE_GENEVE, ICE_UDP_OF_HW },
{ ICE_NVGRE, ICE_GRE_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) ...@@ -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_GENEVE:
case ICE_SW_TUN_VXLAN: case ICE_SW_TUN_VXLAN:
case ICE_SW_TUN_NVGRE: case ICE_SW_TUN_NVGRE:
case ICE_SW_TUN_GTPU:
case ICE_SW_TUN_GTPC:
*mask = ICE_TUN_FLAG_MASK; *mask = ICE_TUN_FLAG_MASK;
return true; return true;
...@@ -4810,6 +5305,12 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo, ...@@ -4810,6 +5305,12 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
case ICE_SW_TUN_NVGRE: case ICE_SW_TUN_NVGRE:
prof_type = ICE_PROF_TUN_GRE; prof_type = ICE_PROF_TUN_GRE;
break; 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: case ICE_SW_TUN_AND_NON_TUN:
default: default:
prof_type = ICE_PROF_ALL; prof_type = ICE_PROF_ALL;
...@@ -5010,17 +5511,17 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, ...@@ -5010,17 +5511,17 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
const u8 **pkt, u16 *pkt_len, const u8 **pkt, u16 *pkt_len,
const struct ice_dummy_pkt_offsets **offsets) const struct ice_dummy_pkt_offsets **offsets)
{ {
bool tcp = false, udp = false, ipv6 = false, vlan = false; bool inner_tcp = false, inner_udp = false, outer_ipv6 = false;
bool ipv6_il = false; bool vlan = false, inner_ipv6 = false, gtp_no_pay = false;
u16 i; u16 i;
for (i = 0; i < lkups_cnt; i++) { for (i = 0; i < lkups_cnt; i++) {
if (lkups[i].type == ICE_UDP_ILOS) if (lkups[i].type == ICE_UDP_ILOS)
udp = true; inner_udp = true;
else if (lkups[i].type == ICE_TCP_IL) else if (lkups[i].type == ICE_TCP_IL)
tcp = true; inner_tcp = true;
else if (lkups[i].type == ICE_IPV6_OFOS) else if (lkups[i].type == ICE_IPV6_OFOS)
ipv6 = true; outer_ipv6 = true;
else if (lkups[i].type == ICE_VLAN_OFOS) else if (lkups[i].type == ICE_VLAN_OFOS)
vlan = true; vlan = true;
else if (lkups[i].type == ICE_ETYPE_OL && 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, ...@@ -5028,29 +5529,103 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
cpu_to_be16(ICE_IPV6_ETHER_ID) && cpu_to_be16(ICE_IPV6_ETHER_ID) &&
lkups[i].m_u.ethertype.ethtype_id == lkups[i].m_u.ethertype.ethtype_id ==
cpu_to_be16(0xFFFF)) cpu_to_be16(0xFFFF))
ipv6 = true; outer_ipv6 = true;
else if (lkups[i].type == ICE_ETYPE_IL && else if (lkups[i].type == ICE_ETYPE_IL &&
lkups[i].h_u.ethertype.ethtype_id == lkups[i].h_u.ethertype.ethtype_id ==
cpu_to_be16(ICE_IPV6_ETHER_ID) && cpu_to_be16(ICE_IPV6_ETHER_ID) &&
lkups[i].m_u.ethertype.ethtype_id == lkups[i].m_u.ethertype.ethtype_id ==
cpu_to_be16(0xFFFF)) 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 (tun_type == ICE_SW_TUN_NVGRE) {
if (tcp && ipv6_il) { if (inner_tcp && inner_ipv6) {
*pkt = dummy_gre_ipv6_tcp_packet; *pkt = dummy_gre_ipv6_tcp_packet;
*pkt_len = sizeof(dummy_gre_ipv6_tcp_packet); *pkt_len = sizeof(dummy_gre_ipv6_tcp_packet);
*offsets = dummy_gre_ipv6_tcp_packet_offsets; *offsets = dummy_gre_ipv6_tcp_packet_offsets;
return; return;
} }
if (tcp) { if (inner_tcp) {
*pkt = dummy_gre_tcp_packet; *pkt = dummy_gre_tcp_packet;
*pkt_len = sizeof(dummy_gre_tcp_packet); *pkt_len = sizeof(dummy_gre_tcp_packet);
*offsets = dummy_gre_tcp_packet_offsets; *offsets = dummy_gre_tcp_packet_offsets;
return; return;
} }
if (ipv6_il) { if (inner_ipv6) {
*pkt = dummy_gre_ipv6_udp_packet; *pkt = dummy_gre_ipv6_udp_packet;
*pkt_len = sizeof(dummy_gre_ipv6_udp_packet); *pkt_len = sizeof(dummy_gre_ipv6_udp_packet);
*offsets = dummy_gre_ipv6_udp_packet_offsets; *offsets = dummy_gre_ipv6_udp_packet_offsets;
...@@ -5064,19 +5639,19 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, ...@@ -5064,19 +5639,19 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
if (tun_type == ICE_SW_TUN_VXLAN || if (tun_type == ICE_SW_TUN_VXLAN ||
tun_type == ICE_SW_TUN_GENEVE) { tun_type == ICE_SW_TUN_GENEVE) {
if (tcp && ipv6_il) { if (inner_tcp && inner_ipv6) {
*pkt = dummy_udp_tun_ipv6_tcp_packet; *pkt = dummy_udp_tun_ipv6_tcp_packet;
*pkt_len = sizeof(dummy_udp_tun_ipv6_tcp_packet); *pkt_len = sizeof(dummy_udp_tun_ipv6_tcp_packet);
*offsets = dummy_udp_tun_ipv6_tcp_packet_offsets; *offsets = dummy_udp_tun_ipv6_tcp_packet_offsets;
return; return;
} }
if (tcp) { if (inner_tcp) {
*pkt = dummy_udp_tun_tcp_packet; *pkt = dummy_udp_tun_tcp_packet;
*pkt_len = sizeof(dummy_udp_tun_tcp_packet); *pkt_len = sizeof(dummy_udp_tun_tcp_packet);
*offsets = dummy_udp_tun_tcp_packet_offsets; *offsets = dummy_udp_tun_tcp_packet_offsets;
return; return;
} }
if (ipv6_il) { if (inner_ipv6) {
*pkt = dummy_udp_tun_ipv6_udp_packet; *pkt = dummy_udp_tun_ipv6_udp_packet;
*pkt_len = sizeof(dummy_udp_tun_ipv6_udp_packet); *pkt_len = sizeof(dummy_udp_tun_ipv6_udp_packet);
*offsets = dummy_udp_tun_ipv6_udp_packet_offsets; *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, ...@@ -5088,7 +5663,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
return; return;
} }
if (udp && !ipv6) { if (inner_udp && !outer_ipv6) {
if (vlan) { if (vlan) {
*pkt = dummy_vlan_udp_packet; *pkt = dummy_vlan_udp_packet;
*pkt_len = sizeof(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, ...@@ -5099,7 +5674,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
*pkt_len = sizeof(dummy_udp_packet); *pkt_len = sizeof(dummy_udp_packet);
*offsets = dummy_udp_packet_offsets; *offsets = dummy_udp_packet_offsets;
return; return;
} else if (udp && ipv6) { } else if (inner_udp && outer_ipv6) {
if (vlan) { if (vlan) {
*pkt = dummy_vlan_udp_ipv6_packet; *pkt = dummy_vlan_udp_ipv6_packet;
*pkt_len = sizeof(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, ...@@ -5110,7 +5685,7 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
*pkt_len = sizeof(dummy_udp_ipv6_packet); *pkt_len = sizeof(dummy_udp_ipv6_packet);
*offsets = dummy_udp_ipv6_packet_offsets; *offsets = dummy_udp_ipv6_packet_offsets;
return; return;
} else if ((tcp && ipv6) || ipv6) { } else if ((inner_tcp && outer_ipv6) || outer_ipv6) {
if (vlan) { if (vlan) {
*pkt = dummy_vlan_tcp_ipv6_packet; *pkt = dummy_vlan_tcp_ipv6_packet;
*pkt_len = sizeof(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, ...@@ -5216,6 +5791,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
case ICE_GENEVE: case ICE_GENEVE:
len = sizeof(struct ice_udp_tnl_hdr); len = sizeof(struct ice_udp_tnl_hdr);
break; break;
case ICE_GTP_NO_PAY:
case ICE_GTP:
len = sizeof(struct ice_udp_gtp_hdr);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -14,6 +14,15 @@ ...@@ -14,6 +14,15 @@
#define ICE_VSI_INVAL_ID 0xffff #define ICE_VSI_INVAL_ID 0xffff
#define ICE_INVAL_Q_HANDLE 0xFFFF #define ICE_INVAL_Q_HANDLE 0xFFFF
/* Switch Profile IDs for Profile related switch rules */
#define ICE_PROFID_IPV4_GTPC_TEID 41
#define ICE_PROFID_IPV4_GTPC_NO_TEID 42
#define ICE_PROFID_IPV4_GTPU_TEID 43
#define ICE_PROFID_IPV6_GTPC_TEID 44
#define ICE_PROFID_IPV6_GTPC_NO_TEID 45
#define ICE_PROFID_IPV6_GTPU_TEID 46
#define ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER 70
#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \ #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr)) (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
......
...@@ -27,6 +27,9 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ...@@ -27,6 +27,9 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
if (flags & ICE_TC_FLWR_FIELD_ENC_DST_MAC) if (flags & ICE_TC_FLWR_FIELD_ENC_DST_MAC)
lkups_cnt++; lkups_cnt++;
if (flags & ICE_TC_FLWR_FIELD_ENC_OPTS)
lkups_cnt++;
if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 | if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 |
ICE_TC_FLWR_FIELD_ENC_DEST_IPV4 | ICE_TC_FLWR_FIELD_ENC_DEST_IPV4 |
ICE_TC_FLWR_FIELD_ENC_SRC_IPV6 | ICE_TC_FLWR_FIELD_ENC_SRC_IPV6 |
...@@ -102,6 +105,11 @@ ice_proto_type_from_tunnel(enum ice_tunnel_type type) ...@@ -102,6 +105,11 @@ ice_proto_type_from_tunnel(enum ice_tunnel_type type)
return ICE_GENEVE; return ICE_GENEVE;
case TNL_GRETAP: case TNL_GRETAP:
return ICE_NVGRE; return ICE_NVGRE;
case TNL_GTPU:
/* NO_PAY profiles will not work with GTP-U */
return ICE_GTP;
case TNL_GTPC:
return ICE_GTP_NO_PAY;
default: default:
return 0; return 0;
} }
...@@ -117,6 +125,10 @@ ice_sw_type_from_tunnel(enum ice_tunnel_type type) ...@@ -117,6 +125,10 @@ ice_sw_type_from_tunnel(enum ice_tunnel_type type)
return ICE_SW_TUN_GENEVE; return ICE_SW_TUN_GENEVE;
case TNL_GRETAP: case TNL_GRETAP:
return ICE_SW_TUN_NVGRE; return ICE_SW_TUN_NVGRE;
case TNL_GTPU:
return ICE_SW_TUN_GTPU;
case TNL_GTPC:
return ICE_SW_TUN_GTPC;
default: default:
return ICE_NON_TUN; return ICE_NON_TUN;
} }
...@@ -143,7 +155,15 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, ...@@ -143,7 +155,15 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
break; break;
case TNL_GRETAP: case TNL_GRETAP:
list[i].h_u.nvgre_hdr.tni_flow = fltr->tenant_id; list[i].h_u.nvgre_hdr.tni_flow = fltr->tenant_id;
memcpy(&list[i].m_u.nvgre_hdr.tni_flow, "\xff\xff\xff\xff", 4); memcpy(&list[i].m_u.nvgre_hdr.tni_flow,
"\xff\xff\xff\xff", 4);
i++;
break;
case TNL_GTPC:
case TNL_GTPU:
list[i].h_u.gtp_hdr.teid = fltr->tenant_id;
memcpy(&list[i].m_u.gtp_hdr.teid,
"\xff\xff\xff\xff", 4);
i++; i++;
break; break;
default: default:
...@@ -160,6 +180,24 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, ...@@ -160,6 +180,24 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
i++; i++;
} }
if (flags & ICE_TC_FLWR_FIELD_ENC_OPTS &&
(fltr->tunnel_type == TNL_GTPU || fltr->tunnel_type == TNL_GTPC)) {
list[i].type = ice_proto_type_from_tunnel(fltr->tunnel_type);
if (fltr->gtp_pdu_info_masks.pdu_type) {
list[i].h_u.gtp_hdr.pdu_type =
fltr->gtp_pdu_info_keys.pdu_type << 4;
memcpy(&list[i].m_u.gtp_hdr.pdu_type, "\xf0", 1);
}
if (fltr->gtp_pdu_info_masks.qfi) {
list[i].h_u.gtp_hdr.qfi = fltr->gtp_pdu_info_keys.qfi;
memcpy(&list[i].m_u.gtp_hdr.qfi, "\x3f", 1);
}
i++;
}
if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 | if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 |
ICE_TC_FLWR_FIELD_ENC_DEST_IPV4)) { ICE_TC_FLWR_FIELD_ENC_DEST_IPV4)) {
list[i].type = ice_proto_type_from_ipv4(false); list[i].type = ice_proto_type_from_ipv4(false);
...@@ -361,6 +399,12 @@ static int ice_tc_tun_get_type(struct net_device *tunnel_dev) ...@@ -361,6 +399,12 @@ static int ice_tc_tun_get_type(struct net_device *tunnel_dev)
if (netif_is_gretap(tunnel_dev) || if (netif_is_gretap(tunnel_dev) ||
netif_is_ip6gretap(tunnel_dev)) netif_is_ip6gretap(tunnel_dev))
return TNL_GRETAP; return TNL_GRETAP;
/* Assume GTP-U by default in case of GTP netdev.
* GTP-C may be selected later, based on enc_dst_port.
*/
if (netif_is_gtp(tunnel_dev))
return TNL_GTPU;
return TNL_LAST; return TNL_LAST;
} }
...@@ -760,6 +804,40 @@ ice_get_tunnel_device(struct net_device *dev, struct flow_rule *rule) ...@@ -760,6 +804,40 @@ ice_get_tunnel_device(struct net_device *dev, struct flow_rule *rule)
return NULL; return NULL;
} }
/**
* ice_parse_gtp_type - Sets GTP tunnel type to GTP-U or GTP-C
* @match: Flow match structure
* @fltr: Pointer to filter structure
*
* GTP-C/GTP-U is selected based on destination port number (enc_dst_port).
* Before calling this funtcion, fltr->tunnel_type should be set to TNL_GTPU,
* therefore making GTP-U the default choice (when destination port number is
* not specified).
*/
static int
ice_parse_gtp_type(struct flow_match_ports match,
struct ice_tc_flower_fltr *fltr)
{
u16 dst_port;
if (match.key->dst) {
dst_port = be16_to_cpu(match.key->dst);
switch (dst_port) {
case 2152:
break;
case 2123:
fltr->tunnel_type = TNL_GTPC;
break;
default:
NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported GTP port number");
return -EINVAL;
}
}
return 0;
}
static int static int
ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule, ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule,
struct ice_tc_flower_fltr *fltr) struct ice_tc_flower_fltr *fltr)
...@@ -815,8 +893,28 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule, ...@@ -815,8 +893,28 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule,
struct flow_match_ports match; struct flow_match_ports match;
flow_rule_match_enc_ports(rule, &match); flow_rule_match_enc_ports(rule, &match);
if (fltr->tunnel_type != TNL_GTPU) {
if (ice_tc_set_port(match, fltr, headers, true)) if (ice_tc_set_port(match, fltr, headers, true))
return -EINVAL; return -EINVAL;
} else {
if (ice_parse_gtp_type(match, fltr))
return -EINVAL;
}
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS)) {
struct flow_match_enc_opts match;
flow_rule_match_enc_opts(rule, &match);
memcpy(&fltr->gtp_pdu_info_keys, &match.key->data[0],
sizeof(struct gtp_pdu_session_info));
memcpy(&fltr->gtp_pdu_info_masks, &match.mask->data[0],
sizeof(struct gtp_pdu_session_info));
fltr->flags |= ICE_TC_FLWR_FIELD_ENC_OPTS;
} }
return 0; return 0;
...@@ -854,6 +952,7 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, ...@@ -854,6 +952,7 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_IP) | BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
BIT(FLOW_DISSECTOR_KEY_PORTS))) { BIT(FLOW_DISSECTOR_KEY_PORTS))) {
NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used"); NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used");
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT BIT(15) #define ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT BIT(15)
#define ICE_TC_FLWR_FIELD_ENC_DST_MAC BIT(16) #define ICE_TC_FLWR_FIELD_ENC_DST_MAC BIT(16)
#define ICE_TC_FLWR_FIELD_ETH_TYPE_ID BIT(17) #define ICE_TC_FLWR_FIELD_ETH_TYPE_ID BIT(17)
#define ICE_TC_FLWR_FIELD_ENC_OPTS BIT(18)
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF #define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
...@@ -119,6 +120,8 @@ struct ice_tc_flower_fltr { ...@@ -119,6 +120,8 @@ struct ice_tc_flower_fltr {
struct ice_tc_flower_lyr_2_4_hdrs inner_headers; struct ice_tc_flower_lyr_2_4_hdrs inner_headers;
struct ice_vsi *src_vsi; struct ice_vsi *src_vsi;
__be32 tenant_id; __be32 tenant_id;
struct gtp_pdu_session_info gtp_pdu_info_keys;
struct gtp_pdu_session_info gtp_pdu_info_masks;
u32 flags; u32 flags;
u8 tunnel_type; u8 tunnel_type;
struct ice_tc_flower_action action; struct ice_tc_flower_action action;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment