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>
This commit is contained in:
parent
ca7614d4c6
commit
b1bc0f3892
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue