|
|
07a51b |
From 3628115b53f7b693f623638fb5ec71bc292a3a00 Mon Sep 17 00:00:00 2001
|
|
|
07a51b |
From: Andrea Claudi <aclaudi@redhat.com>
|
|
|
07a51b |
Date: Thu, 4 Jun 2020 21:43:01 +0200
|
|
|
07a51b |
Subject: [PATCH] iproute_lwtunnel: add options support for erspan metadata
|
|
|
07a51b |
|
|
|
07a51b |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485
|
|
|
07a51b |
Upstream Status: unknown commit 39fa047938fbe
|
|
|
07a51b |
|
|
|
07a51b |
commit 39fa047938fbef6cd08687b0daa4d86afbfdc61c
|
|
|
07a51b |
Author: Xin Long <lucien.xin@gmail.com>
|
|
|
07a51b |
Date: Mon Apr 27 18:27:47 2020 +0800
|
|
|
07a51b |
|
|
|
07a51b |
iproute_lwtunnel: add options support for erspan metadata
|
|
|
07a51b |
|
|
|
07a51b |
This patch is to add LWTUNNEL_IP_OPTS_ERSPAN's parse and print to implement
|
|
|
07a51b |
erspan options support in iproute_lwtunnel.
|
|
|
07a51b |
|
|
|
07a51b |
Option is expressed as version:index:dir:hwid, dir and hwid will be parsed
|
|
|
07a51b |
when version is 2, while index will be parsed when version is 1. All of
|
|
|
07a51b |
these are numbers. erspan doesn't support multiple options.
|
|
|
07a51b |
|
|
|
07a51b |
With this patch, users can add and dump erspan options like:
|
|
|
07a51b |
|
|
|
07a51b |
# ip netns add a
|
|
|
07a51b |
# ip netns add b
|
|
|
07a51b |
# ip -n a link add eth0 type veth peer name eth0 netns b
|
|
|
07a51b |
# ip -n a link set eth0 up
|
|
|
07a51b |
# ip -n b link set eth0 up
|
|
|
07a51b |
# ip -n a addr add 10.1.0.1/24 dev eth0
|
|
|
07a51b |
# ip -n b addr add 10.1.0.2/24 dev eth0
|
|
|
07a51b |
# ip -n b link add erspan1 type erspan key 1 seq erspan 123 \
|
|
|
07a51b |
local 10.1.0.2 remote 10.1.0.1
|
|
|
07a51b |
# ip -n b addr add 1.1.1.1/24 dev erspan1
|
|
|
07a51b |
# ip -n b link set erspan1 up
|
|
|
07a51b |
# ip -n b route add 2.1.1.0/24 dev erspan1
|
|
|
07a51b |
# ip -n a link add erspan1 type erspan key 1 seq local 10.1.0.1 external
|
|
|
07a51b |
# ip -n a addr add 2.1.1.1/24 dev erspan1
|
|
|
07a51b |
# ip -n a link set erspan1 up
|
|
|
07a51b |
# ip -n a route add 1.1.1.0/24 encap ip id 1 \
|
|
|
07a51b |
erspan_opts 2:123:1:2 dst 10.1.0.2 dev erspan1
|
|
|
07a51b |
# ip -n a route show
|
|
|
07a51b |
# ip netns exec a ping 1.1.1.1 -c 1
|
|
|
07a51b |
|
|
|
07a51b |
1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0
|
|
|
07a51b |
erspan_opts 2:0:1:2 dev erspan1 scope link
|
|
|
07a51b |
|
|
|
07a51b |
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
|
|
07a51b |
64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.124 ms
|
|
|
07a51b |
|
|
|
07a51b |
v1->v2:
|
|
|
07a51b |
- improve the changelog.
|
|
|
07a51b |
- use PRINT_ANY to support dumping with json format.
|
|
|
07a51b |
v2->v3:
|
|
|
07a51b |
- implement proper JSON object for opts instead of just bunch of strings.
|
|
|
07a51b |
v3->v4:
|
|
|
07a51b |
- keep the same format between input and output, json and non json.
|
|
|
07a51b |
- print version, index, dir and hwid as uint.
|
|
|
07a51b |
|
|
|
07a51b |
Signed-off-by: Xin Long <lucien.xin@gmail.com>
|
|
|
07a51b |
Signed-off-by: David Ahern <dsahern@gmail.com>
|
|
|
07a51b |
---
|
|
|
07a51b |
ip/iproute_lwtunnel.c | 140 ++++++++++++++++++++++++++++++++++++++++++
|
|
|
07a51b |
1 file changed, 140 insertions(+)
|
|
|
07a51b |
|
|
|
07a51b |
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
|
|
|
07a51b |
index 17514dcad9219..7e145768c111f 100644
|
|
|
07a51b |
--- a/ip/iproute_lwtunnel.c
|
|
|
07a51b |
+++ b/ip/iproute_lwtunnel.c
|
|
|
07a51b |
@@ -350,6 +350,38 @@ static void lwtunnel_print_vxlan_opts(struct rtattr *attr)
|
|
|
07a51b |
close_json_array(PRINT_JSON, name);
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
+static void lwtunnel_print_erspan_opts(struct rtattr *attr)
|
|
|
07a51b |
+{
|
|
|
07a51b |
+ struct rtattr *tb[LWTUNNEL_IP_OPT_ERSPAN_MAX + 1];
|
|
|
07a51b |
+ struct rtattr *i = RTA_DATA(attr);
|
|
|
07a51b |
+ char *name = "erspan_opts";
|
|
|
07a51b |
+ __u8 ver, hwid, dir;
|
|
|
07a51b |
+ __u32 idx;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ parse_rtattr(tb, LWTUNNEL_IP_OPT_ERSPAN_MAX, i, RTA_PAYLOAD(attr));
|
|
|
07a51b |
+ ver = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_VER]);
|
|
|
07a51b |
+ if (ver == 1) {
|
|
|
07a51b |
+ idx = rta_getattr_be32(tb[LWTUNNEL_IP_OPT_ERSPAN_INDEX]);
|
|
|
07a51b |
+ dir = 0;
|
|
|
07a51b |
+ hwid = 0;
|
|
|
07a51b |
+ } else {
|
|
|
07a51b |
+ idx = 0;
|
|
|
07a51b |
+ dir = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_DIR]);
|
|
|
07a51b |
+ hwid = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_HWID]);
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+
|
|
|
07a51b |
+ print_nl();
|
|
|
07a51b |
+ print_string(PRINT_FP, name, "\t%s ", name);
|
|
|
07a51b |
+ open_json_array(PRINT_JSON, name);
|
|
|
07a51b |
+ open_json_object(NULL);
|
|
|
07a51b |
+ print_uint(PRINT_ANY, "ver", "%u", ver);
|
|
|
07a51b |
+ print_uint(PRINT_ANY, "index", ":%u", idx);
|
|
|
07a51b |
+ print_uint(PRINT_ANY, "dir", ":%u", dir);
|
|
|
07a51b |
+ print_uint(PRINT_ANY, "hwid", ":%u ", hwid);
|
|
|
07a51b |
+ close_json_object();
|
|
|
07a51b |
+ close_json_array(PRINT_JSON, name);
|
|
|
07a51b |
+}
|
|
|
07a51b |
+
|
|
|
07a51b |
static void lwtunnel_print_opts(struct rtattr *attr)
|
|
|
07a51b |
{
|
|
|
07a51b |
struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1];
|
|
|
07a51b |
@@ -359,6 +391,8 @@ static void lwtunnel_print_opts(struct rtattr *attr)
|
|
|
07a51b |
lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]);
|
|
|
07a51b |
else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN])
|
|
|
07a51b |
lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]);
|
|
|
07a51b |
+ else if (tb_opt[LWTUNNEL_IP_OPTS_ERSPAN])
|
|
|
07a51b |
+ lwtunnel_print_erspan_opts(tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]);
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
static void print_encap_ip(FILE *fp, struct rtattr *encap)
|
|
|
07a51b |
@@ -973,6 +1007,82 @@ static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta)
|
|
|
07a51b |
return 0;
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
+static int lwtunnel_parse_erspan_opts(char *str, size_t len, struct rtattr *rta)
|
|
|
07a51b |
+{
|
|
|
07a51b |
+ struct rtattr *nest;
|
|
|
07a51b |
+ char *token;
|
|
|
07a51b |
+ int i, err;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_ERSPAN | NLA_F_NESTED);
|
|
|
07a51b |
+ i = 1;
|
|
|
07a51b |
+ token = strsep(&str, ":");
|
|
|
07a51b |
+ while (token) {
|
|
|
07a51b |
+ switch (i) {
|
|
|
07a51b |
+ case LWTUNNEL_IP_OPT_ERSPAN_VER:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ __u8 opt_type;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (!strlen(token))
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ err = get_u8(&opt_type, token, 0);
|
|
|
07a51b |
+ if (err)
|
|
|
07a51b |
+ return err;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ rta_addattr8(rta, len, i, opt_type);
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case LWTUNNEL_IP_OPT_ERSPAN_INDEX:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ __be32 opt_class;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (!strlen(token))
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ err = get_be32(&opt_class, token, 0);
|
|
|
07a51b |
+ if (err)
|
|
|
07a51b |
+ return err;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ rta_addattr32(rta, len, i, opt_class);
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case LWTUNNEL_IP_OPT_ERSPAN_DIR:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ __u8 opt_type;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (!strlen(token))
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ err = get_u8(&opt_type, token, 0);
|
|
|
07a51b |
+ if (err)
|
|
|
07a51b |
+ return err;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ rta_addattr8(rta, len, i, opt_type);
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case LWTUNNEL_IP_OPT_ERSPAN_HWID:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ __u8 opt_type;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (!strlen(token))
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ err = get_u8(&opt_type, token, 0);
|
|
|
07a51b |
+ if (err)
|
|
|
07a51b |
+ return err;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ rta_addattr8(rta, len, i, opt_type);
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ default:
|
|
|
07a51b |
+ fprintf(stderr, "Unknown \"geneve_opts\" type\n");
|
|
|
07a51b |
+ return -1;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+
|
|
|
07a51b |
+ token = strsep(&str, ":");
|
|
|
07a51b |
+ i++;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+
|
|
|
07a51b |
+ rta_nest_end(rta, nest);
|
|
|
07a51b |
+ return 0;
|
|
|
07a51b |
+}
|
|
|
07a51b |
+
|
|
|
07a51b |
static int parse_encap_ip(struct rtattr *rta, size_t len,
|
|
|
07a51b |
int *argcp, char ***argvp)
|
|
|
07a51b |
{
|
|
|
07a51b |
@@ -1059,6 +1169,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
|
|
|
07a51b |
invarg("\"vxlan_opts\" value is invalid\n",
|
|
|
07a51b |
*argv);
|
|
|
07a51b |
rta_nest_end(rta, nest);
|
|
|
07a51b |
+ } else if (strcmp(*argv, "erspan_opts") == 0) {
|
|
|
07a51b |
+ struct rtattr *nest;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (opts_ok++)
|
|
|
07a51b |
+ duparg2("opts", *argv);
|
|
|
07a51b |
+
|
|
|
07a51b |
+ NEXT_ARG();
|
|
|
07a51b |
+
|
|
|
07a51b |
+ nest = rta_nest(rta, len,
|
|
|
07a51b |
+ LWTUNNEL_IP_OPTS | NLA_F_NESTED);
|
|
|
07a51b |
+ ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ invarg("\"erspan_opts\" value is invalid\n",
|
|
|
07a51b |
+ *argv);
|
|
|
07a51b |
+ rta_nest_end(rta, nest);
|
|
|
07a51b |
} else if (strcmp(*argv, "key") == 0) {
|
|
|
07a51b |
if (key_ok++)
|
|
|
07a51b |
duparg2("key", *argv);
|
|
|
07a51b |
@@ -1258,6 +1383,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
|
|
|
07a51b |
invarg("\"vxlan_opts\" value is invalid\n",
|
|
|
07a51b |
*argv);
|
|
|
07a51b |
rta_nest_end(rta, nest);
|
|
|
07a51b |
+ } else if (strcmp(*argv, "erspan_opts") == 0) {
|
|
|
07a51b |
+ struct rtattr *nest;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (opts_ok++)
|
|
|
07a51b |
+ duparg2("opts", *argv);
|
|
|
07a51b |
+
|
|
|
07a51b |
+ NEXT_ARG();
|
|
|
07a51b |
+
|
|
|
07a51b |
+ nest = rta_nest(rta, len,
|
|
|
07a51b |
+ LWTUNNEL_IP_OPTS | NLA_F_NESTED);
|
|
|
07a51b |
+ ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ invarg("\"erspan_opts\" value is invalid\n",
|
|
|
07a51b |
+ *argv);
|
|
|
07a51b |
+ rta_nest_end(rta, nest);
|
|
|
07a51b |
} else if (strcmp(*argv, "key") == 0) {
|
|
|
07a51b |
if (key_ok++)
|
|
|
07a51b |
duparg2("key", *argv);
|
|
|
07a51b |
--
|
|
|
07a51b |
2.26.2
|
|
|
07a51b |
|