Message ID | 20230425211630.698373-3-zahari.doychev@linux.com (mailing list archive) |
---|---|
State | Deferred |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: flower: add cfm support | expand |
On Tue, Apr 25, 2023 at 11:16:29PM +0200, Zahari Doychev wrote: > diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c > index cc49256d5318..5d77da484a88 100644 > --- a/net/sched/cls_flower.c > +++ b/net/sched/cls_flower.c > @@ -11,6 +11,7 @@ > #include <linux/rhashtable.h> > #include <linux/workqueue.h> > #include <linux/refcount.h> > +#include <linux/bitfield.h> > > #include <linux/if_ether.h> > #include <linux/in6.h> > @@ -71,6 +72,7 @@ struct fl_flow_key { > struct flow_dissector_key_num_of_vlans num_of_vlans; > struct flow_dissector_key_pppoe pppoe; > struct flow_dissector_key_l2tpv3 l2tpv3; > + struct flow_dissector_key_cfm cfm; > } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ > > struct fl_flow_mask_range { > @@ -720,7 +722,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { > [TCA_FLOWER_KEY_PPPOE_SID] = { .type = NLA_U16 }, > [TCA_FLOWER_KEY_PPP_PROTO] = { .type = NLA_U16 }, > [TCA_FLOWER_KEY_L2TPV3_SID] = { .type = NLA_U32 }, > - > + [TCA_FLOWER_KEY_CFM] = { .type = NLA_NESTED }, "fl_policy" is used with nla_parse_nested_deprecated(). You can enable strict validation for new attributes using the following diff: diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index fc9037685458..6bccfc1722ad 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -615,7 +615,8 @@ static void *fl_get(struct tcf_proto *tp, u32 handle) } static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { - [TCA_FLOWER_UNSPEC] = { .type = NLA_UNSPEC }, + [TCA_FLOWER_UNSPEC] = { .strict_start_type = + TCA_FLOWER_KEY_CFM }, [TCA_FLOWER_CLASSID] = { .type = NLA_U32 }, [TCA_FLOWER_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ }, > }; > > static const struct nla_policy > @@ -769,6 +771,11 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { > [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL] = { .type = NLA_U32 }, > }; > > +static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { > + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), Instead of 7, can you use FIELD_MAX(FLOW_DIS_CFM_MDL_MASK) like you did in the previous version? > + [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, > +};
On Sun, Apr 30, 2023 at 05:49:57PM +0300, Ido Schimmel wrote: > On Tue, Apr 25, 2023 at 11:16:29PM +0200, Zahari Doychev wrote: > > diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c > > index cc49256d5318..5d77da484a88 100644 > > --- a/net/sched/cls_flower.c > > +++ b/net/sched/cls_flower.c > > @@ -11,6 +11,7 @@ > > #include <linux/rhashtable.h> > > #include <linux/workqueue.h> > > #include <linux/refcount.h> > > +#include <linux/bitfield.h> > > > > #include <linux/if_ether.h> > > #include <linux/in6.h> > > @@ -71,6 +72,7 @@ struct fl_flow_key { > > struct flow_dissector_key_num_of_vlans num_of_vlans; > > struct flow_dissector_key_pppoe pppoe; > > struct flow_dissector_key_l2tpv3 l2tpv3; > > + struct flow_dissector_key_cfm cfm; > > } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ > > > > struct fl_flow_mask_range { > > @@ -720,7 +722,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { > > [TCA_FLOWER_KEY_PPPOE_SID] = { .type = NLA_U16 }, > > [TCA_FLOWER_KEY_PPP_PROTO] = { .type = NLA_U16 }, > > [TCA_FLOWER_KEY_L2TPV3_SID] = { .type = NLA_U32 }, > > - > > + [TCA_FLOWER_KEY_CFM] = { .type = NLA_NESTED }, > > "fl_policy" is used with nla_parse_nested_deprecated(). You can enable > strict validation for new attributes using the following diff: > > diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c > index fc9037685458..6bccfc1722ad 100644 > --- a/net/sched/cls_flower.c > +++ b/net/sched/cls_flower.c > @@ -615,7 +615,8 @@ static void *fl_get(struct tcf_proto *tp, u32 handle) > } > > static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { > - [TCA_FLOWER_UNSPEC] = { .type = NLA_UNSPEC }, > + [TCA_FLOWER_UNSPEC] = { .strict_start_type = > + TCA_FLOWER_KEY_CFM }, > [TCA_FLOWER_CLASSID] = { .type = NLA_U32 }, > [TCA_FLOWER_INDEV] = { .type = NLA_STRING, > .len = IFNAMSIZ }, > > > }; thanks, noted. > > > > static const struct nla_policy > > @@ -769,6 +771,11 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { > > [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL] = { .type = NLA_U32 }, > > }; > > > > +static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { > > + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), > > Instead of 7, can you use FIELD_MAX(FLOW_DIS_CFM_MDL_MASK) like you did > in the previous version? > It seems that the macro can be use only inside functions. I wanted to use it but I was getting the following error: linux/include/linux/bitfield.h:86:9: error: braced-group within expression allowed only inside a function thanks Zahari > > + [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, > > +};
On Sun, Apr 30, 2023 at 06:35:13PM +0200, Zahari Doychev wrote: > On Sun, Apr 30, 2023 at 05:49:57PM +0300, Ido Schimmel wrote: > > On Tue, Apr 25, 2023 at 11:16:29PM +0200, Zahari Doychev wrote: > > > +static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { > > > + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), > > > > Instead of 7, can you use FIELD_MAX(FLOW_DIS_CFM_MDL_MASK) like you did > > in the previous version? > > > > It seems that the macro can be use only inside functions. I wanted to use it > but I was getting the following error: > > linux/include/linux/bitfield.h:86:9: error: braced-group within expression allowed only inside a function I see. Another option that I personally find better than hard-coding 7 is the below: diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h index 479b66b11d2d..52f30906b210 100644 --- a/include/net/flow_dissector.h +++ b/include/net/flow_dissector.h @@ -317,6 +317,7 @@ struct flow_dissector_key_cfm { }; #define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5) +#define FLOW_DIS_CFM_MDL_MAX 7 enum flow_dissector_key_id { FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */ diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 5d77da484a88..85fc77063866 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -772,7 +772,8 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { }; static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { - [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, + FLOW_DIS_CFM_MDL_MAX), [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, };
On Mon, May 01, 2023 at 09:56:15AM +0300, Ido Schimmel wrote: > On Sun, Apr 30, 2023 at 06:35:13PM +0200, Zahari Doychev wrote: > > On Sun, Apr 30, 2023 at 05:49:57PM +0300, Ido Schimmel wrote: > > > On Tue, Apr 25, 2023 at 11:16:29PM +0200, Zahari Doychev wrote: > > > > +static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { > > > > + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), > > > > > > Instead of 7, can you use FIELD_MAX(FLOW_DIS_CFM_MDL_MASK) like you did > > > in the previous version? > > > > > > > It seems that the macro can be use only inside functions. I wanted to use it > > but I was getting the following error: > > > > linux/include/linux/bitfield.h:86:9: error: braced-group within expression allowed only inside a function > > I see. Another option that I personally find better than hard-coding 7 > is the below: I was thinking about the same. I will change it in the next version. Thanks, Zahari > > diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h > index 479b66b11d2d..52f30906b210 100644 > --- a/include/net/flow_dissector.h > +++ b/include/net/flow_dissector.h > @@ -317,6 +317,7 @@ struct flow_dissector_key_cfm { > }; > > #define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5) > +#define FLOW_DIS_CFM_MDL_MAX 7 > > enum flow_dissector_key_id { > FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */ > diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c > index 5d77da484a88..85fc77063866 100644 > --- a/net/sched/cls_flower.c > +++ b/net/sched/cls_flower.c > @@ -772,7 +772,8 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { > }; > > static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { > - [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), > + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, > + FLOW_DIS_CFM_MDL_MAX), > [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, > };
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 648a82f32666..8e3f809c9a03 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -594,6 +594,8 @@ enum { TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */ + TCA_FLOWER_KEY_CFM, /* nested */ + __TCA_FLOWER_MAX, }; @@ -702,6 +704,13 @@ enum { TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1), }; +enum { + TCA_FLOWER_KEY_CFM_OPT_UNSPEC, + TCA_FLOWER_KEY_CFM_MD_LEVEL, + TCA_FLOWER_KEY_CFM_OPCODE, + TCA_FLOWER_KEY_CFM_OPT_MAX, +}; + #define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */ /* Match-all classifier */ diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index cc49256d5318..5d77da484a88 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -11,6 +11,7 @@ #include <linux/rhashtable.h> #include <linux/workqueue.h> #include <linux/refcount.h> +#include <linux/bitfield.h> #include <linux/if_ether.h> #include <linux/in6.h> @@ -71,6 +72,7 @@ struct fl_flow_key { struct flow_dissector_key_num_of_vlans num_of_vlans; struct flow_dissector_key_pppoe pppoe; struct flow_dissector_key_l2tpv3 l2tpv3; + struct flow_dissector_key_cfm cfm; } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ struct fl_flow_mask_range { @@ -720,7 +722,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { [TCA_FLOWER_KEY_PPPOE_SID] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_PPP_PROTO] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_L2TPV3_SID] = { .type = NLA_U32 }, - + [TCA_FLOWER_KEY_CFM] = { .type = NLA_NESTED }, }; static const struct nla_policy @@ -769,6 +771,11 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL] = { .type = NLA_U32 }, }; +static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { + [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, 7), + [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, +}; + static void fl_set_key_val(struct nlattr **tb, void *val, int val_type, void *mask, int mask_type, int len) @@ -1653,6 +1660,54 @@ static bool is_vlan_key(struct nlattr *tb, __be16 *ethertype, return false; } +static int fl_set_key_cfm_md_level(struct nlattr **tb, + struct fl_flow_key *key, + struct fl_flow_key *mask, + struct netlink_ext_ack *extack) +{ + u8 level; + + if (!tb[TCA_FLOWER_KEY_CFM_MD_LEVEL]) + return 0; + + level = nla_get_u8(tb[TCA_FLOWER_KEY_CFM_MD_LEVEL]); + key->cfm.mdl_ver = FIELD_PREP(FLOW_DIS_CFM_MDL_MASK, level); + mask->cfm.mdl_ver = FLOW_DIS_CFM_MDL_MASK; + + return 0; +} + +static void fl_set_key_cfm_opcode(struct nlattr **tb, + struct fl_flow_key *key, + struct fl_flow_key *mask, + struct netlink_ext_ack *extack) +{ + fl_set_key_val(tb, &key->cfm.opcode, TCA_FLOWER_KEY_CFM_OPCODE, + &mask->cfm.opcode, TCA_FLOWER_UNSPEC, + sizeof(key->cfm.opcode)); +} + +static int fl_set_key_cfm(struct nlattr **tb, + struct fl_flow_key *key, + struct fl_flow_key *mask, + struct netlink_ext_ack *extack) +{ + struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX]; + int err; + + if (!tb[TCA_FLOWER_KEY_CFM]) + return 0; + + err = nla_parse_nested(nla_cfm_opt, TCA_FLOWER_KEY_CFM_OPT_MAX, + tb[TCA_FLOWER_KEY_CFM], cfm_opt_policy, extack); + if (err < 0) + return err; + + fl_set_key_cfm_opcode(nla_cfm_opt, key, mask, extack); + + return fl_set_key_cfm_md_level(nla_cfm_opt, key, mask, extack); +} + 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) @@ -1803,6 +1858,10 @@ static int fl_set_key(struct net *net, struct nlattr **tb, TCA_FLOWER_KEY_L2TPV3_SID, &mask->l2tpv3.session_id, TCA_FLOWER_UNSPEC, sizeof(key->l2tpv3.session_id)); + } else if (key->basic.n_proto == htons(ETH_P_CFM)) { + ret = fl_set_key_cfm(tb, key, mask, extack); + if (ret) + return ret; } if (key->basic.ip_proto == IPPROTO_TCP || @@ -1985,6 +2044,8 @@ static void fl_init_dissector(struct flow_dissector *dissector, FLOW_DISSECTOR_KEY_PPPOE, pppoe); FL_KEY_SET_IF_MASKED(mask, keys, cnt, FLOW_DISSECTOR_KEY_L2TPV3, l2tpv3); + FL_KEY_SET_IF_MASKED(mask, keys, cnt, + FLOW_DISSECTOR_KEY_CFM, cfm); skb_flow_dissector_init(dissector, keys, cnt); } @@ -3004,6 +3065,43 @@ static int fl_dump_key_ct(struct sk_buff *skb, return -EMSGSIZE; } +static int fl_dump_key_cfm(struct sk_buff *skb, + struct flow_dissector_key_cfm *key, + struct flow_dissector_key_cfm *mask) +{ + struct nlattr *opts; + int err; + u8 mdl; + + if (!memchr_inv(mask, 0, sizeof(*mask))) + return 0; + + opts = nla_nest_start(skb, TCA_FLOWER_KEY_CFM); + if (!opts) + return -EMSGSIZE; + + if (FIELD_GET(FLOW_DIS_CFM_MDL_MASK, mask->mdl_ver)) { + mdl = FIELD_GET(FLOW_DIS_CFM_MDL_MASK, key->mdl_ver); + err = nla_put_u8(skb, TCA_FLOWER_KEY_CFM_MD_LEVEL, mdl); + if (err) + goto err_cfm_opts; + } + + if (mask->opcode) { + err = nla_put_u8(skb, TCA_FLOWER_KEY_CFM_OPCODE, key->opcode); + if (err) + goto err_cfm_opts; + } + + nla_nest_end(skb, opts); + + return 0; + +err_cfm_opts: + nla_nest_cancel(skb, opts); + return err; +} + static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type, struct flow_dissector_key_enc_opts *enc_opts) { @@ -3286,6 +3384,9 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net, sizeof(key->hash.hash))) goto nla_put_failure; + if (fl_dump_key_cfm(skb, &key->cfm, &mask->cfm)) + goto nla_put_failure; + return 0; nla_put_failure: