Commit 2589d668 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'net-allow-dissecting-matching-tunnel-control-flags'

Davide Caratti says:

====================
net: allow dissecting/matching tunnel control flags

Ilya says: "for correct matching on decapsulated packets, we should match
on not only tunnel id and headers, but also on tunnel configuration flags
like TUNNEL_NO_CSUM and TUNNEL_DONT_FRAGMENT. This is done to distinguish
similar tunnels with slightly different configs. And it is important since
tunnel configuration is flow based, i.e. can be different for every packet,
even though the main tunnel port is the same."

 - patch 1 extends the kernel's flow dissector to extract these flags
   from the packet's tunnel metadata.
 - patch 2 extends TC flower to match on any combination of TUNNEL_NO_CSUM,
   TUNNEL_DONT_FRAGMENT, TUNNEL_OAM, TUNNEL_CRIT_OPT

v4:
 - fix kernel-doc warning in flow_dissector.h (thanks Jakub)

v3:
 - rebase on top of new uAPI bits and internals after commit 5832c4a7
   ("ip_tunnel: convert __be16 tunnel flags to bitmaps"). Use of network
   byte order is no more needed, since these bits match on metadata: convert
   netlink attributes to be u32.
 - also include TUNNEL_CRIT_OPT

v2:
 - use NL_REQ_ATTR_CHECK() where possible (thanks Jamal)
 - don't overwrite 'ret' in the error path of fl_set_key_flags()
====================

