From 3075a9ccaf6071c6b88323b66146c15e7254f1f7 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 09 2020 17:24:00 +0000 Subject: Apply patch 0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch patch_name: 0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch present_in_specfile: true location_in_specfile: 28 --- diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 index c208e2c..ad99724 100644 --- a/man/man8/tc-tunnel_key.8 +++ b/man/man8/tc-tunnel_key.8 @@ -68,8 +68,10 @@ options. .B dst_port , .B geneve_opts -and +, .B vxlan_opts +and +.B erspan_opts are optional. .RS .TP @@ -99,6 +101,14 @@ Vxlan metatdata options. is specified in the form GBP, as a 32bit number. Multiple options is not supported. .TP +.B erspan_opts +Erspan metatdata options. +.B erspan_opts +is specified in the form VERSION:INDEX:DIR:HWID, where VERSION is represented +as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit number. +Multiple options is not supported. Note INDEX is used when VERSION is 1, +and DIR and HWID are used when VERSION is 2. +.TP .B tos Outer header TOS .TP diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c index 76391d6..a56fe24 100644 --- a/tc/m_tunnel_key.c +++ b/tc/m_tunnel_key.c @@ -29,7 +29,7 @@ static void explain(void) "src_ip (mandatory)\n" "dst_ip (mandatory)\n" "dst_port \n" - "geneve_opts | vxlan_opts \n" + "geneve_opts | vxlan_opts | erspan_opts \n" "csum | nocsum (default is \"csum\")\n"); } @@ -97,6 +97,21 @@ static int tunnel_key_parse_be16(char *str, int base, int type, return 0; } +static int tunnel_key_parse_be32(char *str, int base, int type, + struct nlmsghdr *n) +{ + __be32 value; + int ret; + + ret = get_be32(&value, str, base); + if (ret) + return ret; + + addattr32(n, MAX_MSG, type, value); + + return 0; +} + static int tunnel_key_parse_u8(char *str, int base, int type, struct nlmsghdr *n) { @@ -226,6 +241,63 @@ static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n) return 0; } +static int tunnel_key_parse_erspan_opt(char *str, struct nlmsghdr *n) +{ + char *token, *saveptr = NULL; + struct rtattr *encap, *nest; + int i, ret; + + encap = addattr_nest(n, MAX_MSG, + TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED); + nest = addattr_nest(n, MAX_MSG, + TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED); + + token = strtok_r(str, ":", &saveptr); + i = 1; + while (token) { + switch (i) { + case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER: + { + ret = tunnel_key_parse_u8(token, 0, i, n); + if (ret) + return ret; + break; + } + case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX: + { + ret = tunnel_key_parse_be32(token, 0, i, n); + if (ret) + return ret; + break; + } + case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR: + { + ret = tunnel_key_parse_u8(token, 0, i, n); + if (ret) + return ret; + break; + } + case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID: + { + ret = tunnel_key_parse_u8(token, 0, i, n); + if (ret) + return ret; + break; + } + default: + return -1; + } + + token = strtok_r(NULL, ":", &saveptr); + i++; + } + + addattr_nest_end(n, nest); + addattr_nest_end(n, encap); + + return 0; +} + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) { int ret; @@ -330,6 +402,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, fprintf(stderr, "Illegal \"vxlan_opts\"\n"); return -1; } + } else if (matches(*argv, "erspan_opts") == 0) { + NEXT_ARG(); + + if (tunnel_key_parse_erspan_opt(*argv, n)) { + fprintf(stderr, "Illegal \"erspan_opts\"\n"); + return -1; + } } else if (matches(*argv, "tos") == 0) { NEXT_ARG(); ret = tunnel_key_parse_tos_ttl(*argv, @@ -517,6 +596,39 @@ static void tunnel_key_print_vxlan_options(struct rtattr *attr) close_json_array(PRINT_JSON, name); } +static void tunnel_key_print_erspan_options(struct rtattr *attr) +{ + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1]; + struct rtattr *i = RTA_DATA(attr); + int rem = RTA_PAYLOAD(attr); + char *name = "erspan_opts"; + __u8 ver, hwid, dir; + __u32 idx; + + parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, i, rem); + ver = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]); + if (ver == 1) { + idx = rta_getattr_be32(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]); + dir = 0; + hwid = 0; + } else { + idx = 0; + dir = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]); + hwid = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]); + } + + print_nl(); + print_string(PRINT_FP, name, "\t%s ", name); + open_json_array(PRINT_JSON, name); + open_json_object(NULL); + print_uint(PRINT_ANY, "ver", "%u", ver); + print_uint(PRINT_ANY, "index", ":%u", idx); + print_uint(PRINT_ANY, "dir", ":%u", dir); + print_uint(PRINT_ANY, "hwid", ":%u", hwid); + close_json_object(); + close_json_array(PRINT_JSON, name); +} + static void tunnel_key_print_key_opt(struct rtattr *attr) { struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; @@ -531,6 +643,9 @@ static void tunnel_key_print_key_opt(struct rtattr *attr) else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]) tunnel_key_print_vxlan_options( tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]); + else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]) + tunnel_key_print_erspan_options( + tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]); } static void tunnel_key_print_tos_ttl(FILE *f, char *name,