From 873511fb86756c40631f80963356179627d69d49 Mon Sep 17 00:00:00 2001 From: Andrea Claudi Date: Thu, 4 Jun 2020 21:43:01 +0200 Subject: [PATCH] iproute_lwtunnel: add options support for vxlan metadata Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 Upstream Status: unknown commit b1bc0f3892222 commit b1bc0f38922220b379ed39552a5e2a7cf9dccd92 Author: Xin Long Date: Mon Apr 27 18:27:46 2020 +0800 iproute_lwtunnel: add options support for vxlan metadata This patch is to add LWTUNNEL_IP_OPTS_VXLAN's parse and print to implement vxlan options support in iproute_lwtunnel. Option is expressed a number for gbp only, and vxlan doesn't support multiple options. With this patch, users can add and dump vxlan options like: # ip netns add a # ip netns add b # ip -n a link add eth0 type veth peer name eth0 netns b # ip -n a link set eth0 up # ip -n b link set eth0 up # ip -n a addr add 10.1.0.1/24 dev eth0 # ip -n b addr add 10.1.0.2/24 dev eth0 # ip -n b link add vxlan1 type vxlan id 1 local 10.1.0.2 \ remote 10.1.0.1 dev eth0 ttl 64 gbp # ip -n b addr add 1.1.1.1/24 dev vxlan1 # ip -n b link set vxlan1 up # ip -n b route add 2.1.1.0/24 dev vxlan1 # ip -n a link add vxlan1 type vxlan local 10.1.0.1 dev eth0 ttl 64 \ gbp external # ip -n a addr add 2.1.1.1/24 dev vxlan1 # ip -n a link set vxlan1 up # ip -n a route add 1.1.1.0/24 encap ip id 1 \ vxlan_opts 1110 dst 10.1.0.2 dev vxlan1 # ip -n a route show # ip netns exec a ping 1.1.1.1 -c 1 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 vxlan_opts 1110 dev vxlan1 scope link PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.111 ms v1->v2: - improve the changelog. - get_u32 with base = 0 for gbp. - use PRINT_ANY to support dumping with json format. v2->v3: - implement proper JSON array for opts. v3->v4: - keep the same format between input and output, json and non json. - print gbp as uint. Signed-off-by: Xin Long Signed-off-by: David Ahern --- ip/iproute_lwtunnel.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 76d906c47c44f..17514dcad9219 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -330,6 +330,26 @@ static void lwtunnel_print_geneve_opts(struct rtattr *attr) close_json_array(PRINT_JSON, name); } +static void lwtunnel_print_vxlan_opts(struct rtattr *attr) +{ + struct rtattr *tb[LWTUNNEL_IP_OPT_VXLAN_MAX + 1]; + struct rtattr *i = RTA_DATA(attr); + int rem = RTA_PAYLOAD(attr); + char *name = "vxlan_opts"; + __u32 gbp; + + parse_rtattr(tb, LWTUNNEL_IP_OPT_VXLAN_MAX, i, rem); + gbp = rta_getattr_u32(tb[LWTUNNEL_IP_OPT_VXLAN_GBP]); + + print_nl(); + print_string(PRINT_FP, name, "\t%s ", name); + open_json_array(PRINT_JSON, name); + open_json_object(NULL); + print_uint(PRINT_ANY, "gbp", "%u ", gbp); + close_json_object(); + close_json_array(PRINT_JSON, name); +} + static void lwtunnel_print_opts(struct rtattr *attr) { struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; @@ -337,6 +357,8 @@ static void lwtunnel_print_opts(struct rtattr *attr) parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr); if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE]) lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); + else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN]) + lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]); } static void print_encap_ip(FILE *fp, struct rtattr *encap) @@ -935,6 +957,22 @@ static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta) return 0; } +static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta) +{ + struct rtattr *nest; + __u32 gbp; + int err; + + nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_VXLAN | NLA_F_NESTED); + err = get_u32(&gbp, str, 0); + if (err) + return err; + rta_addattr32(rta, len, LWTUNNEL_IP_OPT_VXLAN_GBP, gbp); + + rta_nest_end(rta, nest); + return 0; +} + static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { @@ -1006,6 +1044,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, invarg("\"geneve_opts\" value is invalid\n", *argv); rta_nest_end(rta, nest); + } else if (strcmp(*argv, "vxlan_opts") == 0) { + struct rtattr *nest; + + if (opts_ok++) + duparg2("opts", *argv); + + NEXT_ARG(); + + nest = rta_nest(rta, len, + LWTUNNEL_IP_OPTS | NLA_F_NESTED); + ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); + if (ret) + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); } else if (strcmp(*argv, "key") == 0) { if (key_ok++) duparg2("key", *argv); @@ -1190,6 +1243,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, invarg("\"geneve_opts\" value is invalid\n", *argv); rta_nest_end(rta, nest); + } else if (strcmp(*argv, "vxlan_opts") == 0) { + struct rtattr *nest; + + if (opts_ok++) + duparg2("opts", *argv); + + NEXT_ARG(); + + nest = rta_nest(rta, len, + LWTUNNEL_IP_OPTS | NLA_F_NESTED); + ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); + if (ret) + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); } else if (strcmp(*argv, "key") == 0) { if (key_ok++) duparg2("key", *argv); -- 2.26.2