Link: https://lore.kernel.org/r/cover.1717088241.git.dcaratti@redhat.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 4fdb6b60 1d17568e
...@@ -329,6 +329,14 @@ struct flow_dissector_key_cfm { ...@@ -329,6 +329,14 @@ struct flow_dissector_key_cfm {
#define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5) #define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)
#define FLOW_DIS_CFM_MDL_MAX 7 #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 { enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */ FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */ FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
...@@ -363,6 +371,7 @@ enum flow_dissector_key_id { ...@@ -363,6 +371,7 @@ enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */ FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */ FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */
FLOW_DISSECTOR_KEY_IPSEC, /* struct flow_dissector_key_ipsec */ FLOW_DISSECTOR_KEY_IPSEC, /* struct flow_dissector_key_ipsec */
FLOW_DISSECTOR_KEY_ENC_FLAGS, /* struct flow_dissector_key_enc_flags */
FLOW_DISSECTOR_KEY_MAX, FLOW_DISSECTOR_KEY_MAX,
}; };
......
...@@ -247,6 +247,18 @@ static inline bool ip_tunnel_is_options_present(const unsigned long *flags) ...@@ -247,6 +247,18 @@ static inline bool ip_tunnel_is_options_present(const unsigned long *flags)
return ip_tunnel_flags_intersect(flags, present); 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) static inline bool ip_tunnel_flags_is_be16_compat(const unsigned long *flags)
{ {
IP_TUNNEL_DECLARE_FLAGS(supp) = { }; IP_TUNNEL_DECLARE_FLAGS(supp) = { };
......
...@@ -554,6 +554,9 @@ enum { ...@@ -554,6 +554,9 @@ enum {
TCA_FLOWER_KEY_SPI, /* be32 */ TCA_FLOWER_KEY_SPI, /* be32 */
TCA_FLOWER_KEY_SPI_MASK, /* be32 */ TCA_FLOWER_KEY_SPI_MASK, /* be32 */
TCA_FLOWER_KEY_ENC_FLAGS, /* u32 */
TCA_FLOWER_KEY_ENC_FLAGS_MASK, /* u32 */
__TCA_FLOWER_MAX, __TCA_FLOWER_MAX,
}; };
......
...@@ -382,7 +382,9 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb, ...@@ -382,7 +382,9 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
!dissector_uses_key(flow_dissector, !dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_ENC_IP) && FLOW_DISSECTOR_KEY_ENC_IP) &&
!dissector_uses_key(flow_dissector, !dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_ENC_OPTS)) FLOW_DISSECTOR_KEY_ENC_OPTS) &&
!dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_ENC_FLAGS))
return; return;
info = skb_tunnel_info(skb); info = skb_tunnel_info(skb);
...@@ -475,6 +477,18 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb, ...@@ -475,6 +477,18 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
IP_TUNNEL_GENEVE_OPT_BIT); IP_TUNNEL_GENEVE_OPT_BIT);
enc_opt->dst_opt_type = val < __IP_TUNNEL_FLAG_NUM ? val : 0; 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); EXPORT_SYMBOL(skb_flow_dissect_tunnel_info);
......
...@@ -41,6 +41,12 @@ ...@@ -41,6 +41,12 @@
#define TCA_FLOWER_KEY_CT_FLAGS_MASK \ #define TCA_FLOWER_KEY_CT_FLAGS_MASK \
(TCA_FLOWER_KEY_CT_FLAGS_MAX - 1) (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 fl_flow_key {
struct flow_dissector_key_meta meta; struct flow_dissector_key_meta meta;
struct flow_dissector_key_control control; struct flow_dissector_key_control control;
...@@ -75,6 +81,7 @@ struct fl_flow_key { ...@@ -75,6 +81,7 @@ struct fl_flow_key {
struct flow_dissector_key_l2tpv3 l2tpv3; struct flow_dissector_key_l2tpv3 l2tpv3;
struct flow_dissector_key_ipsec ipsec; struct flow_dissector_key_ipsec ipsec;
struct flow_dissector_key_cfm cfm; 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. */ } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
struct fl_flow_mask_range { struct fl_flow_mask_range {
...@@ -732,6 +739,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { ...@@ -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_KEY_SPI_MASK] = { .type = NLA_U32 },
[TCA_FLOWER_L2_MISS] = NLA_POLICY_MAX(NLA_U8, 1), [TCA_FLOWER_L2_MISS] = NLA_POLICY_MAX(NLA_U8, 1),
[TCA_FLOWER_KEY_CFM] = { .type = NLA_NESTED }, [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 static const struct nla_policy
...@@ -1825,6 +1836,21 @@ static int fl_set_key_cfm(struct nlattr **tb, ...@@ -1825,6 +1836,21 @@ static int fl_set_key_cfm(struct nlattr **tb,
return 0; 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, static int fl_set_key(struct net *net, struct nlattr **tb,
struct fl_flow_key *key, struct fl_flow_key *mask, struct fl_flow_key *key, struct fl_flow_key *mask,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -2059,9 +2085,16 @@ static int fl_set_key(struct net *net, struct nlattr **tb, ...@@ -2059,9 +2085,16 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
if (ret) if (ret)
return ret; return ret;
if (tb[TCA_FLOWER_KEY_FLAGS]) if (tb[TCA_FLOWER_KEY_FLAGS]) {
ret = fl_set_key_flags(tb, &key->control.flags, ret = fl_set_key_flags(tb, &key->control.flags,
&mask->control.flags, extack); &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; return ret;
} }
...@@ -2175,6 +2208,8 @@ static void fl_init_dissector(struct flow_dissector *dissector, ...@@ -2175,6 +2208,8 @@ static void fl_init_dissector(struct flow_dissector *dissector,
FLOW_DISSECTOR_KEY_IPSEC, ipsec); FLOW_DISSECTOR_KEY_IPSEC, ipsec);
FL_KEY_SET_IF_MASKED(mask, keys, cnt, FL_KEY_SET_IF_MASKED(mask, keys, cnt,
FLOW_DISSECTOR_KEY_CFM, cfm); 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); skb_flow_dissector_init(dissector, keys, cnt);
} }
...@@ -3291,6 +3326,22 @@ static int fl_dump_key_cfm(struct sk_buff *skb, ...@@ -3291,6 +3326,22 @@ static int fl_dump_key_cfm(struct sk_buff *skb,
return err; 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, static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
struct flow_dissector_key_enc_opts *enc_opts) struct flow_dissector_key_enc_opts *enc_opts)
{ {
...@@ -3592,6 +3643,9 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net, ...@@ -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)) if (fl_dump_key_cfm(skb, &key->cfm, &mask->cfm))
goto nla_put_failure; goto nla_put_failure;
if (fl_dump_key_enc_flags(skb, &key->enc_flags, &mask->enc_flags))
goto nla_put_failure;
return 0; return 0;
nla_put_failure: nla_put_failure:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment