Skip to content

Commit

Permalink
Merge branch 'ice-pfcp-filter'
Browse files Browse the repository at this point in the history
Alexander Lobakin says:

====================
ice: add PFCP filter support

Add support for creating PFCP filters in switchdev mode. Add pfcp module
that allows to create a PFCP-type netdev. The netdev then can be passed to
tc when creating a filter to indicate that PFCP filter should be created.

To add 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:12ab/ff:fffffffffffffff0 skip_hw action mirred egress redirect \
    dev pfcp0

Changes in iproute2 [1] are required to use pfcp_opts in tc.

ICE COMMS package is required as it contains PFCP profiles.

Part of this patchset modifies IP_TUNNEL_*_OPTs, which were previously
stored in a __be16. All possible values have already been used, making
it impossible to add new ones.

* 1-3: add new bitmap_{read,write}(), which is used later in the IP
       tunnel flags code (from Alexander's ARM64 MTE series[2]);
* 4-14: some bitmap code preparations also used later in IP tunnels;
* 15-17: convert IP tunnel flags from __be16 to a bitmap;
* 18-21: add PFCP module and support for it in ice.

[1] https://lore.kernel.org/netdev/20230614091758.11180-1-marcin.szycik@linux.intel.com
[2] https://lore.kernel.org/linux-kernel/20231218124033.551770-1-glider@google.com
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 1, 2024
2 parents d79b28f + 784feaa commit d823265
Show file tree
Hide file tree
Showing 78 changed files with 1,988 additions and 624 deletions.
5 changes: 0 additions & 5 deletions drivers/md/dm-clone-metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,11 +465,6 @@ static void __destroy_persistent_data_structures(struct dm_clone_metadata *cmd)

/*---------------------------------------------------------------------------*/

static size_t bitmap_size(unsigned long nr_bits)
{
return BITS_TO_LONGS(nr_bits) * sizeof(long);
}

static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
unsigned long nr_regions)
{
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,19 @@ config GTP
To compile this drivers as a module, choose M here: the module
will be called gtp.

config PFCP
tristate "Packet Forwarding Control Protocol (PFCP)"
depends on INET
select NET_UDP_TUNNEL
help
This allows one to create PFCP virtual interfaces that allows to
set up software and hardware offload of PFCP packets.
Note that this module does not support PFCP protocol in the kernel space.
There is no support for parsing any PFCP messages.

To compile this drivers as a module, choose M here: the module
will be called pfcp.

config AMT
tristate "Automatic Multicast Tunneling (AMT)"
depends on INET && IP_MULTICAST
Expand Down
1 change: 1 addition & 0 deletions drivers/net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ obj-$(CONFIG_GENEVE) += geneve.o
obj-$(CONFIG_BAREUDP) += bareudp.o
obj-$(CONFIG_GTP) += gtp.o
obj-$(CONFIG_NLMON) += nlmon.o
obj-$(CONFIG_PFCP) += pfcp.o
obj-$(CONFIG_NET_VRF) += vrf.o
obj-$(CONFIG_VSOCKMON) += vsockmon.o
obj-$(CONFIG_MHI_NET) += mhi_net.o
Expand Down
19 changes: 13 additions & 6 deletions drivers/net/bareudp.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct bareudp_dev {
static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
struct metadata_dst *tun_dst = NULL;
IP_TUNNEL_DECLARE_FLAGS(key) = { };
struct bareudp_dev *bareudp;
unsigned short family;
unsigned int len;
Expand Down Expand Up @@ -137,7 +138,10 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
bareudp->dev->stats.rx_dropped++;
goto drop;
}
tun_dst = udp_tun_rx_dst(skb, family, TUNNEL_KEY, 0, 0);

__set_bit(IP_TUNNEL_KEY_BIT, key);

tun_dst = udp_tun_rx_dst(skb, family, key, 0, 0);
if (!tun_dst) {
bareudp->dev->stats.rx_dropped++;
goto drop;
Expand Down Expand Up @@ -285,10 +289,10 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct bareudp_dev *bareudp,
const struct ip_tunnel_info *info)
{
bool udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags);
bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev));
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct socket *sock = rcu_dereference(bareudp->sock);
bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
const struct ip_tunnel_key *key = &info->key;
struct rtable *rt;
__be16 sport, df;
Expand Down Expand Up @@ -316,7 +320,8 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,

tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
ttl = key->ttl;
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
df = test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, key->tun_flags) ?
htons(IP_DF) : 0;
skb_scrub_packet(skb, xnet);

err = -ENOSPC;
Expand All @@ -338,7 +343,8 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
udp_tunnel_xmit_skb(rt, sock->sk, skb, saddr, info->key.u.ipv4.dst,
tos, ttl, df, sport, bareudp->port,
!net_eq(bareudp->net, dev_net(bareudp->dev)),
!(info->key.tun_flags & TUNNEL_CSUM));
!test_bit(IP_TUNNEL_CSUM_BIT,
info->key.tun_flags));
return 0;

free_dst:
Expand All @@ -350,10 +356,10 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct bareudp_dev *bareudp,
const struct ip_tunnel_info *info)
{
bool udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags);
bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev));
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct socket *sock = rcu_dereference(bareudp->sock);
bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
const struct ip_tunnel_key *key = &info->key;
struct dst_entry *dst = NULL;
struct in6_addr saddr, daddr;
Expand Down Expand Up @@ -402,7 +408,8 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
udp_tunnel6_xmit_skb(dst, sock->sk, skb, dev,
&saddr, &daddr, prio, ttl,
info->key.label, sport, bareudp->port,
!(info->key.tun_flags & TUNNEL_CSUM));
!test_bit(IP_TUNNEL_CSUM_BIT,
info->key.tun_flags));
return 0;

free_dst:
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_ddp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 &&
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_flex_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};

Expand Down
12 changes: 12 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_protocol_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 */
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
85 changes: 85 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Loading

0 comments on commit d823265

Please sign in to comment.