Commit e7afb958 authored by Jakub Kicinski's avatar Jakub Kicinski

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.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ba7a0f44 536b97ac
......@@ -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:
......
......@@ -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,
};
......
......@@ -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) = { };
......
......@@ -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,
......
......@@ -299,9 +299,10 @@ 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,
struct flow_dissector *flow_dissector,
void *target_container)
skb_flow_dissect_set_enc_control(enum flow_dissector_key_id type,
u32 ctrl_flags,
struct flow_dissector *flow_dissector,
void *target_container)
{
struct flow_dissector_key_control *ctrl;
......@@ -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,11 +394,20 @@ 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,
target_container);
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)) {
struct flow_dissector_key_ipv4_addrs *ipv4;
......@@ -410,9 +420,9 @@ 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,
target_container);
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)) {
struct flow_dissector_key_ipv6_addrs *ipv6;
......@@ -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);
......
......@@ -41,11 +41,15 @@
#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))
#define TCA_FLOWER_KEY_FLAGS_POLICY_MASK \
(TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT | \
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST)
#define TCA_FLOWER_KEY_ENC_FLAGS_POLICY_MASK \
(TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM | \
TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT | \
TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM | \
TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT)
struct fl_flow_key {
struct flow_dissector_key_meta meta;
......@@ -81,7 +85,6 @@ 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 {
......@@ -676,8 +679,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
[TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_ENC_UDP_DST_PORT] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_FLAGS] = { .type = NLA_U32 },
[TCA_FLOWER_KEY_FLAGS_MASK] = { .type = NLA_U32 },
[TCA_FLOWER_KEY_FLAGS] = NLA_POLICY_MASK(NLA_BE32,
TCA_FLOWER_KEY_FLAGS_POLICY_MASK),
[TCA_FLOWER_KEY_FLAGS_MASK] = NLA_POLICY_MASK(NLA_BE32,
TCA_FLOWER_KEY_FLAGS_POLICY_MASK),
[TCA_FLOWER_KEY_ICMPV4_TYPE] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_ICMPV4_CODE] = { .type = NLA_U8 },
......@@ -739,10 +744,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),
[TCA_FLOWER_KEY_ENC_FLAGS] = NLA_POLICY_MASK(NLA_BE32,
TCA_FLOWER_KEY_ENC_FLAGS_POLICY_MASK),
[TCA_FLOWER_KEY_ENC_FLAGS_MASK] = NLA_POLICY_MASK(NLA_BE32,
TCA_FLOWER_KEY_ENC_FLAGS_POLICY_MASK),
};
static const struct nla_policy
......@@ -1166,19 +1171,29 @@ static void fl_set_key_flag(u32 flower_key, u32 flower_mask,
}
}
static int fl_set_key_flags(struct nlattr **tb, u32 *flags_key,
u32 *flags_mask, struct netlink_ext_ack *extack)
static int fl_set_key_flags(struct nlattr *tca_opts, struct nlattr **tb,
bool encap, u32 *flags_key, u32 *flags_mask,
struct netlink_ext_ack *extack)
{
int fl_key, fl_mask;
u32 key, mask;
if (encap) {
fl_key = TCA_FLOWER_KEY_ENC_FLAGS;
fl_mask = TCA_FLOWER_KEY_ENC_FLAGS_MASK;
} else {
fl_key = TCA_FLOWER_KEY_FLAGS;
fl_mask = TCA_FLOWER_KEY_FLAGS_MASK;
}
/* mask is mandatory for flags */
if (!tb[TCA_FLOWER_KEY_FLAGS_MASK]) {
if (NL_REQ_ATTR_CHECK(extack, tca_opts, tb, fl_mask)) {
NL_SET_ERR_MSG(extack, "Missing flags mask");
return -EINVAL;
}
key = be32_to_cpu(nla_get_be32(tb[TCA_FLOWER_KEY_FLAGS]));
mask = be32_to_cpu(nla_get_be32(tb[TCA_FLOWER_KEY_FLAGS_MASK]));
key = be32_to_cpu(nla_get_be32(tb[fl_key]));
mask = be32_to_cpu(nla_get_be32(tb[fl_mask]));
*flags_key = 0;
*flags_mask = 0;
......@@ -1189,6 +1204,21 @@ static int fl_set_key_flags(struct nlattr **tb, u32 *flags_key,
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST,
FLOW_DIS_FIRST_FRAG);
fl_set_key_flag(key, mask, flags_key, flags_mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM,
FLOW_DIS_F_TUNNEL_CSUM);
fl_set_key_flag(key, mask, flags_key, flags_mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT,
FLOW_DIS_F_TUNNEL_DONT_FRAGMENT);
fl_set_key_flag(key, mask, flags_key, flags_mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM, FLOW_DIS_F_TUNNEL_OAM);
fl_set_key_flag(key, mask, flags_key, flags_mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT,
FLOW_DIS_F_TUNNEL_CRIT_OPT);
return 0;
}
......@@ -1836,24 +1866,9 @@ 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)
static int fl_set_key(struct net *net, struct nlattr *tca_opts,
struct nlattr **tb, struct fl_flow_key *key,
struct fl_flow_key *mask, struct netlink_ext_ack *extack)
{
__be16 ethertype;
int ret = 0;
......@@ -2086,15 +2101,17 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
return ret;
if (tb[TCA_FLOWER_KEY_FLAGS]) {
ret = fl_set_key_flags(tb, &key->control.flags,
ret = fl_set_key_flags(tca_opts, tb, false,
&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);
ret = fl_set_key_flags(tca_opts, tb, true,
&key->enc_control.flags,
&mask->enc_control.flags, extack);
return ret;
}
......@@ -2185,7 +2202,8 @@ static void fl_init_dissector(struct flow_dissector *dissector,
FL_KEY_SET_IF_MASKED(mask, keys, cnt,
FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, enc_ipv6);
if (FL_KEY_IS_MASKED(mask, enc_ipv4) ||
FL_KEY_IS_MASKED(mask, enc_ipv6))
FL_KEY_IS_MASKED(mask, enc_ipv6) ||
FL_KEY_IS_MASKED(mask, enc_control))
FL_KEY_SET(keys, cnt, FLOW_DISSECTOR_KEY_ENC_CONTROL,
enc_control);
FL_KEY_SET_IF_MASKED(mask, keys, cnt,
......@@ -2208,8 +2226,6 @@ 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);
}
......@@ -2345,6 +2361,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
{
struct cls_fl_head *head = fl_head_dereference(tp);
bool rtnl_held = !(flags & TCA_ACT_FLAGS_NO_RTNL);
struct nlattr *tca_opts = tca[TCA_OPTIONS];
struct cls_fl_filter *fold = *arg;
bool bound_to_filter = false;
struct cls_fl_filter *fnew;
......@@ -2353,7 +2370,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
bool in_ht;
int err;
if (!tca[TCA_OPTIONS]) {
if (!tca_opts) {
err = -EINVAL;
goto errout_fold;
}
......@@ -2371,7 +2388,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
}
err = nla_parse_nested_deprecated(tb, TCA_FLOWER_MAX,
tca[TCA_OPTIONS], fl_policy, NULL);
tca_opts, fl_policy, NULL);
if (err < 0)
goto errout_tb;
......@@ -2447,7 +2464,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
bound_to_filter = true;
}
err = fl_set_key(net, tb, &fnew->key, &mask->key, extack);
err = fl_set_key(net, tca_opts, tb, &fnew->key, &mask->key, extack);
if (err)
goto unbind_filter;
......@@ -2787,18 +2804,19 @@ static void *fl_tmplt_create(struct net *net, struct tcf_chain *chain,
struct nlattr **tca,
struct netlink_ext_ack *extack)
{
struct nlattr *tca_opts = tca[TCA_OPTIONS];
struct fl_flow_tmplt *tmplt;
struct nlattr **tb;
int err;
if (!tca[TCA_OPTIONS])
if (!tca_opts)
return ERR_PTR(-EINVAL);
tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
if (!tb)
return ERR_PTR(-ENOBUFS);
err = nla_parse_nested_deprecated(tb, TCA_FLOWER_MAX,
tca[TCA_OPTIONS], fl_policy, NULL);
tca_opts, fl_policy, NULL);
if (err)
goto errout_tb;
......@@ -2808,7 +2826,8 @@ static void *fl_tmplt_create(struct net *net, struct tcf_chain *chain,
goto errout_tb;
}
tmplt->chain = chain;
err = fl_set_key(net, tb, &tmplt->dummy_key, &tmplt->mask, extack);
err = fl_set_key(net, tca_opts, tb, &tmplt->dummy_key,
&tmplt->mask, extack);
if (err)
goto errout_tmplt;
......@@ -3084,12 +3103,22 @@ static void fl_get_key_flag(u32 dissector_key, u32 dissector_mask,
}
}
static int fl_dump_key_flags(struct sk_buff *skb, u32 flags_key, u32 flags_mask)
static int fl_dump_key_flags(struct sk_buff *skb, bool encap,
u32 flags_key, u32 flags_mask)
{
u32 key, mask;
int fl_key, fl_mask;
__be32 _key, _mask;
u32 key, mask;
int err;
if (encap) {
fl_key = TCA_FLOWER_KEY_ENC_FLAGS;
fl_mask = TCA_FLOWER_KEY_ENC_FLAGS_MASK;
} else {
fl_key = TCA_FLOWER_KEY_FLAGS;
fl_mask = TCA_FLOWER_KEY_FLAGS_MASK;
}
if (!memchr_inv(&flags_mask, 0, sizeof(flags_mask)))
return 0;
......@@ -3102,14 +3131,29 @@ static int fl_dump_key_flags(struct sk_buff *skb, u32 flags_key, u32 flags_mask)
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST,
FLOW_DIS_FIRST_FRAG);
fl_get_key_flag(flags_key, flags_mask, &key, &mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM,
FLOW_DIS_F_TUNNEL_CSUM);
fl_get_key_flag(flags_key, flags_mask, &key, &mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT,
FLOW_DIS_F_TUNNEL_DONT_FRAGMENT);
fl_get_key_flag(flags_key, flags_mask, &key, &mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM, FLOW_DIS_F_TUNNEL_OAM);
fl_get_key_flag(flags_key, flags_mask, &key, &mask,
TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT,
FLOW_DIS_F_TUNNEL_CRIT_OPT);
_key = cpu_to_be32(key);
_mask = cpu_to_be32(mask);
err = nla_put(skb, TCA_FLOWER_KEY_FLAGS, 4, &_key);
err = nla_put(skb, fl_key, 4, &_key);
if (err)
return err;
return nla_put(skb, TCA_FLOWER_KEY_FLAGS_MASK, 4, &_mask);
return nla_put(skb, fl_mask, 4, &_mask);
}
static int fl_dump_key_geneve_opt(struct sk_buff *skb,
......@@ -3326,22 +3370,6 @@ static int fl_dump_key_cfm(struct sk_buff *skb,
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)
{
......@@ -3632,7 +3660,8 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
if (fl_dump_key_ct(skb, &key->ct, &mask->ct))
goto nla_put_failure;
if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags))
if (fl_dump_key_flags(skb, false, key->control.flags,
mask->control.flags))
goto nla_put_failure;
if (fl_dump_key_val(skb, &key->hash.hash, TCA_FLOWER_KEY_HASH,
......@@ -3643,7 +3672,8 @@ 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))
if (fl_dump_key_flags(skb, true, key->enc_control.flags,
mask->enc_control.flags))
goto nla_put_failure;
return 0;
......
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