]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - tc/m_tunnel_key.c
rdma: Properly mark RDMAtool license
[mirror_iproute2.git] / tc / m_tunnel_key.c
index 0fa461549ad90e195b007f51d9f56f671f10cc70..9449287ea0b4fd77efaad7f6b6e788204f952208 100644 (file)
@@ -25,10 +25,11 @@ static void explain(void)
        fprintf(stderr, "       tunnel_key set <TUNNEL_KEY>\n");
        fprintf(stderr,
                "Where TUNNEL_KEY is a combination of:\n"
-               "id <TUNNELID> (mandatory)\n"
+               "id <TUNNELID>\n"
                "src_ip <IP> (mandatory)\n"
                "dst_ip <IP> (mandatory)\n"
                "dst_port <UDP_PORT>\n"
+               "geneve_opts <OPTIONS>\n"
                "csum | nocsum (default is \"csum\")\n");
 }
 
@@ -81,6 +82,130 @@ static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n)
        return 0;
 }
 
+static int tunnel_key_parse_be16(char *str, int base, int type,
+                                struct nlmsghdr *n)
+{
+       int ret;
+       __be16 value;
+
+       ret = get_be16(&value, str, base);
+       if (ret)
+               return ret;
+
+       addattr16(n, MAX_MSG, type, value);
+
+       return 0;
+}
+
+static int tunnel_key_parse_u8(char *str, int base, int type,
+                              struct nlmsghdr *n)
+{
+       int ret;
+       __u8 value;
+
+       ret = get_u8(&value, str, base);
+       if (ret)
+               return ret;
+
+       addattr8(n, MAX_MSG, type, value);
+
+       return 0;
+}
+
+static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n)
+{
+       char *token, *saveptr = NULL;
+       struct rtattr *nest;
+       int i, ret;
+
+       nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
+
+       token = strtok_r(str, ":", &saveptr);
+       i = 1;
+       while (token) {
+               switch (i) {
+               case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS:
+               {
+                       ret = tunnel_key_parse_be16(token, 16, i, n);
+                       if (ret)
+                               return ret;
+                       break;
+               }
+               case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE:
+               {
+                       ret = tunnel_key_parse_u8(token, 16, i, n);
+                       if (ret)
+                               return ret;
+                       break;
+               }
+               case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA:
+               {
+                       size_t token_len = strlen(token);
+                       uint8_t *opts;
+
+                       opts = malloc(token_len / 2);
+                       if (!opts)
+                               return -1;
+                       if (hex2mem(token, opts, token_len / 2) < 0) {
+                               free(opts);
+                               return -1;
+                       }
+                       addattr_l(n, MAX_MSG, i, opts, token_len / 2);
+                       free(opts);
+
+                       break;
+               }
+               default:
+                       return -1;
+               }
+
+               token = strtok_r(NULL, ":", &saveptr);
+               i++;
+       }
+
+       addattr_nest_end(n, nest);
+
+       return 0;
+}
+
+static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n)
+{
+       char *token, *saveptr = NULL;
+       struct rtattr *nest;
+       int ret;
+
+       nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS);
+
+       token = strtok_r(str, ",", &saveptr);
+       while (token) {
+               ret = tunnel_key_parse_geneve_opt(token, n);
+               if (ret)
+                       return ret;
+
+               token = strtok_r(NULL, ",", &saveptr);
+       }
+
+       addattr_nest_end(n, nest);
+
+       return 0;
+}
+
+static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n)
+{
+       int ret;
+       __u8 val;
+
+       ret = get_u8(&val, str, 10);
+       if (ret)
+               ret = get_u8(&val, str, 16);
+       if (ret)
+               return -1;
+
+       addattr8(n, MAX_MSG, type, val);
+
+       return 0;
+}
+
 static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
                            int tca_id, struct nlmsghdr *n)
 {
@@ -92,7 +217,6 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
        int ret;
        int has_src_ip = 0;
        int has_dst_ip = 0;
-       int has_key_id = 0;
        int csum = 1;
 
        if (matches(*argv, "tunnel_key") != 0)
@@ -148,7 +272,6 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
                                fprintf(stderr, "Illegal \"id\"\n");
                                return -1;
                        }
