mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:38:03 +00:00
ice: Add support for PFCP hardware offload in switchdev
Add support for creating PFCP filters in switchdev mode. Add support for parsing PFCP-specific tc options: S flag and SEID. To create a PFCP filter, a special netdev must be created and passed to tc command: ip link add pfcp0 type pfcp tc filter add dev eth0 ingress prio 1 flower pfcp_opts \ 1:123/ff:fffffffffffffff0 skip_hw action mirred egress redirect \ dev pfcp0 Changes in iproute2 [1] are required to be able to use pfcp_opts in tc. ICE COMMS package is required to create a filter as it contains PFCP profiles. Link: https://lore.kernel.org/netdev/20230614091758.11180-1-marcin.szycik@linux.intel.com [1] Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2312dfdfab
commit
784feaa65d
@ -721,6 +721,12 @@ static bool ice_is_gtp_c_profile(u16 prof_idx)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ice_is_pfcp_profile(u16 prof_idx)
|
||||
{
|
||||
return prof_idx >= ICE_PROFID_IPV4_PFCP_NODE &&
|
||||
prof_idx <= ICE_PROFID_IPV6_PFCP_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_sw_prof_type - determine switch profile type
|
||||
* @hw: pointer to the HW structure
|
||||
@ -738,6 +744,9 @@ static enum ice_prof_type ice_get_sw_prof_type(struct ice_hw *hw,
|
||||
if (ice_is_gtp_u_profile(prof_idx))
|
||||
return ICE_PROF_TUN_GTPU;
|
||||
|
||||
if (ice_is_pfcp_profile(prof_idx))
|
||||
return ICE_PROF_TUN_PFCP;
|
||||
|
||||
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 &&
|
||||
|
@ -93,6 +93,7 @@ enum ice_tunnel_type {
|
||||
TNL_GRETAP,
|
||||
TNL_GTPC,
|
||||
TNL_GTPU,
|
||||
TNL_PFCP,
|
||||
__TNL_TYPE_CNT,
|
||||
TNL_LAST = 0xFF,
|
||||
TNL_ALL = 0xFF,
|
||||
@ -358,7 +359,8 @@ enum ice_prof_type {
|
||||
ICE_PROF_TUN_GRE = 0x4,
|
||||
ICE_PROF_TUN_GTPU = 0x8,
|
||||
ICE_PROF_TUN_GTPC = 0x10,
|
||||
ICE_PROF_TUN_ALL = 0x1E,
|
||||
ICE_PROF_TUN_PFCP = 0x20,
|
||||
ICE_PROF_TUN_ALL = 0x3E,
|
||||
ICE_PROF_ALL = 0xFF,
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,7 @@ enum ice_protocol_type {
|
||||
ICE_NVGRE,
|
||||
ICE_GTP,
|
||||
ICE_GTP_NO_PAY,
|
||||
ICE_PFCP,
|
||||
ICE_PPPOE,
|
||||
ICE_L2TPV3,
|
||||
ICE_VLAN_EX,
|
||||
@ -61,6 +62,7 @@ enum ice_sw_tunnel_type {
|
||||
ICE_SW_TUN_NVGRE,
|
||||
ICE_SW_TUN_GTPU,
|
||||
ICE_SW_TUN_GTPC,
|
||||
ICE_SW_TUN_PFCP,
|
||||
ICE_ALL_TUNNELS /* All tunnel types including NVGRE */
|
||||
};
|
||||
|
||||
@ -202,6 +204,15 @@ struct ice_udp_gtp_hdr {
|
||||
u8 rsvrd;
|
||||
};
|
||||
|
||||
struct ice_pfcp_hdr {
|
||||
u8 flags;
|
||||
u8 msg_type;
|
||||
__be16 length;
|
||||
__be64 seid;
|
||||
__be32 seq;
|
||||
u8 spare;
|
||||
} __packed __aligned(__alignof__(u16));
|
||||
|
||||
struct ice_pppoe_hdr {
|
||||
u8 rsrvd_ver_type;
|
||||
u8 rsrvd_code;
|
||||
@ -418,6 +429,7 @@ union ice_prot_hdr {
|
||||
struct ice_udp_tnl_hdr tnl_hdr;
|
||||
struct ice_nvgre_hdr nvgre_hdr;
|
||||
struct ice_udp_gtp_hdr gtp_hdr;
|
||||
struct ice_pfcp_hdr pfcp_hdr;
|
||||
struct ice_pppoe_hdr pppoe_hdr;
|
||||
struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr;
|
||||
struct ice_hw_metadata metadata;
|
||||
|
@ -42,6 +42,7 @@ enum {
|
||||
ICE_PKT_KMALLOC = BIT(9),
|
||||
ICE_PKT_PPPOE = BIT(10),
|
||||
ICE_PKT_L2TPV3 = BIT(11),
|
||||
ICE_PKT_PFCP = BIT(12),
|
||||
};
|
||||
|
||||
struct ice_dummy_pkt_offsets {
|
||||
@ -1110,6 +1111,77 @@ ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
|
||||
0x00, 0x00,
|
||||
};
|
||||
|
||||
ICE_DECLARE_PKT_OFFSETS(pfcp_session_ipv4) = {
|
||||
{ ICE_MAC_OFOS, 0 },
|
||||
{ ICE_ETYPE_OL, 12 },
|
||||
{ ICE_IPV4_OFOS, 14 },
|
||||
{ ICE_UDP_ILOS, 34 },
|
||||
{ ICE_PFCP, 42 },
|
||||
{ ICE_PROTOCOL_LAST, 0 },
|
||||
};
|
||||
|
||||
ICE_DECLARE_PKT_TEMPLATE(pfcp_session_ipv4) = {
|
||||
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x08, 0x00, /* ICE_ETYPE_OL 12 */
|
||||
|
||||
0x45, 0x00, 0x00, 0x2c, /* ICE_IPV4_OFOS 14 */
|
||||
0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x11, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x22, 0x65, /* ICE_UDP_ILOS 34 */
|
||||
0x00, 0x18, 0x00, 0x00,
|
||||
|
||||
0x21, 0x01, 0x00, 0x0c, /* ICE_PFCP 42 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, /* 2 bytes for 4 byte alignment */
|
||||
};
|
||||
|
||||
ICE_DECLARE_PKT_OFFSETS(pfcp_session_ipv6) = {
|
||||
{ ICE_MAC_OFOS, 0 },
|
||||
{ ICE_ETYPE_OL, 12 },
|
||||
{ ICE_IPV6_OFOS, 14 },
|
||||
{ ICE_UDP_ILOS, 54 },
|
||||
{ ICE_PFCP, 62 },
|
||||
{ ICE_PROTOCOL_LAST, 0 },
|
||||
};
|
||||
|
||||
ICE_DECLARE_PKT_TEMPLATE(pfcp_session_ipv6) = {
|
||||
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x86, 0xdd, /* ICE_ETYPE_OL 12 */
|
||||
|
||||
0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
|
||||
0x00, 0x10, 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,
|
||||
|
||||
0x00, 0x00, 0x22, 0x65, /* ICE_UDP_ILOS 54 */
|
||||
0x00, 0x18, 0x00, 0x00,
|
||||
|
||||
0x21, 0x01, 0x00, 0x0c, /* ICE_PFCP 62 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, /* 2 bytes for 4 byte alignment */
|
||||
};
|
||||
|
||||
ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_tcp) = {
|
||||
{ ICE_MAC_OFOS, 0 },
|
||||
{ ICE_ETYPE_OL, 12 },
|
||||
@ -1343,6 +1415,8 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
|
||||
ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
|
||||
ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
|
||||
ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
|
||||
ICE_PKT_PROFILE(pfcp_session_ipv6, ICE_PKT_PFCP | ICE_PKT_OUTER_IPV6),
|
||||
ICE_PKT_PROFILE(pfcp_session_ipv4, ICE_PKT_PFCP),
|
||||
ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 |
|
||||
ICE_PKT_INNER_UDP),
|
||||
ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6),
|
||||
@ -4532,6 +4606,7 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
|
||||
ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
|
||||
ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
|
||||
ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
|
||||
ICE_PROTOCOL_ENTRY(ICE_PFCP, 8, 10, 12, 14, 16, 18, 20, 22),
|
||||
ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
|
||||
ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
|
||||
ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
|
||||
@ -4565,6 +4640,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
|
||||
{ ICE_NVGRE, ICE_GRE_OF_HW },
|
||||
{ ICE_GTP, ICE_UDP_OF_HW },
|
||||
{ ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW },
|
||||
{ ICE_PFCP, ICE_UDP_ILOS_HW },
|
||||
{ ICE_PPPOE, ICE_PPPOE_HW },
|
||||
{ ICE_L2TPV3, ICE_L2TPV3_HW },
|
||||
{ ICE_VLAN_EX, ICE_VLAN_OF_HW },
|
||||
@ -5272,6 +5348,9 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
|
||||
case ICE_SW_TUN_GTPC:
|
||||
prof_type = ICE_PROF_TUN_GTPC;
|
||||
break;
|
||||
case ICE_SW_TUN_PFCP:
|
||||
prof_type = ICE_PROF_TUN_PFCP;
|
||||
break;
|
||||
case ICE_SW_TUN_AND_NON_TUN:
|
||||
default:
|
||||
prof_type = ICE_PROF_ALL;
|
||||
@ -5556,6 +5635,9 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
|
||||
case ICE_SW_TUN_VXLAN:
|
||||
match |= ICE_PKT_TUN_UDP;
|
||||
break;
|
||||
case ICE_SW_TUN_PFCP:
|
||||
match |= ICE_PKT_PFCP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -5696,6 +5778,9 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
|
||||
case ICE_GTP:
|
||||
len = sizeof(struct ice_udp_gtp_hdr);
|
||||
break;
|
||||
case ICE_PFCP:
|
||||
len = sizeof(struct ice_pfcp_hdr);
|
||||
break;
|
||||
case ICE_PPPOE:
|
||||
len = sizeof(struct ice_pppoe_hdr);
|
||||
break;
|
||||
|
@ -22,6 +22,8 @@
|
||||
#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_PROFID_IPV4_PFCP_NODE 79
|
||||
#define ICE_PROFID_IPV6_PFCP_SESSION 82
|
||||
|
||||
#define ICE_SW_RULE_VSI_LIST_SIZE(s, n) struct_size((s), vsi, (n))
|
||||
#define ICE_SW_RULE_RX_TX_HDR_SIZE(s, l) struct_size((s), hdr_data, (l))
|
||||
|
@ -38,6 +38,9 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
|
||||
if (flags & ICE_TC_FLWR_FIELD_GTP_OPTS)
|
||||
lkups_cnt++;
|
||||
|
||||
if (flags & ICE_TC_FLWR_FIELD_PFCP_OPTS)
|
||||
lkups_cnt++;
|
||||
|
||||
if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 |
|
||||
ICE_TC_FLWR_FIELD_ENC_DEST_IPV4 |
|
||||
ICE_TC_FLWR_FIELD_ENC_SRC_IPV6 |
|
||||
@ -138,6 +141,8 @@ ice_proto_type_from_tunnel(enum ice_tunnel_type type)
|
||||
return ICE_GTP;
|
||||
case TNL_GTPC:
|
||||
return ICE_GTP_NO_PAY;
|
||||
case TNL_PFCP:
|
||||
return ICE_PFCP;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -157,6 +162,8 @@ ice_sw_type_from_tunnel(enum ice_tunnel_type type)
|
||||
return ICE_SW_TUN_GTPU;
|
||||
case TNL_GTPC:
|
||||
return ICE_SW_TUN_GTPC;
|
||||
case TNL_PFCP:
|
||||
return ICE_SW_TUN_PFCP;
|
||||
default:
|
||||
return ICE_NON_TUN;
|
||||
}
|
||||
@ -236,6 +243,22 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
|
||||
i++;
|
||||
}
|
||||
|
||||
if (flags & ICE_TC_FLWR_FIELD_PFCP_OPTS) {
|
||||
struct ice_pfcp_hdr *hdr_h, *hdr_m;
|
||||
|
||||
hdr_h = &list[i].h_u.pfcp_hdr;
|
||||
hdr_m = &list[i].m_u.pfcp_hdr;
|
||||
list[i].type = ICE_PFCP;
|
||||
|
||||
hdr_h->flags = fltr->pfcp_meta_keys.type;
|
||||
hdr_m->flags = fltr->pfcp_meta_masks.type & 0x01;
|
||||
|
||||
hdr_h->seid = fltr->pfcp_meta_keys.seid;
|
||||
hdr_m->seid = fltr->pfcp_meta_masks.seid;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (flags & (ICE_TC_FLWR_FIELD_ENC_SRC_IPV4 |
|
||||
ICE_TC_FLWR_FIELD_ENC_DEST_IPV4)) {
|
||||
list[i].type = ice_proto_type_from_ipv4(false);
|
||||
@ -366,8 +389,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
|
||||
if (tc_fltr->tunnel_type != TNL_LAST) {
|
||||
i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i);
|
||||
|
||||
headers = &tc_fltr->inner_headers;
|
||||
inner = true;
|
||||
/* PFCP is considered non-tunneled - don't swap headers. */
|
||||
if (tc_fltr->tunnel_type != TNL_PFCP) {
|
||||
headers = &tc_fltr->inner_headers;
|
||||
inner = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ICE_TC_FLWR_FIELD_ETH_TYPE_ID) {
|
||||
@ -621,6 +647,8 @@ static int ice_tc_tun_get_type(struct net_device *tunnel_dev)
|
||||
*/
|
||||
if (netif_is_gtp(tunnel_dev))
|
||||
return TNL_GTPU;
|
||||
if (netif_is_pfcp(tunnel_dev))
|
||||
return TNL_PFCP;
|
||||
return TNL_LAST;
|
||||
}
|
||||
|
||||
@ -1415,6 +1443,20 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule,
|
||||
fltr->flags |= ICE_TC_FLWR_FIELD_GTP_OPTS;
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS) &&
|
||||
fltr->tunnel_type == TNL_PFCP) {
|
||||
struct flow_match_enc_opts match;
|
||||
|
||||
flow_rule_match_enc_opts(rule, &match);
|
||||
|
||||
memcpy(&fltr->pfcp_meta_keys, match.key->data,
|
||||
sizeof(struct pfcp_metadata));
|
||||
memcpy(&fltr->pfcp_meta_masks, match.mask->data,
|
||||
sizeof(struct pfcp_metadata));
|
||||
|
||||
fltr->flags |= ICE_TC_FLWR_FIELD_PFCP_OPTS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1473,10 +1515,14 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* header pointers should point to the inner headers, outer
|
||||
* header were already set by ice_parse_tunnel_attr
|
||||
*/
|
||||
headers = &fltr->inner_headers;
|
||||
/* PFCP is considered non-tunneled - don't swap headers. */
|
||||
if (fltr->tunnel_type != TNL_PFCP) {
|
||||
/* Header pointers should point to the inner headers,
|
||||
* outer header were already set by
|
||||
* ice_parse_tunnel_attr().
|
||||
*/
|
||||
headers = &fltr->inner_headers;
|
||||
}
|
||||
} else if (dissector->used_keys &
|
||||
(BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
|
||||
BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
|
||||
|
@ -4,6 +4,9 @@
|
||||
#ifndef _ICE_TC_LIB_H_
|
||||
#define _ICE_TC_LIB_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <net/pfcp.h>
|
||||
|
||||
#define ICE_TC_FLWR_FIELD_DST_MAC BIT(0)
|
||||
#define ICE_TC_FLWR_FIELD_SRC_MAC BIT(1)
|
||||
#define ICE_TC_FLWR_FIELD_VLAN BIT(2)
|
||||
@ -34,6 +37,7 @@
|
||||
#define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27)
|
||||
#define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28)
|
||||
#define ICE_TC_FLWR_FIELD_VLAN_TPID BIT(29)
|
||||
#define ICE_TC_FLWR_FIELD_PFCP_OPTS BIT(30)
|
||||
|
||||
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
|
||||
|
||||
@ -161,6 +165,8 @@ struct ice_tc_flower_fltr {
|
||||
__be32 tenant_id;
|
||||
struct gtp_pdu_session_info gtp_pdu_info_keys;
|
||||
struct gtp_pdu_session_info gtp_pdu_info_masks;
|
||||
struct pfcp_metadata pfcp_meta_keys;
|
||||
struct pfcp_metadata pfcp_meta_masks;
|
||||
u32 flags;
|
||||
u8 tunnel_type;
|
||||
struct ice_tc_flower_action action;
|
||||
|
Loading…
Reference in New Issue
Block a user