Commit e7afb958 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'flower-rework-tca_flower_key_enc_flags-usage'

Asbjørn Sloth Tønnesen says:

====================
flower: rework TCA_FLOWER_KEY_ENC_FLAGS usage

This series reworks the recently added TCA_FLOWER_KEY_ENC_FLAGS
attribute, to be more like TCA_FLOWER_KEY_FLAGS, and use the unused
u32 flags field in FLOW_DISSECTOR_KEY_ENC_CONTROL, instead of adding
a new flags field as FLOW_DISSECTOR_KEY_ENC_FLAGS.

I have defined the new FLOW_DIS_F_* and TCA_FLOWER_KEY_FLAGS_*
flags to co-exist with the existing flags, so the meaning
of the flags field in struct flow_dissector_key_control is not
depending on the context it is used in. If we run out of bits
then we can always split them up later, if we really want to.
Future flags might also be valid in both contexts.

iproute2 RFC v2 patch:
https://lore.kernel.org/560bcd549ca8ab24b1ad5abe352580a621f6d426.1720790774.git.dcaratti@redhat.com/

v3: https://lore.kernel.org/20240709163825.1210046-1-ast@fiberby.net/
v2: https://lore.kernel.org/20240705133348.728901-1-ast@fiberby.net/
v1: https://lore.kernel.org/20240703104600.455125-1-ast@fiberby.net/
RFC: https://lore.kernel.org/20240611235355.177667-1-ast@fiberby.net/
====================

Link: https://patch.msgid.link/20240713021911.1631517-1-ast@fiberby.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ba7a0f44 536b97ac
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -41,6 +41,16 @@ definitions:
      - in-hw
      - not-in-nw
      - verbose
  -
    name: tc-flower-key-ctrl-flags
    type: flags
    entries:
      - frag
      - firstfrag
      - tuncsum
      - tundf
      - tunoam
      - tuncrit
  -
    name: tc-stats
    type: struct
@@ -2536,10 +2546,14 @@ attribute-sets:
        name: key-flags
        type: u32
        byte-order: big-endian
        enum: tc-flower-key-ctrl-flags
        enum-as-flags: true
      -
        name: key-flags-mask
        type: u32
        byte-order: big-endian
        enum: tc-flower-key-ctrl-flags
        enum-as-flags: true
      -
        name: key-icmpv4-code
        type: u8
@@ -2749,6 +2763,18 @@ attribute-sets:
        name: key-spi-mask
        type: u32
        byte-order: big-endian
      -
        name: key-enc-flags
        type: u32
        byte-order: big-endian
        enum: tc-flower-key-ctrl-flags
        enum-as-flags: true
      -
        name: key-enc-flags-mask
        type: u32
        byte-order: big-endian
        enum: tc-flower-key-ctrl-flags
        enum-as-flags: true
  -
    name: tc-flower-key-enc-opts-attrs
    attributes:
+17 −13
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/siphash.h>
#include <linux/string.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/pkt_cls.h>

struct bpf_prog;
struct net;
@@ -16,7 +17,8 @@ struct sk_buff;
 * struct flow_dissector_key_control:
 * @thoff:     Transport header offset
 * @addr_type: Type of key. One of FLOW_DISSECTOR_KEY_*
 * @flags:     Key flags. Any of FLOW_DIS_(IS_FRAGMENT|FIRST_FRAGENCAPSULATION)
 * @flags:     Key flags.
 *             Any of FLOW_DIS_(IS_FRAGMENT|FIRST_FRAG|ENCAPSULATION|F_*)
 */
