]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/sched: cls_flower: add support for matching tunnel control flags
authorDavide Caratti <dcaratti@redhat.com>
Thu, 30 May 2024 17:08:35 +0000 (19:08 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 4 Jun 2024 09:16:38 +0000 (11:16 +0200)
extend cls_flower to match TUNNEL_FLAGS_PRESENT bits in tunnel metadata.

Suggested-by: Ilya Maximets <i.maximets@ovn.org>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
include/uapi/linux/pkt_cls.h
net/sched/cls_flower.c

index 229fc925ec3a299ece747c77076feb9afe193c90..b6d38f5fd7c05aaed160c93081d9d630f4056f1d 100644 (file)
@@ -554,6 +554,9 @@ 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_MAX,
 };
 
index fd9a6f20b60b463286dec0ff171d3519617d4a7c..eef570c577ac7e35505492383e49554caf728f7b 100644 (file)
 #define TCA_FLOWER_KEY_CT_FLAGS_MASK \
                (TCA_FLOWER_KEY_CT_FLAGS_MAX - 1)
 
+#define TUNNEL_FLAGS_PRESENT (\
+       _BITUL(IP_TUNNEL_CSUM_BIT) |            \
+       _BITUL(IP_TUNNEL_DONT_FRAGMENT_BIT) |   \
+       _BITUL(IP_TUNNEL_OAM_BIT) |             \
+       _BITUL(IP_TUNNEL_CRIT_OPT_BIT))
+
 struct fl_flow_key {
        struct flow_dissector_key_meta meta;
        struct flow_dissector_key_control control;
@@ -75,6 +81,7 @@ struct fl_flow_key {
        struct flow_dissector_key_l2tpv3 l2tpv3;
        struct flow_dissector_key_ipsec ipsec;
        struct flow_dissector_key_cfm cfm;
+       struct flow_dissector_key_enc_flags enc_flags;
 } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
 
 struct fl_flow_mask_range {
@@ -732,6 +739,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
        [TCA_FLOWER_KEY_SPI_MASK]       = { .type = NLA_U32 },
        [TCA_FLOWER_L2_MISS]            = NLA_POLICY_MAX(NLA_U8, 1),
        [TCA_FLOWER_KEY_CFM]            = { .type = NLA_NESTED },
+       [TCA_FLOWER_KEY_ENC_FLAGS]      = NLA_POLICY_MASK(NLA_U32,
+                                                         TUNNEL_FLAGS_PRESENT),
+       [TCA_FLOWER_KEY_ENC_FLAGS_MASK] = NLA_POLICY_MASK(NLA_U32,
+                                                         TUNNEL_FLAGS_PRESENT),
 };
 
 static const struct nla_policy
@@ -1825,6 +1836,21 @@ static int fl_set_key_cfm(struct nlattr **tb,
        return 0;
 }
 
+static int fl_set_key_enc_flags(struct nlattr **tb, u32 *flags_key,
+                               u32 *flags_mask, struct netlink_ext_ack *extack)
+{
+       /* mask is mandatory for flags */
+       if (NL_REQ_ATTR_CHECK(extack, NULL, tb, TCA_FLOWER_KEY_ENC_FLAGS_MASK)) {
+               NL_SET_ERR_MSG(extack, "missing enc_flags mask");
+               return -EINVAL;
+       }
+
+       *flags_key = nla_get_u32(tb[TCA_FLOWER_KEY_ENC_FLAGS]);
+       *flags_mask = nla_get_u32(tb[TCA_FLOWER_KEY_ENC_FLAGS_MASK]);
+
+       return 0;
+}
+
 static int fl_set_key(struct net *net, struct nlattr **tb,
                      struct fl_flow_key *key, struct fl_flow_key *mask,
                      struct netlink_ext_ack *extack)
@@ -2059,9 +2085,16 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
        if (ret)
                return ret;
 
-       if (tb[TCA_FLOWER_KEY_FLAGS])
+       if (tb[TCA_FLOWER_KEY_FLAGS]) {
                ret = fl_set_key_flags(tb, &key->control.flags,
                                       &mask->control.flags, extack);
+               if (ret)
+                       return ret;
+       }
+
+       if (tb[TCA_FLOWER_KEY_ENC_FLAGS])
+               ret = fl_set_key_enc_flags(tb, &key->enc_flags.flags,
+                                          &mask->enc_flags.flags, extack);
 
        return ret;
 }
@@ -2175,6 +2208,8 @@ static void fl_init_dissector(struct flow_dissector *dissector,
                             FLOW_DISSECTOR_KEY_IPSEC, ipsec);
        FL_KEY_SET_IF_MASKED(mask, keys, cnt,
                             FLOW_DISSECTOR_KEY_CFM, cfm);
+       FL_KEY_SET_IF_MASKED(mask, keys, cnt,
+                            FLOW_DISSECTOR_KEY_ENC_FLAGS, enc_flags);
 
        skb_flow_dissector_init(dissector, keys, cnt);
 }
@@ -3291,6 +3326,22 @@ err_cfm_opts:
        return err;
 }
 
+static int fl_dump_key_enc_flags(struct sk_buff *skb,
+                                struct flow_dissector_key_enc_flags *key,
+                                struct flow_dissector_key_enc_flags *mask)
+{
+       if (!memchr_inv(mask, 0, sizeof(*mask)))
+               return 0;
+
+       if (nla_put_u32(skb, TCA_FLOWER_KEY_ENC_FLAGS, key->flags))
+               return -EMSGSIZE;
+
+       if (nla_put_u32(skb, TCA_FLOWER_KEY_ENC_FLAGS_MASK, mask->flags))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
 static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
                               struct flow_dissector_key_enc_opts *enc_opts)
 {
@@ -3592,6 +3643,9 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
        if (fl_dump_key_cfm(skb, &key->cfm, &mask->cfm))
                goto nla_put_failure;
 
+       if (fl_dump_key_enc_flags(skb, &key->enc_flags, &mask->enc_flags))
+               goto nla_put_failure;
+
        return 0;
 
 nla_put_failure: