[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20180322115328.qoozkea4cfioqir6@netronome.com>
Date: Thu, 22 Mar 2018 12:53:29 +0100
From: Simon Horman <simon.horman@...ronome.com>
To: Jiri Benc <jbenc@...hat.com>
Cc: Jiri Pirko <jiri@...lanox.com>,
Jamal Hadi Salim <jhs@...atatu.com>,
Cong Wang <xiyou.wangcong@...il.com>, netdev@...r.kernel.org,
oss-drivers@...ronome.com,
Pieter Jansen van Vuuren
<pieter.jansenvanvuuren@...ronome.com>
Subject: Re: [PATCH/RFC 3/3] net/sched: add tunnel option support to
act_tunnel_key
On Fri, Mar 09, 2018 at 12:53:17PM +0100, Jiri Benc wrote:
> On Tue, 6 Mar 2018 18:08:05 +0100, Simon Horman wrote:
> > +static int
> > +tunnel_key_copy_geneve_opt(const struct nlattr *nla, int dst_len, void *dst,
> > + struct netlink_ext_ack *extack)
> > +{
> > + struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
> > + int err, data_len, opt_len;
> > + u8 *data;
> > +
> > + err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX,
> > + nla, geneve_opt_policy, extack);
> > + if (err < 0)
> > + return err;
> > +
> > + if (!tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] ||
> > + !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] ||
> > + !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]) {
> > + NL_SET_ERR_MSG(extack, "Missing tunnel key enc geneve option class, type or data");
>
> I think it's obvious by now that I don't like the "enc" :-)
>
> > + return -EINVAL;
> > + }
> > +
> > + data = nla_data(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
> > + data_len = nla_len(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
> > + if (data_len < 4) {
> > + NL_SET_ERR_MSG(extack, "Tunnel key enc geneve option data is less than 4 bytes long");
> > + return -ERANGE;
> > + }
> > + if (data_len % 4) {
> > + NL_SET_ERR_MSG(extack, "Tunnel key enc geneve option data is not a multiple of 4 bytes long");
> > + return -ERANGE;
> > + }
> > +
> > + opt_len = sizeof(struct geneve_opt) + data_len;
> > + if (dst) {
> > + struct geneve_opt *opt = dst;
> > + u16 class;
> > +
> > + if (dst_len < opt_len) {
> > + NL_SET_ERR_MSG(extack, "Tunnel key enc geneve option data length is longer than the supplied data");
>
> I don't understand this error. What can the user do about it?
> Furthermore, the error is not propagated to the user space (see also
> below).
>
> Shouldn't this be WARN_ON or something?
Sure, that is fine by me.
>
> > + return -EINVAL;
> > + }
> > +
> > + class = nla_get_u16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]);
> > + put_unaligned_be16(class, &opt->opt_class);
>
> How this can be unaligned, given we check that the option length is a
> multiple of 4 bytes and the option header is 4 bytes?
True.
> > +
> > + opt->type = nla_get_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]);
> > + opt->length = data_len / 4; /* length is in units of 4 bytes */
> > + opt->r1 = 0;
> > + opt->r2 = 0;
> > + opt->r3 = 0;
> > +
> > + memcpy(opt + 1, data, data_len);
> > + }
> > +
> > + return opt_len;
> > +}
> > +
> > +static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
> > + int dst_len, struct netlink_ext_ack *extack)
>
> Please be consistent with parameter ordering, dst and dst_len are in a
> different order here and in tunnel_key_copy_geneve_opt.
Sure, will do.
> [...]
> > @@ -157,6 +292,11 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
> > goto err_out;
> > }
> >
> > + if (opts_len)
> > + tunnel_key_opts_set(tb[TCA_TUNNEL_KEY_ENC_OPTS],
> > + &metadata->u.tun_info, opts_len,
> > + extack);
>
> You need to propagate the error here. The previous validation is not
> enough as errors while copying to tun_info were not covered.
Thanks, sorry for missing that.
> > +
> > metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX;
> > break;
> > default:
> > @@ -221,6 +361,53 @@ static void tunnel_key_release(struct tc_action *a)
> > kfree_rcu(params, rcu);
> > }
> >
> > +static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
> > + const struct ip_tunnel_info *info)
> > +{
> > + int len = info->options_len;
> > + u8 *src = (u8 *)(info + 1);
> > +
> > + while (len > 0) {
> > + struct geneve_opt *opt = (struct geneve_opt *)src;
> > + u16 class;
> > +
> > + class = get_unaligned_be16(&opt->opt_class);
>
> I don't think this can be unaligned.
Thanks, I'm not sure why I thought otherwise.
> > + if (nla_put_u16(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,
> > + class) ||
> > + nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE,
> > + opt->type) ||
> > + nla_put(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA,
> > + opt->length * 4, opt + 1))
> > + return -EMSGSIZE;
> > +
> > + len -= sizeof(struct geneve_opt) + opt->length * 4;
> > + src += sizeof(struct geneve_opt) + opt->length * 4;
> > + }
>
> All of this needs to be nested in TCA_TUNNEL_KEY_ENC_OPTS_GENEVE.
Agreed.
> > +
> > + return 0;
> > +}
> > +
> > +static int tunnel_key_opts_dump(struct sk_buff *skb,
> > + const struct ip_tunnel_info *info)
> > +{
> > + struct nlattr *start;
> > + int err;
> > +
> > + if (!info->options_len)
> > + return 0;
> > +
> > + start = nla_nest_start(skb, TCA_TUNNEL_KEY_ENC_OPTS);
> > + if (!start)
> > + return -EMSGSIZE;
> > +
> > + err = tunnel_key_geneve_opts_dump(skb, info);
>
> How do you know it is geneve opts and not some other (future) tunnel
> type options?
>
> This is actually more fundamental problem with this patch. The
> metadata_dst options are blindly set to the provided data, yet nowhere
> we check whether the tunnel type matches. This must be done somehow. We
> probably need to store the options type in metadata_dst.
Thanks for pointing that out. Its a pretty fundamental oversight.
Powered by blists - more mailing lists