[ovs-dev] [PATCH ovs 1/2] lib/tc: add geneve with option encap action offload
Simon Horman
simon.horman at netronome.com
Thu Aug 30 13:33:25 UTC 2018
Hi Pieter,
On Tue, Aug 21, 2018 at 02:49:45PM +0100, Pieter Jansen van Vuuren wrote:
> Add TC offload support for encapsulating geneve tunnels with options.
>
> Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren at netronome.com>
> Reviewed-by: Simon Horman <simon.horman at netronome.com>
thanks for your patch. In general I am happy with this and would value any
feedback from others.
Travis noticed an alignment problem which I have annotated inline.
> ---
> include/linux/tc_act/tc_tunnel_key.h | 23 ++++++
> lib/netdev-tc-offloads.c | 30 ++++++++
> lib/tc.c | 106 ++++++++++++++++++++++++++-
> lib/tc.h | 2 +
> 4 files changed, 158 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/tc_act/tc_tunnel_key.h b/include/linux/tc_act/tc_tunnel_key.h
> index 26cbd2ff1..f13acf17d 100644
> --- a/include/linux/tc_act/tc_tunnel_key.h
> +++ b/include/linux/tc_act/tc_tunnel_key.h
> @@ -47,6 +47,29 @@ enum {
>
> #define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)
>
> +enum {
> + TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC,
> + TCA_TUNNEL_KEY_ENC_OPTS_GENEVE, /* Nested
> + * TCA_TUNNEL_KEY_ENC_OPTS_GENEVE
> + * attributes
> + */
> + __TCA_TUNNEL_KEY_ENC_OPTS_MAX,
> +};
> +
> +#define TCA_TUNNEL_KEY_ENC_OPTS_MAX (__TCA_TUNNEL_KEY_ENC_OPTS_MAX - 1)
> +
> +enum {
> + TCA_TUNNEL_KEY_ENC_OPT_GENEVE_UNSPEC,
> + TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS, /* be16 */
> + TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */
> + TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */
> +
> + __TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX,
> +};
> +
> +#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \
> + (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1)
> +
> #endif /* __KERNEL__ || HAVE_TCA_TUNNEL_KEY_ENC_TTL */
>
> #endif /* __LINUX_TC_ACT_TC_TUNNEL_KEY_WRAPPER_H */
> diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c
> index 7bc745e95..0612b1348 100644
> --- a/lib/netdev-tc-offloads.c
> +++ b/lib/netdev-tc-offloads.c
> @@ -409,6 +409,29 @@ parse_flower_rewrite_to_netlink_action(struct ofpbuf *buf,
> }
> }
>
> +static void parse_tc_flower_geneve_opts(struct tc_action *action,
> + struct ofpbuf *buf)
> +{
> + int tun_opt_len = action->encap.data.present.len;
> + size_t geneve_off;
> + int idx = 0;
> +
> + if (!tun_opt_len) {
> + return;
> + }
> +
> + geneve_off = nl_msg_start_nested(buf, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS);
> + while (tun_opt_len) {
> + struct geneve_opt *opt;
> +
> + opt = &action->encap.data.opts.gnv[idx];
> + nl_msg_put(buf, opt, sizeof(struct geneve_opt) + opt->length * 4);
> + idx += sizeof(struct geneve_opt) + opt->length * 4;
> + tun_opt_len -= sizeof(struct geneve_opt) + opt->length * 4;
> + }
> + nl_msg_end_nested(buf, geneve_off);
> +}
> +
> static int
> parse_tc_flower_to_match(struct tc_flower *flower,
> struct match *match,
> @@ -580,6 +603,7 @@ parse_tc_flower_to_match(struct tc_flower *flower,
> nl_msg_put_be16(buf, OVS_TUNNEL_KEY_ATTR_TP_DST,
> action->encap.tp_dst);
>
> + parse_tc_flower_geneve_opts(action, buf);
> nl_msg_end_nested(buf, tunnel_offset);
> nl_msg_end_nested(buf, set_offset);
> }
> @@ -786,6 +810,12 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action,
> action->encap.tp_dst = nl_attr_get_be16(tun_attr);
> }
> break;
> + case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: {
> + memcpy(action->encap.data.opts.gnv, nl_attr_get(tun_attr),
> + nl_attr_get_size(tun_attr));
> + action->encap.data.present.len = nl_attr_get_size(tun_attr);
> + }
> + break;
> }
> }
>
> diff --git a/lib/tc.c b/lib/tc.c
> index bbc382326..fcaf7832e 100644
> --- a/lib/tc.c
> +++ b/lib/tc.c
> @@ -659,8 +659,72 @@ static const struct nl_policy tunnel_key_policy[] = {
> [TCA_TUNNEL_KEY_ENC_DST_PORT] = { .type = NL_A_U16, .optional = true, },
> [TCA_TUNNEL_KEY_ENC_TOS] = { .type = NL_A_U8, .optional = true, },
> [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NL_A_U8, .optional = true, },
> + [TCA_TUNNEL_KEY_ENC_OPTS] = { .type = NL_A_NESTED, .optional = true,},
> };
>
> +static void
> +nl_parse_act_geneve_opts(const struct nlattr *in_nlattr,
> + struct tc_action *action)
> +{
> + struct geneve_opt *opt = NULL;
> + const struct ofpbuf *msg;
> + struct nlattr *nla;
> + struct ofpbuf buf;
> + size_t left;
> + int cnt;
> +
> + nl_attr_get_nested(in_nlattr, &buf);
> + msg = &buf;
> +
> + cnt = 0;
> + NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
> + uint16_t type = nl_attr_type(nla);
> +
> + switch (type) {
> + case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS:
> + opt = (struct geneve_opt *) &action->encap.data.opts.gnv[cnt];
Clang believe that casting from uint8_t * to unsigned char *
changes the alignment requirements from 1 to 2.
https://travis-ci.org/horms2/ovs/jobs/422509606
> + opt->opt_class = nl_attr_get_be16(nla);
> + action->encap.data.present.len += sizeof(struct geneve_opt);
> + cnt += sizeof(struct geneve_opt);
> + break;
> + case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE:
> + opt->type = nl_attr_get_u8(nla);
> + break;
> + case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA:
> + opt->length = nl_attr_get_size(nla) / 4;
> + memcpy(opt + 1, nl_attr_get_unspec(nla, 1), opt->length * 4);
> + action->encap.data.present.len += opt->length * 4;
> + cnt += opt->length * 4;
> + break;
> + }
> + }
> +}
> +
> +static void
> +nl_parse_act_tunnel_opts(struct nlattr *options, struct tc_action *action)
> +{
> + const struct ofpbuf *msg;
> + struct nlattr *nla;
> + struct ofpbuf buf;
> + size_t left;
> +
> + if (!options) {
> + return;
> + }
> +
> + nl_attr_get_nested(options, &buf);
> + msg = &buf;
> +
> + NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
> + uint16_t type = nl_attr_type(nla);
> + switch (type) {
> + case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE:
> + nl_parse_act_geneve_opts(nla, action);
> + break;
> + }
> + }
> +}
> +
> static int
> nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower)
> {
> @@ -686,6 +750,7 @@ nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower)
> struct nlattr *ipv6_dst = tun_attrs[TCA_TUNNEL_KEY_ENC_IPV6_DST];
> struct nlattr *tos = tun_attrs[TCA_TUNNEL_KEY_ENC_TOS];
> struct nlattr *ttl = tun_attrs[TCA_TUNNEL_KEY_ENC_TTL];
> + struct nlattr *tun_opt = tun_attrs[TCA_TUNNEL_KEY_ENC_OPTS];
>
> action = &flower->actions[flower->action_count++];
> action->type = TC_ACT_ENCAP;
> @@ -701,6 +766,7 @@ nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower)
> action->encap.tp_dst = dst_port ? nl_attr_get_be16(dst_port) : 0;
> action->encap.tos = tos ? nl_attr_get_u8(tos) : 0;
> action->encap.ttl = ttl ? nl_attr_get_u8(ttl) : 0;
> + nl_parse_act_tunnel_opts(tun_opt, action);
> } else if (tun->t_action == TCA_TUNNEL_KEY_ACT_RELEASE) {
> flower->tunnel.tunnel = true;
> } else {
> @@ -1268,13 +1334,44 @@ nl_msg_put_act_tunnel_key_release(struct ofpbuf *request)
> nl_msg_end_nested(request, offset);
> }
>
> +static void
> +nl_msg_put_act_tunnel_geneve_option(struct ofpbuf *request,
> + uint8_t *tun_options, int tun_opt_len)
> +{
> + const struct geneve_opt *opt;
> + size_t outer, inner;
> + int idx = 0;
> +
> + if (!tun_opt_len) {
> + return;
> + }
> +
> + outer = nl_msg_start_nested(request, TCA_TUNNEL_KEY_ENC_OPTS);
> +
> + while (tun_opt_len) {
> + opt = (struct geneve_opt *) &tun_options[idx];
> + inner = nl_msg_start_nested(request, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
> + nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,
> + opt->opt_class);
> + nl_msg_put_u8(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE, opt->type);
> + nl_msg_put_unspec(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA, opt + 1,
> + opt->length * 4);
> + nl_msg_end_nested(request, inner);
> +
> + idx += sizeof(struct geneve_opt) + opt->length * 4;
> + tun_opt_len -= sizeof(struct geneve_opt) + opt->length * 4;
> + }
> +
> + nl_msg_end_nested(request, outer);
> +}
> +
> static void
> nl_msg_put_act_tunnel_key_set(struct ofpbuf *request, ovs_be64 id,
> ovs_be32 ipv4_src, ovs_be32 ipv4_dst,
> struct in6_addr *ipv6_src,
> struct in6_addr *ipv6_dst,
> - ovs_be16 tp_dst,
> - uint8_t tos, uint8_t ttl)
> + ovs_be16 tp_dst, uint8_t tos, uint8_t ttl,
> + void *tun_options, int tun_opt_len)
> {
> size_t offset;
>
> @@ -1304,6 +1401,7 @@ nl_msg_put_act_tunnel_key_set(struct ofpbuf *request, ovs_be64 id,
> nl_msg_put_u8(request, TCA_TUNNEL_KEY_ENC_TTL, ttl);
> }
> nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_DST_PORT, tp_dst);
> + nl_msg_put_act_tunnel_geneve_option(request, tun_options, tun_opt_len);
> }
> nl_msg_end_nested(request, offset);
> }
> @@ -1546,7 +1644,9 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
> &action->encap.ipv6.ipv6_dst,
> action->encap.tp_dst,
> action->encap.tos,
> - action->encap.ttl);
> + action->encap.ttl,
> + action->encap.data.opts.gnv,
> + action->encap.data.present.len);
> nl_msg_end_nested(request, act_offset);
> }
> break;
> diff --git a/lib/tc.h b/lib/tc.h
> index aa8805df2..4ae06eb27 100644
> --- a/lib/tc.h
> +++ b/lib/tc.h
> @@ -27,6 +27,7 @@
> #include "odp-netlink.h"
> #include "openvswitch/ofpbuf.h"
> #include "openvswitch/flow.h"
> +#include "openvswitch/tun-metadata.h"
>
> /* For backwards compatability with older kernels */
> #ifndef TC_H_CLSACT
> @@ -140,6 +141,7 @@ struct tc_action {
> struct in6_addr ipv6_src;
> struct in6_addr ipv6_dst;
> } ipv6;
> + struct tun_metadata data;
> } encap;
> };
>
> --
> 2.17.0
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
More information about the dev
mailing list