-                       has_key_id = 1;
                } else if (matches(*argv, "dst_port") == 0) {
                        NEXT_ARG();
                        ret = tunnel_key_parse_dst_port(*argv,
@@ -157,6 +280,29 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
                                fprintf(stderr, "Illegal \"dst port\"\n");
                                return -1;
                        }
+               } else if (matches(*argv, "geneve_opts") == 0) {
+                       NEXT_ARG();
+
+                       if (tunnel_key_parse_geneve_opts(*argv, n)) {
+                               fprintf(stderr, "Illegal \"geneve_opts\"\n");
+                               return -1;
+                       }
+               } else if (matches(*argv, "tos") == 0) {
+                       NEXT_ARG();
+                       ret = tunnel_key_parse_tos_ttl(*argv,
+                                                       TCA_TUNNEL_KEY_ENC_TOS, n);
+                       if (ret < 0) {
+                               fprintf(stderr, "Illegal \"tos\"\n");
+                               return -1;
+                       }
+               } else if (matches(*argv, "ttl") == 0) {
+                       NEXT_ARG();
+                       ret = tunnel_key_parse_tos_ttl(*argv,
+                                                       TCA_TUNNEL_KEY_ENC_TTL, n);
+                       if (ret < 0) {
+                               fprintf(stderr, "Illegal \"ttl\"\n");
+                               return -1;
+                       }
                } else if (matches(*argv, "csum") == 0) {
                        csum = 1;
                } else if (matches(*argv, "nocsum") == 0) {
@@ -187,7 +333,7 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
        }
 
        if (action == TCA_TUNNEL_KEY_ACT_SET &&
-           (!has_src_ip || !has_dst_ip || !has_key_id)) {
+           (!has_src_ip || !has_dst_ip)) {
                fprintf(stderr, "set needs tunnel_key parameters\n");
                explain();
                return -1;
@@ -260,6 +406,82 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on,
                     rta_getattr_u8(attr) ? name_on : name_off);
 }
 
+static void tunnel_key_print_geneve_options(const char *name,
+                                           struct rtattr *attr)
+{
+       struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
+       struct rtattr *i = RTA_DATA(attr);
+       int ii, data_len = 0, offset = 0;
+       int rem = RTA_PAYLOAD(attr);
+       char strbuf[rem * 2 + 1];
+       char data[rem * 2 + 1];
+       uint8_t data_r[rem];
+       uint16_t clss;
+       uint8_t type;
+
+       open_json_array(PRINT_JSON, name);
+       print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt");
+
+       while (rem) {
+               parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem);
+               clss = rta_getattr_be16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]);
+               type = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]);
+               data_len = RTA_PAYLOAD(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
+               hexstring_n2a(RTA_DATA(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]),
+                             data_len, data, sizeof(data));
+               hex2mem(data, data_r, data_len);
+               offset += data_len + 20;
+               rem -= data_len + 20;
+               i = RTA_DATA(attr) + offset;
+
+               open_json_object(NULL);
+               print_uint(PRINT_JSON, "class", NULL, clss);
+               print_uint(PRINT_JSON, "type", NULL, type);
+               open_json_array(PRINT_JSON, "data");
+               for (ii = 0; ii < data_len; ii++)
+                       print_uint(PRINT_JSON, NULL, NULL, data_r[ii]);
+               close_json_array(PRINT_JSON, "data");
+               close_json_object();
+
+               sprintf(strbuf, "%04x:%02x:%s", clss, type, data);
+               if (rem)
+                       print_string(PRINT_FP, NULL, "%s,", strbuf);
+               else
+                       print_string(PRINT_FP, NULL, "%s", strbuf);
+       }
+
+       close_json_array(PRINT_JSON, name);
+}
+
+static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr)
+{
+       struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1];
+
+       if (!attr)
+               return;
+
+       parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr);
+       tunnel_key_print_geneve_options(name,
+                                       tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]);
+}
+
+static void tunnel_key_print_tos_ttl(FILE *f, char *name,
+                                    struct rtattr *attr)
+{
+       if (!attr)
+               return;
+
+       if (matches(name, "tos") == 0 && rta_getattr_u8(attr) != 0) {
+               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_uint(PRINT_ANY, "tos", "\ttos 0x%x",
+                          rta_getattr_u8(attr));
+       } else if (matches(name, "ttl") == 0 && rta_getattr_u8(attr) != 0) {
+               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_uint(PRINT_ANY, "ttl", "\tttl %u",
+                          rta_getattr_u8(attr));
+       }
+}
+
 static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
 {
        struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
@@ -297,8 +519,14 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
                                        tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
                tunnel_key_print_dst_port(f, "dst_port",
                                          tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
+               tunnel_key_print_key_opt("geneve_opts",
+                                        tb[TCA_TUNNEL_KEY_ENC_OPTS]);
                tunnel_key_print_flag(f, "nocsum", "csum",
                                      tb[TCA_TUNNEL_KEY_NO_CSUM]);
+               tunnel_key_print_tos_ttl(f, "tos",
+                                         tb[TCA_TUNNEL_KEY_ENC_TOS]);
+               tunnel_key_print_tos_ttl(f, "ttl",
+                                         tb[TCA_TUNNEL_KEY_ENC_TTL]);
                break;
        }
        print_action_control(f, " ", parm->action, "");