aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2020-04-27 18:27:46 +0800
committerDavid Ahern <dsahern@gmail.com>2020-05-01 16:33:03 +0000
commitb1bc0f38922220b379ed39552a5e2a7cf9dccd92 (patch)
treebc94a02ee03ba7c06ebefae460f1c127da82c78a
parentca7614d4c6f456187d831a8202bb4a8559a72f8b (diff)
downloadiproute2-b1bc0f38922220b379ed39552a5e2a7cf9dccd92.tar.gz
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 <lucien.xin@gmail.com> Signed-off-by: David Ahern <dsahern@gmail.com>
-rw-r--r--ip/iproute_lwtunnel.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 859985366..bbd0ace78 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -333,6 +333,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];
@@ -340,6 +360,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)
@@ -938,6 +960,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)
{
@@ -1009,6 +1047,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);
@@ -1193,6 +1246,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);