|
|
0ac2f3 |
From f970b592af7421ce932a788a6a14161c351d75e0 Mon Sep 17 00:00:00 2001
|
|
|
0ac2f3 |
From: Andrea Claudi <aclaudi@redhat.com>
|
|
|
0ac2f3 |
Date: Thu, 4 Jun 2020 21:43:01 +0200
|
|
|
0ac2f3 |
Subject: [PATCH] tc: m_tunnel_key: add options support for vxlan
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485
|
|
|
0ac2f3 |
Upstream Status: unknown commit f72c3ad00f3b7
|
|
|
0ac2f3 |
Conflicts: context change due to missing commit 7b0d424abef16
|
|
|
0ac2f3 |
("tc: do not output newline in oneline mode")
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
commit f72c3ad00f3b7869e90840d0098a83cb88224892
|
|
|
0ac2f3 |
Author: Xin Long <lucien.xin@gmail.com>
|
|
|
0ac2f3 |
Date: Mon Apr 27 18:27:48 2020 +0800
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
tc: m_tunnel_key: add options support for vxlan
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_VXLAN's parse and
|
|
|
0ac2f3 |
print to implement vxlan options support in m_tunnel_key, like
|
|
|
0ac2f3 |
Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support
|
|
|
0ac2f3 |
to act_tunnel_key") for geneve options support.
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
Option is expressed a 32bit number for gbp only, and vxlan
|
|
|
0ac2f3 |
doesn't support multiple options.
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
With this patch, users can add and dump vxlan options like:
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
# ip link add name vxlan1 type vxlan dstport 0 external
|
|
|
0ac2f3 |
# tc qdisc add dev eth0 ingress
|
|
|
0ac2f3 |
# tc filter add dev eth0 protocol ip parent ffff: \
|
|
|
0ac2f3 |
flower indev eth0 \
|
|
|
0ac2f3 |
ip_proto udp \
|
|
|
0ac2f3 |
action tunnel_key \
|
|
|
0ac2f3 |
set src_ip 10.0.99.192 \
|
|
|
0ac2f3 |
dst_ip 10.0.99.193 \
|
|
|
0ac2f3 |
dst_port 6081 \
|
|
|
0ac2f3 |
id 11 \
|
|
|
0ac2f3 |
vxlan_opts 65793 \
|
|
|
0ac2f3 |
action mirred egress redirect dev vxlan1
|
|
|
0ac2f3 |
# tc -s filter show dev eth0 parent ffff:
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
filter protocol ip pref 49152 flower chain 0 handle 0x1
|
|
|
0ac2f3 |
indev eth0
|
|
|
0ac2f3 |
eth_type ipv4
|
|
|
0ac2f3 |
ip_proto udp
|
|
|
0ac2f3 |
not_in_hw
|
|
|
0ac2f3 |
action order 1: tunnel_key set
|
|
|
0ac2f3 |
src_ip 10.0.99.192
|
|
|
0ac2f3 |
dst_ip 10.0.99.193
|
|
|
0ac2f3 |
key_id 11
|
|
|
0ac2f3 |
dst_port 6081
|
|
|
0ac2f3 |
vxlan_opts 65793
|
|
|
0ac2f3 |
...
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
v1->v2:
|
|
|
0ac2f3 |
- get_u32 with base = 0 for gbp.
|
|
|
0ac2f3 |
- use to print_unint("0x%x") to print gbp.
|
|
|
0ac2f3 |
v2->v3:
|
|
|
0ac2f3 |
- implement proper JSON array for opts.
|
|
|
0ac2f3 |
v3->v4:
|
|
|
0ac2f3 |
- keep the same format between input and output, json and non json.
|
|
|
0ac2f3 |
- print gbp as uint.
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
Signed-off-by: Xin Long <lucien.xin@gmail.com>
|
|
|
0ac2f3 |
Signed-off-by: David Ahern <dsahern@gmail.com>
|
|
|
0ac2f3 |
---
|
|
|
0ac2f3 |
man/man8/tc-tunnel_key.8 | 10 ++++-
|
|
|
0ac2f3 |
tc/m_tunnel_key.c | 85 +++++++++++++++++++++++++++++++++++-----
|
|
|
0ac2f3 |
2 files changed, 85 insertions(+), 10 deletions(-)
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8
|
|
|
0ac2f3 |
index 2145eb62e70e2..c208e2c82a181 100644
|
|
|
0ac2f3 |
--- a/man/man8/tc-tunnel_key.8
|
|
|
0ac2f3 |
+++ b/man/man8/tc-tunnel_key.8
|
|
|
0ac2f3 |
@@ -66,8 +66,10 @@ options.
|
|
|
0ac2f3 |
.B id
|
|
|
0ac2f3 |
,
|
|
|
0ac2f3 |
.B dst_port
|
|
|
0ac2f3 |
-and
|
|
|
0ac2f3 |
+,
|
|
|
0ac2f3 |
.B geneve_opts
|
|
|
0ac2f3 |
+and
|
|
|
0ac2f3 |
+.B vxlan_opts
|
|
|
0ac2f3 |
are optional.
|
|
|
0ac2f3 |
.RS
|
|
|
0ac2f3 |
.TP
|
|
|
0ac2f3 |
@@ -91,6 +93,12 @@ is specified in the form CLASS:TYPE:DATA, where CLASS is represented as a
|
|
|
0ac2f3 |
variable length hexadecimal value. Additionally multiple options may be
|
|
|
0ac2f3 |
listed using a comma delimiter.
|
|
|
0ac2f3 |
.TP
|
|
|
0ac2f3 |
+.B vxlan_opts
|
|
|
0ac2f3 |
+Vxlan metatdata options.
|
|
|
0ac2f3 |
+.B vxlan_opts
|
|
|
0ac2f3 |
+is specified in the form GBP, as a 32bit number. Multiple options is not
|
|
|
0ac2f3 |
+supported.
|
|
|
0ac2f3 |
+.TP
|
|
|
0ac2f3 |
.B tos
|
|
|
0ac2f3 |
Outer header TOS
|
|
|
0ac2f3 |
.TP
|
|
|
0ac2f3 |
diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c
|
|
|
0ac2f3 |
index 4e65e444776a2..76391d6c85fb2 100644
|
|
|
0ac2f3 |
--- a/tc/m_tunnel_key.c
|
|
|
0ac2f3 |
+++ b/tc/m_tunnel_key.c
|
|
|
0ac2f3 |
@@ -29,7 +29,7 @@ static void explain(void)
|
|
|
0ac2f3 |
"src_ip <IP> (mandatory)\n"
|
|
|
0ac2f3 |
"dst_ip <IP> (mandatory)\n"
|
|
|
0ac2f3 |
"dst_port <UDP_PORT>\n"
|
|
|
0ac2f3 |
- "geneve_opts <OPTIONS>\n"
|
|
|
0ac2f3 |
+ "geneve_opts | vxlan_opts <OPTIONS>\n"
|
|
|
0ac2f3 |
"csum | nocsum (default is \"csum\")\n");
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
@@ -112,6 +112,21 @@ static int tunnel_key_parse_u8(char *str, int base, int type,
|
|
|
0ac2f3 |
return 0;
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
+static int tunnel_key_parse_u32(char *str, int base, int type,
|
|
|
0ac2f3 |
+ struct nlmsghdr *n)
|
|
|
0ac2f3 |
+{
|
|
|
0ac2f3 |
+ __u32 value;
|
|
|
0ac2f3 |
+ int ret;
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ ret = get_u32(&value, str, base);
|
|
|
0ac2f3 |
+ if (ret)
|
|
|
0ac2f3 |
+ return ret;
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ addattr32(n, MAX_MSG, type, value);
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ return 0;
|
|
|
0ac2f3 |
+}
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n)
|
|
|
0ac2f3 |
{
|
|
|
0ac2f3 |
char *token, *saveptr = NULL;
|
|
|
0ac2f3 |
@@ -190,6 +205,27 @@ static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n)
|
|
|
0ac2f3 |
return 0;
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
+static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n)
|
|
|
0ac2f3 |
+{
|
|
|
0ac2f3 |
+ struct rtattr *encap, *nest;
|
|
|
0ac2f3 |
+ int ret;
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ encap = addattr_nest(n, MAX_MSG,
|
|
|
0ac2f3 |
+ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED);
|
|
|
0ac2f3 |
+ nest = addattr_nest(n, MAX_MSG,
|
|
|
0ac2f3 |
+ TCA_TUNNEL_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED);
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ ret = tunnel_key_parse_u32(str, 0,
|
|
|
0ac2f3 |
+ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, n);
|
|
|
0ac2f3 |
+ if (ret)
|
|
|
0ac2f3 |
+ return ret;
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ addattr_nest_end(n, nest);
|
|
|
0ac2f3 |
+ addattr_nest_end(n, encap);
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ return 0;
|
|
|
0ac2f3 |
+}
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n)
|
|
|
0ac2f3 |
{
|
|
|
0ac2f3 |
int ret;
|
|
|
0ac2f3 |
@@ -287,6 +323,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
|
|
|
0ac2f3 |
fprintf(stderr, "Illegal \"geneve_opts\"\n");
|
|
|
0ac2f3 |
return -1;
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
+ } else if (matches(*argv, "vxlan_opts") == 0) {
|
|
|
0ac2f3 |
+ NEXT_ARG();
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ if (tunnel_key_parse_vxlan_opt(*argv, n)) {
|
|
|
0ac2f3 |
+ fprintf(stderr, "Illegal \"vxlan_opts\"\n");
|
|
|
0ac2f3 |
+ return -1;
|
|
|
0ac2f3 |
+ }
|
|
|
0ac2f3 |
} else if (matches(*argv, "tos") == 0) {
|
|
|
0ac2f3 |
NEXT_ARG();
|
|
|
0ac2f3 |
ret = tunnel_key_parse_tos_ttl(*argv,
|
|
|
0ac2f3 |
@@ -406,13 +449,13 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on,
|
|
|
0ac2f3 |
rta_getattr_u8(attr) ? name_on : name_off);
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
-static void tunnel_key_print_geneve_options(const char *name,
|
|
|
0ac2f3 |
- struct rtattr *attr)
|
|
|
0ac2f3 |
+static void tunnel_key_print_geneve_options(struct rtattr *attr)
|
|
|
0ac2f3 |
{
|
|
|
0ac2f3 |
struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
|
|
|
0ac2f3 |
struct rtattr *i = RTA_DATA(attr);
|
|
|
0ac2f3 |
int ii, data_len = 0, offset = 0;
|
|
|
0ac2f3 |
int rem = RTA_PAYLOAD(attr);
|
|
|
0ac2f3 |
+ char *name = "geneve_opts";
|
|
|
0ac2f3 |
char strbuf[rem * 2 + 1];
|
|
|
0ac2f3 |
char data[rem * 2 + 1];
|
|
|
0ac2f3 |
uint8_t data_r[rem];
|
|
|
0ac2f3 |
@@ -420,7 +463,8 @@ static void tunnel_key_print_geneve_options(const char *name,
|
|
|
0ac2f3 |
uint8_t type;
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
open_json_array(PRINT_JSON, name);
|
|
|
0ac2f3 |
- print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt");
|
|
|
0ac2f3 |
+ print_nl();
|
|
|
0ac2f3 |
+ print_string(PRINT_FP, name, "\t%s ", name);
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
while (rem) {
|
|
|
0ac2f3 |
parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem);
|
|
|
0ac2f3 |
@@ -453,7 +497,27 @@ static void tunnel_key_print_geneve_options(const char *name,
|
|
|
0ac2f3 |
close_json_array(PRINT_JSON, name);
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
-static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr)
|
|
|
0ac2f3 |
+static void tunnel_key_print_vxlan_options(struct rtattr *attr)
|
|
|
0ac2f3 |
+{
|
|
|
0ac2f3 |
+ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1];
|
|
|
0ac2f3 |
+ struct rtattr *i = RTA_DATA(attr);
|
|
|
0ac2f3 |
+ int rem = RTA_PAYLOAD(attr);
|
|
|
0ac2f3 |
+ char *name = "vxlan_opts";
|
|
|
0ac2f3 |
+ __u32 gbp;
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, i, rem);
|
|
|
0ac2f3 |
+ gbp = rta_getattr_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]);
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+ print_nl();
|
|
|
0ac2f3 |
+ print_string(PRINT_FP, name, "\t%s ", name);
|
|
|
0ac2f3 |
+ open_json_array(PRINT_JSON, name);
|
|
|
0ac2f3 |
+ open_json_object(NULL);
|
|
|
0ac2f3 |
+ print_uint(PRINT_ANY, "gbp", "%u", gbp);
|
|
|
0ac2f3 |
+ close_json_object();
|
|
|
0ac2f3 |
+ close_json_array(PRINT_JSON, name);
|
|
|
0ac2f3 |
+}
|
|
|
0ac2f3 |
+
|
|
|
0ac2f3 |
+static void tunnel_key_print_key_opt(struct rtattr *attr)
|
|
|
0ac2f3 |
{
|
|
|
0ac2f3 |
struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1];
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
@@ -461,8 +525,12 @@ static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr)
|
|
|
0ac2f3 |
return;
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr);
|
|
|
0ac2f3 |
- tunnel_key_print_geneve_options(name,
|
|
|
0ac2f3 |
- tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]);
|
|
|
0ac2f3 |
+ if (tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE])
|
|
|
0ac2f3 |
+ tunnel_key_print_geneve_options(
|
|
|
0ac2f3 |
+ tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]);
|
|
|
0ac2f3 |
+ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN])
|
|
|
0ac2f3 |
+ tunnel_key_print_vxlan_options(
|
|
|
0ac2f3 |
+ tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]);
|
|
|
0ac2f3 |
}
|
|
|
0ac2f3 |
|
|
|
0ac2f3 |
static void tunnel_key_print_tos_ttl(FILE *f, char *name,
|
|
|
0ac2f3 |
@@ -518,8 +586,7 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
|
|
|
0ac2f3 |
tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
|
|
|
0ac2f3 |
tunnel_key_print_dst_port(f, "dst_port",
|
|
|
0ac2f3 |
tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
|
|
|
0ac2f3 |
- tunnel_key_print_key_opt("geneve_opts",
|
|
|
0ac2f3 |
- tb[TCA_TUNNEL_KEY_ENC_OPTS]);
|
|
|
0ac2f3 |
+ tunnel_key_print_key_opt(tb[TCA_TUNNEL_KEY_ENC_OPTS]);
|
|
|
0ac2f3 |
tunnel_key_print_flag(f, "nocsum", "csum",
|
|
|
0ac2f3 |
tb[TCA_TUNNEL_KEY_NO_CSUM]);
|
|
|
0ac2f3 |
tunnel_key_print_tos_ttl(f, "tos",
|
|
|
0ac2f3 |
--
|
|
|
0ac2f3 |
2.26.2
|
|
|
0ac2f3 |
|