struct flow_dissector_key_control {
	u16	thoff;
@@ -24,9 +26,20 @@ struct flow_dissector_key_control {
	u32	flags;
};

#define FLOW_DIS_IS_FRAGMENT	BIT(0)
#define FLOW_DIS_FIRST_FRAG	BIT(1)
#define FLOW_DIS_ENCAPSULATION	BIT(2)
/* The control flags are kept in sync with TCA_FLOWER_KEY_FLAGS_*, as those
 * flags are exposed to userspace in some error paths, ie. unsupported flags.
 */
enum flow_dissector_ctrl_flags {
	FLOW_DIS_IS_FRAGMENT		= TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT,
	FLOW_DIS_FIRST_FRAG		= TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST,
	FLOW_DIS_F_TUNNEL_CSUM		= TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM,
	FLOW_DIS_F_TUNNEL_DONT_FRAGMENT	= TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT,
	FLOW_DIS_F_TUNNEL_OAM		= TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM,
	FLOW_DIS_F_TUNNEL_CRIT_OPT	= TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT,

	/* These flags are internal to the kernel */
	FLOW_DIS_ENCAPSULATION		= (TCA_FLOWER_KEY_FLAGS_MAX << 1),
};

enum flow_dissect_ret {
	FLOW_DISSECT_RET_OUT_GOOD,
@@ -329,14 +342,6 @@ struct flow_dissector_key_cfm {
#define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)
#define FLOW_DIS_CFM_MDL_MAX 7

/**
 * struct flow_dissector_key_enc_flags: tunnel metadata control flags
 * @flags: tunnel control flags
 */
struct flow_dissector_key_enc_flags {
	u32 flags;
};

enum flow_dissector_key_id {
	FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
	FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
@@ -371,7 +376,6 @@ enum flow_dissector_key_id {
	FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
	FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */
	FLOW_DISSECTOR_KEY_IPSEC, /* struct flow_dissector_key_ipsec */
	FLOW_DISSECTOR_KEY_ENC_FLAGS, /* struct flow_dissector_key_enc_flags */

	FLOW_DISSECTOR_KEY_MAX,
};
+0 −12
Original line number Diff line number Diff line
@@ -247,18 +247,6 @@ static inline bool ip_tunnel_is_options_present(const unsigned long *flags)
	return ip_tunnel_flags_intersect(flags, present);
}

static inline void ip_tunnel_set_encflags_present(unsigned long *flags)
{
	IP_TUNNEL_DECLARE_FLAGS(present) = { };

	__set_bit(IP_TUNNEL_CSUM_BIT, present);
	__set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, present);
	__set_bit(IP_TUNNEL_OAM_BIT, present);
	__set_bit(IP_TUNNEL_CRIT_OPT_BIT, present);

	ip_tunnel_flags_or(flags, flags, present);
}

static inline bool ip_tunnel_flags_is_be16_compat(const unsigned long *flags)
{
	IP_TUNNEL_DECLARE_FLAGS(supp) = { };
+9 −2
Original line number Diff line number Diff line
@@ -554,8 +554,8 @@ enum {
	TCA_FLOWER_KEY_SPI,		/* be32 */
	TCA_FLOWER_KEY_SPI_MASK,	/* be32 */

	TCA_FLOWER_KEY_ENC_FLAGS,	/* u32 */
	TCA_FLOWER_KEY_ENC_FLAGS_MASK,	/* u32 */
	TCA_FLOWER_KEY_ENC_FLAGS,	/* be32 */
	TCA_FLOWER_KEY_ENC_FLAGS_MASK,	/* be32 */

	__TCA_FLOWER_MAX,
};
@@ -677,8 +677,15 @@ enum {
enum {
	TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
	TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
	TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM = (1 << 2),
	TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT = (1 << 3),
	TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM = (1 << 4),
	TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT = (1 << 5),
	__TCA_FLOWER_KEY_FLAGS_MAX,
};

#define TCA_FLOWER_KEY_FLAGS_MAX (__TCA_FLOWER_KEY_FLAGS_MAX - 1)

enum {
	TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
	TCA_FLOWER_KEY_CFM_MD_LEVEL,
+26 −24
Original line number Diff line number Diff line
@@ -299,7 +299,8 @@ void skb_flow_dissect_meta(const struct sk_buff *skb,
EXPORT_SYMBOL(skb_flow_dissect_meta);

static void
skb_flow_dissect_set_enc_addr_type(enum flow_dissector_key_id type,
skb_flow_dissect_set_enc_control(enum flow_dissector_key_id type,
				 u32 ctrl_flags,
				 struct flow_dissector *flow_dissector,
				 void *target_container)
{
@@ -312,6 +313,7 @@ skb_flow_dissect_set_enc_addr_type(enum flow_dissector_key_id type,
					 FLOW_DISSECTOR_KEY_ENC_CONTROL,
					 target_container);
	ctrl->addr_type = type;
	ctrl->flags = ctrl_flags;
}

void
@@ -367,6 +369,7 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
{
	struct ip_tunnel_info *info;
	struct ip_tunnel_key *key;
	u32 ctrl_flags = 0;

	/* A quick check to see if there might be something to do. */
	if (!dissector_uses_key(flow_dissector,
@@ -382,9 +385,7 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
	    !dissector_uses_key(flow_dissector,
				FLOW_DISSECTOR_KEY_ENC_IP) &&
	    !dissector_uses_key(flow_dissector,
				FLOW_DISSECTOR_KEY_ENC_OPTS) &&
	    !dissector_uses_key(flow_dissector,
				FLOW_DISSECTOR_KEY_ENC_FLAGS))
				FLOW_DISSECTOR_KEY_ENC_OPTS))
		return;

	info = skb_tunnel_info(skb);
@@ -393,10 +394,19 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,

	key = &info->key;

	if (test_bit(IP_TUNNEL_CSUM_BIT, key->tun_flags))
		ctrl_flags |= FLOW_DIS_F_TUNNEL_CSUM;
	if (test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, key->tun_flags))
		ctrl_flags |= FLOW_DIS_F_TUNNEL_DONT_FRAGMENT;
	if (test_bit(IP_TUNNEL_OAM_BIT, key->tun_flags))
		ctrl_flags |= FLOW_DIS_F_TUNNEL_OAM;
	if (test_bit(IP_TUNNEL_CRIT_OPT_BIT, key->tun_flags))
		ctrl_flags |= FLOW_DIS_F_TUNNEL_CRIT_OPT;

	switch (ip_tunnel_info_af(info)) {
	case AF_INET:
		skb_flow_dissect_set_enc_addr_type(FLOW_DISSECTOR_KEY_IPV4_ADDRS,
						   flow_dissector,
		skb_flow_dissect_set_enc_control(FLOW_DISSECTOR_KEY_IPV4_ADDRS,
						 ctrl_flags, flow_dissector,
						 target_container);
		if (dissector_uses_key(flow_dissector,
				       FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
@@ -410,8 +420,8 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
		}
		break;
	case AF_INET6:
		skb_flow_dissect_set_enc_addr_type(FLOW_DISSECTOR_KEY_IPV6_ADDRS,
						   flow_dissector,
		skb_flow_dissect_set_enc_control(FLOW_DISSECTOR_KEY_IPV6_ADDRS,
						 ctrl_flags, flow_dissector,
						 target_container);
		if (dissector_uses_key(flow_dissector,
				       FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
@@ -424,6 +434,10 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
			ipv6->dst = key->u.ipv6.dst;
		}
		break;
	default:
		skb_flow_dissect_set_enc_control(0, ctrl_flags, flow_dissector,
						 target_container);
		break;
	}

	if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
@@ -477,18 +491,6 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
				    IP_TUNNEL_GENEVE_OPT_BIT);
		enc_opt->dst_opt_type = val < __IP_TUNNEL_FLAG_NUM ? val : 0;
	}

	if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_FLAGS)) {
		struct flow_dissector_key_enc_flags *enc_flags;
		IP_TUNNEL_DECLARE_FLAGS(flags) = {};

		enc_flags = skb_flow_dissector_target(flow_dissector,
						      FLOW_DISSECTOR_KEY_ENC_FLAGS,
						      target_container);
		ip_tunnel_set_encflags_present(flags);
		ip_tunnel_flags_and(flags, flags, info->key.tun_flags);
		enc_flags->flags = bitmap_read(flags, IP_TUNNEL_CSUM_BIT, 32);
	}
}
EXPORT_SYMBOL(skb_flow_dissect_tunnel_info);

Loading