Commit d823265d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ice-pfcp-filter'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents d79b28fd 784feaa6
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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)
{
+13 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+13 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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:
@@ -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;
@@ -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:
+9 −0
Original line number Diff line number Diff line
@@ -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 &&
Loading