|
|
07a51b |
From 2fb8c115a8031d893fff588181cc42764391e4d5 Mon Sep 17 00:00:00 2001
|
|
|
07a51b |
From: Andrea Claudi <aclaudi@redhat.com>
|
|
|
07a51b |
Date: Thu, 4 Jun 2020 21:43:50 +0200
|
|
|
07a51b |
Subject: [PATCH] tc: m_tunnel_key: add options support for erpsan
|
|
|
07a51b |
|
|
|
07a51b |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485
|
|
|
07a51b |
Upstream Status: unknown commit 668fd9b25d9ec
|
|
|
07a51b |
|
|
|
07a51b |
commit 668fd9b25d9eca3067040273239f7825db95442b
|
|
|
07a51b |
Author: Xin Long <lucien.xin@gmail.com>
|
|
|
07a51b |
Date: Mon Apr 27 18:27:49 2020 +0800
|
|
|
07a51b |
|
|
|
07a51b |
tc: m_tunnel_key: add options support for erpsan
|
|
|
07a51b |
|
|
|
07a51b |
This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN's parse and
|
|
|
07a51b |
print to implement erspan options support in m_tunnel_key, like
|
|
|
07a51b |
Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support
|
|
|
07a51b |
to act_tunnel_key") for geneve options support.
|
|
|
07a51b |
|
|
|
07a51b |
Option is expressed as version:index:dir:hwid, dir and hwid will
|
|
|
07a51b |
be parsed when version is 2, while index will be parsed when
|
|
|
07a51b |
version is 1. erspan doesn't support multiple options.
|
|
|
07a51b |
|
|
|
07a51b |
With this patch, users can add and dump erspan options like:
|
|
|
07a51b |
|
|
|
07a51b |
# ip link add name erspan1 type erspan external
|
|
|
07a51b |
# tc qdisc add dev eth0 ingress
|
|
|
07a51b |
# tc filter add dev eth0 protocol ip parent ffff: \
|
|
|
07a51b |
flower indev eth0 \
|
|
|
07a51b |
ip_proto udp \
|
|
|
07a51b |
action tunnel_key \
|
|
|
07a51b |
set src_ip 10.0.99.192 \
|
|
|
07a51b |
dst_ip 10.0.99.193 \
|
|
|
07a51b |
dst_port 6081 \
|
|
|
07a51b |
id 11 \
|
|
|
07a51b |
erspan_opts 1:2:0:0 \
|
|
|
07a51b |
action mirred egress redirect dev erspan1
|
|
|
07a51b |
# tc -s filter show dev eth0 parent ffff:
|
|
|
07a51b |
|
|
|
07a51b |
filter protocol ip pref 49151 flower chain 0 handle 0x1
|
|
|
07a51b |
indev eth0
|
|
|
07a51b |
eth_type ipv4
|
|
|
07a51b |
ip_proto udp
|
|
|
07a51b |
not_in_hw
|
|
|
07a51b |
action order 1: tunnel_key set
|
|
|
07a51b |
src_ip 10.0.99.192
|
|
|
07a51b |
dst_ip 10.0.99.193
|
|
|
07a51b |
key_id 11
|
|
|
07a51b |
dst_port 6081
|
|
|
07a51b |
erspan_opts 1:2:0:0
|
|
|
07a51b |
csum pipe
|
|
|
07a51b |
index 2 ref 1 bind 1
|
|
|
07a51b |
...
|
|
|
07a51b |
v1->v2:
|
|
|
07a51b |
- no change.
|
|
|
07a51b |
v2->v3:
|
|
|
07a51b |
- no change.
|
|
|
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 |
man/man8/tc-tunnel_key.8 | 12 +++-
|
|
|
07a51b |
tc/m_tunnel_key.c | 117 ++++++++++++++++++++++++++++++++++++++-
|
|
|
07a51b |
2 files changed, 127 insertions(+), 2 deletions(-)
|
|
|
07a51b |
|
|
|
07a51b |
diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8
|
|
|
07a51b |
index c208e2c82a181..ad9972402c0e5 100644
|
|
|
07a51b |
--- a/man/man8/tc-tunnel_key.8
|
|
|
07a51b |
+++ b/man/man8/tc-tunnel_key.8
|
|
|
07a51b |
@@ -68,8 +68,10 @@ options.
|
|
|
07a51b |
.B dst_port
|
|
|
07a51b |
,
|
|
|
07a51b |
.B geneve_opts
|
|
|
07a51b |
-and
|
|
|
07a51b |
+,
|
|
|
07a51b |
.B vxlan_opts
|
|
|
07a51b |
+and
|
|
|
07a51b |
+.B erspan_opts
|
|
|
07a51b |
are optional.
|
|
|
07a51b |
.RS
|
|
|
07a51b |
.TP
|
|
|
07a51b |
@@ -99,6 +101,14 @@ Vxlan metatdata options.
|
|
|
07a51b |
is specified in the form GBP, as a 32bit number. Multiple options is not
|
|
|
07a51b |
supported.
|
|
|
07a51b |
.TP
|
|
|
07a51b |
+.B erspan_opts
|
|
|
07a51b |
+Erspan metatdata options.
|
|
|
07a51b |
+.B erspan_opts
|
|
|
07a51b |
+is specified in the form VERSION:INDEX:DIR:HWID, where VERSION is represented
|
|
|
07a51b |
+as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit number.
|
|
|
07a51b |
+Multiple options is not supported. Note INDEX is used when VERSION is 1,
|
|
|
07a51b |
+and DIR and HWID are used when VERSION is 2.
|
|
|
07a51b |
+.TP
|
|
|
07a51b |
.B tos
|
|
|
07a51b |
Outer header TOS
|
|
|
07a51b |
.TP
|
|
|
07a51b |
diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c
|
|
|
07a51b |
index 76391d6c85fb2..a56fe24413fa0 100644
|
|
|
07a51b |
--- a/tc/m_tunnel_key.c
|
|
|
07a51b |
+++ b/tc/m_tunnel_key.c
|
|
|
07a51b |
@@ -29,7 +29,7 @@ static void explain(void)
|
|
|
07a51b |
"src_ip <IP> (mandatory)\n"
|
|
|
07a51b |
"dst_ip <IP> (mandatory)\n"
|
|
|
07a51b |
"dst_port <UDP_PORT>\n"
|
|
|
07a51b |
- "geneve_opts | vxlan_opts <OPTIONS>\n"
|
|
|
07a51b |
+ "geneve_opts | vxlan_opts | erspan_opts <OPTIONS>\n"
|
|
|
07a51b |
"csum | nocsum (default is \"csum\")\n");
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
@@ -97,6 +97,21 @@ static int tunnel_key_parse_be16(char *str, int base, int type,
|
|
|
07a51b |
return 0;
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
+static int tunnel_key_parse_be32(char *str, int base, int type,
|
|
|
07a51b |
+ struct nlmsghdr *n)
|
|
|
07a51b |
+{
|
|
|
07a51b |
+ __be32 value;
|
|
|
07a51b |
+ int ret;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ ret = get_be32(&value, str, base);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ return ret;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ addattr32(n, MAX_MSG, type, value);
|
|
|
07a51b |
+
|
|
|
07a51b |
+ return 0;
|
|
|
07a51b |
+}
|
|
|
07a51b |
+
|
|
|
07a51b |
static int tunnel_key_parse_u8(char *str, int base, int type,
|
|
|
07a51b |
struct nlmsghdr *n)
|
|
|
07a51b |
{
|
|
|
07a51b |
@@ -226,6 +241,63 @@ static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n)
|
|
|
07a51b |
return 0;
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
+static int tunnel_key_parse_erspan_opt(char *str, struct nlmsghdr *n)
|
|
|
07a51b |
+{
|
|
|
07a51b |
+ char *token, *saveptr = NULL;
|
|
|
07a51b |
+ struct rtattr *encap, *nest;
|
|
|
07a51b |
+ int i, ret;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ encap = addattr_nest(n, MAX_MSG,
|
|
|
07a51b |
+ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED);
|
|
|
07a51b |
+ nest = addattr_nest(n, MAX_MSG,
|
|
|
07a51b |
+ TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED);
|
|
|
07a51b |
+
|
|
|
07a51b |
+ token = strtok_r(str, ":", &saveptr);
|
|
|
07a51b |
+ i = 1;
|
|
|
07a51b |
+ while (token) {
|
|
|
07a51b |
+ switch (i) {
|
|
|
07a51b |
+ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ ret = tunnel_key_parse_u8(token, 0, i, n);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ return ret;
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ ret = tunnel_key_parse_be32(token, 0, i, n);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ return ret;
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ ret = tunnel_key_parse_u8(token, 0, i, n);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ return ret;
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID:
|
|
|
07a51b |
+ {
|
|
|
07a51b |
+ ret = tunnel_key_parse_u8(token, 0, i, n);
|
|
|
07a51b |
+ if (ret)
|
|
|
07a51b |
+ return ret;
|
|
|
07a51b |
+ break;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+ default:
|
|
|
07a51b |
+ return -1;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+
|
|
|
07a51b |
+ token = strtok_r(NULL, ":", &saveptr);
|
|
|
07a51b |
+ i++;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
+
|
|
|
07a51b |
+ addattr_nest_end(n, nest);
|
|
|
07a51b |
+ addattr_nest_end(n, encap);
|
|
|
07a51b |
+
|
|
|
07a51b |
+ return 0;
|
|
|
07a51b |
+}
|
|
|
07a51b |
+
|
|
|
07a51b |
static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n)
|
|
|
07a51b |
{
|
|
|
07a51b |
int ret;
|
|
|
07a51b |
@@ -330,6 +402,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
|
|
|
07a51b |
fprintf(stderr, "Illegal \"vxlan_opts\"\n");
|
|
|
07a51b |
return -1;
|
|
|
07a51b |
}
|
|
|
07a51b |
+ } else if (matches(*argv, "erspan_opts") == 0) {
|
|
|
07a51b |
+ NEXT_ARG();
|
|
|
07a51b |
+
|
|
|
07a51b |
+ if (tunnel_key_parse_erspan_opt(*argv, n)) {
|
|
|
07a51b |
+ fprintf(stderr, "Illegal \"erspan_opts\"\n");
|
|
|
07a51b |
+ return -1;
|
|
|
07a51b |
+ }
|
|
|
07a51b |
} else if (matches(*argv, "tos") == 0) {
|
|
|
07a51b |
NEXT_ARG();
|
|
|
07a51b |
ret = tunnel_key_parse_tos_ttl(*argv,
|
|
|
07a51b |
@@ -517,6 +596,39 @@ static void tunnel_key_print_vxlan_options(struct rtattr *attr)
|
|
|
07a51b |
close_json_array(PRINT_JSON, name);
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
+static void tunnel_key_print_erspan_options(struct rtattr *attr)
|
|
|
07a51b |
+{
|
|
|
07a51b |
+ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1];
|
|
|
07a51b |
+ struct rtattr *i = RTA_DATA(attr);
|
|
|
07a51b |
+ int rem = RTA_PAYLOAD(attr);
|
|
|
07a51b |
+ char *name = "erspan_opts";
|
|
|
07a51b |
+ __u8 ver, hwid, dir;
|
|
|
07a51b |
+ __u32 idx;
|
|
|
07a51b |
+
|
|
|
07a51b |
+ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, i, rem);
|
|
|
07a51b |
+ ver = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]);
|
|
|
07a51b |
+ if (ver == 1) {
|
|
|
07a51b |
+ idx = rta_getattr_be32(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]);
|
|
|
07a51b |
+ dir = 0;
|
|
|
07a51b |
+ hwid = 0;
|
|
|
07a51b |
+ } else {
|
|
|
07a51b |
+ idx = 0;
|
|
|
07a51b |
+ dir = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]);
|
|
|
07a51b |
+ hwid = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_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 tunnel_key_print_key_opt(struct rtattr *attr)
|
|
|
07a51b |
{
|
|
|
07a51b |
struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1];
|
|
|
07a51b |
@@ -531,6 +643,9 @@ static void tunnel_key_print_key_opt(struct rtattr *attr)
|
|
|
07a51b |
else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN])
|
|
|
07a51b |
tunnel_key_print_vxlan_options(
|
|
|
07a51b |
tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]);
|
|
|
07a51b |
+ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN])
|
|
|
07a51b |
+ tunnel_key_print_erspan_options(
|
|
|
07a51b |
+ tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]);
|
|
|
07a51b |
}
|
|
|
07a51b |
|
|
|
07a51b |
static void tunnel_key_print_tos_ttl(FILE *f, char *name,
|
|
|
07a51b |
--
|
|
|
07a51b |
2.26.2
|
|
|
07a51b |
|