]> git.ipfire.org Git - thirdparty/iproute2.git/blame - tc/m_tunnel_key.c
tc: make action_util arg const
[thirdparty/iproute2.git] / tc / m_tunnel_key.c
CommitLineData
b3a091d1 1/* SPDX-License-Identifier: GPL-2.0-or-later */
d57639a4
AV
2/*
3 * m_tunnel_key.c ip tunnel manipulation module
4 *
d57639a4
AV
5 * Authors: Amir Vadai <amir@vadai.me>
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <string.h>
12#include <linux/if_ether.h>
13#include "utils.h"
14#include "rt_names.h"
15#include "tc_util.h"
16#include <linux/tc_act/tc_tunnel_key.h>
17
18static void explain(void)
19{
50907a82 20 fprintf(stderr,
8589eb4e
MC
21 "Usage: tunnel_key unset\n"
22 " tunnel_key set <TUNNEL_KEY>\n"
50907a82 23 "Where TUNNEL_KEY is a combination of:\n"
dc0332b1 24 "id <TUNNELID>\n"
50907a82
JB
25 "src_ip <IP> (mandatory)\n"
26 "dst_ip <IP> (mandatory)\n"
59eb271d 27 "dst_port <UDP_PORT>\n"
668fd9b2 28 "geneve_opts | vxlan_opts | erspan_opts <OPTIONS>\n"
8208365d
DC
29 "csum | nocsum (default is \"csum\")\n"
30 "nofrag\n");
d57639a4
AV
31}
32
33static void usage(void)
34{
35 explain();
36 exit(-1);
37}
38
39static int tunnel_key_parse_ip_addr(const char *str, int addr4_type,
40 int addr6_type, struct nlmsghdr *n)
41{
42 inet_prefix addr;
43 int ret;
44
45 ret = get_addr(&addr, str, AF_UNSPEC);
46 if (ret)
47 return ret;
48
49 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
50 addr.data, addr.bytelen);
51
52 return 0;
53}
54
55static int tunnel_key_parse_key_id(const char *str, int type,
56 struct nlmsghdr *n)
57{
58 __be32 key_id;
59 int ret;
60
61 ret = get_be32(&key_id, str, 10);
62 if (!ret)
63 addattr32(n, MAX_MSG, type, key_id);
64
65 return ret;
66}
67
449c709c
HHZ
68static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n)
69{
70 int ret;
71 __be16 dst_port;
72
73 ret = get_be16(&dst_port, str, 10);
74 if (ret)
75 return -1;
76
77 addattr16(n, MAX_MSG, type, dst_port);
78
79 return 0;
80}
81
6217917a
SH
82static int tunnel_key_parse_be16(char *str, int base, int type,
83 struct nlmsghdr *n)
84{
85 int ret;
86 __be16 value;
87
88 ret = get_be16(&value, str, base);
89 if (ret)
90 return ret;
91
92 addattr16(n, MAX_MSG, type, value);
93
94 return 0;
95}
96
668fd9b2
XL
97static int tunnel_key_parse_be32(char *str, int base, int type,
98 struct nlmsghdr *n)
99{
100 __be32 value;
101 int ret;
102
103 ret = get_be32(&value, str, base);
104 if (ret)
105 return ret;
106
107 addattr32(n, MAX_MSG, type, value);
108
109 return 0;
110}
111
6217917a
SH
112static int tunnel_key_parse_u8(char *str, int base, int type,
113 struct nlmsghdr *n)
114{
115 int ret;
116 __u8 value;
117
118 ret = get_u8(&value, str, base);
119 if (ret)
120 return ret;
121
122 addattr8(n, MAX_MSG, type, value);
123
124 return 0;
125}
126
f72c3ad0
XL
127static int tunnel_key_parse_u32(char *str, int base, int type,
128 struct nlmsghdr *n)
129{
130 __u32 value;
131 int ret;
132
133 ret = get_u32(&value, str, base);
134 if (ret)
135 return ret;
136
137 addattr32(n, MAX_MSG, type, value);
138
139 return 0;
140}
141
6217917a
SH
142static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n)
143{
144 char *token, *saveptr = NULL;
145 struct rtattr *nest;
146 int i, ret;
147
148 nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
149
150 token = strtok_r(str, ":", &saveptr);
151 i = 1;
152 while (token) {
153 switch (i) {
154 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS:
155 {
156 ret = tunnel_key_parse_be16(token, 16, i, n);
157 if (ret)
158 return ret;
159 break;
160 }
161 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE:
162 {
163 ret = tunnel_key_parse_u8(token, 16, i, n);
164 if (ret)
165 return ret;
166 break;
167 }
168 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA:
169 {
170 size_t token_len = strlen(token);
171 uint8_t *opts;
172
173 opts = malloc(token_len / 2);
174 if (!opts)
175 return -1;
176 if (hex2mem(token, opts, token_len / 2) < 0) {
177 free(opts);
178 return -1;
179 }
180 addattr_l(n, MAX_MSG, i, opts, token_len / 2);
181 free(opts);
182
183 break;
184 }
185 default:
186 return -1;
187 }
188
189 token = strtok_r(NULL, ":", &saveptr);
190 i++;
191 }
192
193 addattr_nest_end(n, nest);
194
195 return 0;
196}
197
198static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n)
199{
200 char *token, *saveptr = NULL;
201 struct rtattr *nest;
202 int ret;
203
204 nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS);
205
206 token = strtok_r(str, ",", &saveptr);
207 while (token) {
208 ret = tunnel_key_parse_geneve_opt(token, n);
209 if (ret)
210 return ret;
211
212 token = strtok_r(NULL, ",", &saveptr);
213 }
214
215 addattr_nest_end(n, nest);
216
217 return 0;
218}
219
f72c3ad0
XL
220static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n)
221{
222 struct rtattr *encap, *nest;
223 int ret;
224
225 encap = addattr_nest(n, MAX_MSG,
226 TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED);
227 nest = addattr_nest(n, MAX_MSG,
228 TCA_TUNNEL_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED);
229
230 ret = tunnel_key_parse_u32(str, 0,
231 TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, n);
232 if (ret)
233 return ret;
234
235 addattr_nest_end(n, nest);
236 addattr_nest_end(n, encap);
237
238 return 0;
239}
240
668fd9b2
XL
241static int tunnel_key_parse_erspan_opt(char *str, struct nlmsghdr *n)
242{
243 char *token, *saveptr = NULL;
244 struct rtattr *encap, *nest;
245 int i, ret;
246
247 encap = addattr_nest(n, MAX_MSG,
248 TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED);
249 nest = addattr_nest(n, MAX_MSG,
250 TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED);
251
252 token = strtok_r(str, ":", &saveptr);
253 i = 1;
254 while (token) {
255 switch (i) {
256 case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER:
257 {
258 ret = tunnel_key_parse_u8(token, 0, i, n);
259 if (ret)
260 return ret;
261 break;
262 }
263 case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX:
264 {
265 ret = tunnel_key_parse_be32(token, 0, i, n);
266 if (ret)
267 return ret;
268 break;
269 }
270 case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR:
271 {
272 ret = tunnel_key_parse_u8(token, 0, i, n);
273 if (ret)
274 return ret;
275 break;
276 }
277 case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID:
278 {
279 ret = tunnel_key_parse_u8(token, 0, i, n);
280 if (ret)
281 return ret;
282 break;
283 }
284 default:
285 return -1;
286 }
287
288 token = strtok_r(NULL, ":", &saveptr);
289 i++;
290 }
291
292 addattr_nest_end(n, nest);
293 addattr_nest_end(n, encap);
294
295 return 0;
296}
297
9f89b0cc
OG
298static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n)
299{
300 int ret;
301 __u8 val;
302
303 ret = get_u8(&val, str, 10);
304 if (ret)
305 ret = get_u8(&val, str, 16);
306 if (ret)
307 return -1;
308
309 addattr8(n, MAX_MSG, type, val);
310
311 return 0;
312}
313
38b0e6c1 314static int parse_tunnel_key(const struct action_util *a, int *argc_p, char ***argv_p,
d57639a4
AV
315 int tca_id, struct nlmsghdr *n)
316{
e67aba55 317 struct tc_tunnel_key parm = {};
d57639a4
AV
318 char **argv = *argv_p;
319 int argc = *argc_p;
320 struct rtattr *tail;
321 int action = 0;
322 int ret;
323 int has_src_ip = 0;
324 int has_dst_ip = 0;
8208365d 325 int csum = 1, nofrag = 0;
d57639a4
AV
326
327 if (matches(*argv, "tunnel_key") != 0)
328 return -1;
329
c14f9d92 330 tail = addattr_nest(n, MAX_MSG, tca_id);
d57639a4
AV
331
332 NEXT_ARG();
333
334 while (argc > 0) {
335 if (matches(*argv, "unset") == 0) {
336 if (action) {
337 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
338 *argv);
339 explain();
340 return -1;
341 }
342 action = TCA_TUNNEL_KEY_ACT_RELEASE;
343 } else if (matches(*argv, "set") == 0) {
344 if (action) {
345 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
346 *argv);
347 explain();
348 return -1;
349 }
350 action = TCA_TUNNEL_KEY_ACT_SET;
351 } else if (matches(*argv, "src_ip") == 0) {
352 NEXT_ARG();
353 ret = tunnel_key_parse_ip_addr(*argv,
354 TCA_TUNNEL_KEY_ENC_IPV4_SRC,
355 TCA_TUNNEL_KEY_ENC_IPV6_SRC,
356 n);
357 if (ret < 0) {
358 fprintf(stderr, "Illegal \"src_ip\"\n");
359 return -1;
360 }
361 has_src_ip = 1;
362 } else if (matches(*argv, "dst_ip") == 0) {
363 NEXT_ARG();
364 ret = tunnel_key_parse_ip_addr(*argv,
365 TCA_TUNNEL_KEY_ENC_IPV4_DST,
366 TCA_TUNNEL_KEY_ENC_IPV6_DST,
367 n);
368 if (ret < 0) {
369 fprintf(stderr, "Illegal \"dst_ip\"\n");
370 return -1;
371 }
372 has_dst_ip = 1;
373 } else if (matches(*argv, "id") == 0) {
374 NEXT_ARG();
375 ret = tunnel_key_parse_key_id(*argv, TCA_TUNNEL_KEY_ENC_KEY_ID, n);
376 if (ret < 0) {
377 fprintf(stderr, "Illegal \"id\"\n");
378 return -1;
379 }
449c709c
HHZ
380 } else if (matches(*argv, "dst_port") == 0) {
381 NEXT_ARG();
382 ret = tunnel_key_parse_dst_port(*argv,
383 TCA_TUNNEL_KEY_ENC_DST_PORT, n);
384 if (ret < 0) {
385 fprintf(stderr, "Illegal \"dst port\"\n");
386 return -1;
387 }
6217917a
SH
388 } else if (matches(*argv, "geneve_opts") == 0) {
389 NEXT_ARG();
390
391 if (tunnel_key_parse_geneve_opts(*argv, n)) {
392 fprintf(stderr, "Illegal \"geneve_opts\"\n");
393 return -1;
394 }
f72c3ad0
XL
395 } else if (matches(*argv, "vxlan_opts") == 0) {
396 NEXT_ARG();
397
398 if (tunnel_key_parse_vxlan_opt(*argv, n)) {
399 fprintf(stderr, "Illegal \"vxlan_opts\"\n");
400 return -1;
401 }
668fd9b2
XL
402 } else if (matches(*argv, "erspan_opts") == 0) {
403 NEXT_ARG();
404
405 if (tunnel_key_parse_erspan_opt(*argv, n)) {
406 fprintf(stderr, "Illegal \"erspan_opts\"\n");
407 return -1;
408 }
9f89b0cc
OG
409 } else if (matches(*argv, "tos") == 0) {
410 NEXT_ARG();
411 ret = tunnel_key_parse_tos_ttl(*argv,
412 TCA_TUNNEL_KEY_ENC_TOS, n);
413 if (ret < 0) {
414 fprintf(stderr, "Illegal \"tos\"\n");
415 return -1;
416 }
417 } else if (matches(*argv, "ttl") == 0) {
418 NEXT_ARG();
419 ret = tunnel_key_parse_tos_ttl(*argv,
420 TCA_TUNNEL_KEY_ENC_TTL, n);
421 if (ret < 0) {
422 fprintf(stderr, "Illegal \"ttl\"\n");
423 return -1;
424 }
59eb271d
JB
425 } else if (matches(*argv, "csum") == 0) {
426 csum = 1;
427 } else if (matches(*argv, "nocsum") == 0) {
428 csum = 0;
8208365d
DC
429 } else if (strcmp(*argv, "nofrag") == 0) {
430 nofrag = 1;
d57639a4
AV
431 } else if (matches(*argv, "help") == 0) {
432 usage();
433 } else {
434 break;
435 }
436 NEXT_ARG_FWD();
437 }
438
59eb271d
JB
439 addattr8(n, MAX_MSG, TCA_TUNNEL_KEY_NO_CSUM, !csum);
440
8208365d
DC
441 if (nofrag)
442 addattr(n, MAX_MSG, TCA_TUNNEL_KEY_NO_FRAG);
443
e67aba55
JP
444 parse_action_control_dflt(&argc, &argv, &parm.action,
445 false, TC_ACT_PIPE);
d57639a4
AV
446
447 if (argc) {
448 if (matches(*argv, "index") == 0) {
449 NEXT_ARG();
450 if (get_u32(&parm.index, *argv, 10)) {
451 fprintf(stderr, "tunnel_key: Illegal \"index\"\n");
452 return -1;
453 }
454
455 NEXT_ARG_FWD();
456 }
457 }
458
459 if (action == TCA_TUNNEL_KEY_ACT_SET &&
dc0332b1 460 (!has_src_ip || !has_dst_ip)) {
d57639a4
AV
461 fprintf(stderr, "set needs tunnel_key parameters\n");
462 explain();
463 return -1;
464 }
465
466 parm.t_action = action;
467 addattr_l(n, MAX_MSG, TCA_TUNNEL_KEY_PARMS, &parm, sizeof(parm));
c14f9d92 468 addattr_nest_end(n, tail);
d57639a4
AV
469
470 *argc_p = argc;
471 *argv_p = argv;
472
473 return 0;
474}
475
476static void tunnel_key_print_ip_addr(FILE *f, const char *name,
477 struct rtattr *attr)
478{
479 int family;
480 size_t len;
481
482 if (!attr)
483 return;
484
485 len = RTA_PAYLOAD(attr);
486
487 if (len == 4)
488 family = AF_INET;
489 else if (len == 16)
490 family = AF_INET6;
491 else
492 return;
493
0501fe73 494 print_nl();
8feb516b
RM
495 if (matches(name, "src_ip") == 0)
496 print_string(PRINT_ANY, "src_ip", "\tsrc_ip %s",
497 rt_addr_n2a_rta(family, attr));
498 else if (matches(name, "dst_ip") == 0)
499 print_string(PRINT_ANY, "dst_ip", "\tdst_ip %s",
500 rt_addr_n2a_rta(family, attr));
d57639a4
AV
501}
502
503static void tunnel_key_print_key_id(FILE *f, const char *name,
504 struct rtattr *attr)
505{
506 if (!attr)
507 return;
0501fe73 508 print_nl();
8feb516b 509 print_uint(PRINT_ANY, "key_id", "\tkey_id %u", rta_getattr_be32(attr));
d57639a4
AV
510}
511
449c709c
HHZ
512static void tunnel_key_print_dst_port(FILE *f, char *name,
513 struct rtattr *attr)
514{
515 if (!attr)
516 return;
0501fe73 517 print_nl();
8feb516b
RM
518 print_uint(PRINT_ANY, "dst_port", "\tdst_port %u",
519 rta_getattr_be16(attr));
449c709c
HHZ
520}
521
8208365d
DC
522static const struct {
523 const char *name;
524 unsigned int nl_flag;
525} tunnel_key_flag_names[] = {
526 { "", TCA_TUNNEL_KEY_NO_CSUM }, /* special handling, not bool */
527 { "nofrag", TCA_TUNNEL_KEY_NO_FRAG },
528};
529
530static void tunnel_key_print_flags(struct rtattr *tb[])
59eb271d 531{
8208365d
DC
532 unsigned int i, nl_flag;
533
0501fe73 534 print_nl();
8208365d
DC
535 for (i = 0; i < ARRAY_SIZE(tunnel_key_flag_names); i++) {
536 nl_flag = tunnel_key_flag_names[i].nl_flag;
537 if (nl_flag == TCA_TUNNEL_KEY_NO_CSUM) {
538 /* special handling to preserve csum/nocsum design */
539 if (!tb[nl_flag])
540 continue;
541 print_string(PRINT_ANY, "flag", "\t%s",
542 rta_getattr_u8(tb[nl_flag]) ?
543 "nocsum" : "csum" );
544 } else {
545 if (tb[nl_flag])
546 print_string(PRINT_FP, NULL, "\t%s",
547 tunnel_key_flag_names[i].name);
548 print_bool(PRINT_JSON, tunnel_key_flag_names[i].name,
549 NULL, !!tb[nl_flag]);
550 }
551 }
59eb271d
JB
552}
553
f72c3ad0 554static void tunnel_key_print_geneve_options(struct rtattr *attr)
6217917a
SH
555{
556 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
557 struct rtattr *i = RTA_DATA(attr);
558 int ii, data_len = 0, offset = 0;
559 int rem = RTA_PAYLOAD(attr);
f72c3ad0 560 char *name = "geneve_opts";
6217917a
SH
561 char strbuf[rem * 2 + 1];
562 char data[rem * 2 + 1];
563 uint8_t data_r[rem];
564 uint16_t clss;
565 uint8_t type;
566
567 open_json_array(PRINT_JSON, name);
7b0d424a 568 print_nl();
f72c3ad0 569 print_string(PRINT_FP, name, "\t%s ", name);
6217917a
SH
570
571 while (rem) {
572 parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem);
573 clss = rta_getattr_be16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]);
574 type = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]);
575 data_len = RTA_PAYLOAD(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
576 hexstring_n2a(RTA_DATA(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]),
577 data_len, data, sizeof(data));
578 hex2mem(data, data_r, data_len);
579 offset += data_len + 20;
580 rem -= data_len + 20;
581 i = RTA_DATA(attr) + offset;
582
583 open_json_object(NULL);
584 print_uint(PRINT_JSON, "class", NULL, clss);
585 print_uint(PRINT_JSON, "type", NULL, type);
586 open_json_array(PRINT_JSON, "data");
587 for (ii = 0; ii < data_len; ii++)
588 print_uint(PRINT_JSON, NULL, NULL, data_r[ii]);
589 close_json_array(PRINT_JSON, "data");
590 close_json_object();
591
592 sprintf(strbuf, "%04x:%02x:%s", clss, type, data);
593 if (rem)
594 print_string(PRINT_FP, NULL, "%s,", strbuf);
595 else
596 print_string(PRINT_FP, NULL, "%s", strbuf);
597 }
598
599 close_json_array(PRINT_JSON, name);
600}
601
f72c3ad0
XL
602static void tunnel_key_print_vxlan_options(struct rtattr *attr)
603{
604 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1];
605 struct rtattr *i = RTA_DATA(attr);
606 int rem = RTA_PAYLOAD(attr);
607 char *name = "vxlan_opts";
608 __u32 gbp;
609
610 parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, i, rem);
611 gbp = rta_getattr_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]);
612
613 print_nl();
614 print_string(PRINT_FP, name, "\t%s ", name);
615 open_json_array(PRINT_JSON, name);
616 open_json_object(NULL);
617 print_uint(PRINT_ANY, "gbp", "%u", gbp);
618 close_json_object();
619 close_json_array(PRINT_JSON, name);
620}
621
668fd9b2
XL
622static void tunnel_key_print_erspan_options(struct rtattr *attr)
623{
624 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1];
625 struct rtattr *i = RTA_DATA(attr);
626 int rem = RTA_PAYLOAD(attr);
627 char *name = "erspan_opts";
628 __u8 ver, hwid, dir;
629 __u32 idx;
630
631 parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, i, rem);
632 ver = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]);
633 if (ver == 1) {
634 idx = rta_getattr_be32(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]);
635 dir = 0;
636 hwid = 0;
637 } else {
638 idx = 0;
639 dir = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]);
640 hwid = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]);
641 }
642
643 print_nl();
644 print_string(PRINT_FP, name, "\t%s ", name);
645 open_json_array(PRINT_JSON, name);
646 open_json_object(NULL);
647 print_uint(PRINT_ANY, "ver", "%u", ver);
648 print_uint(PRINT_ANY, "index", ":%u", idx);
649 print_uint(PRINT_ANY, "dir", ":%u", dir);
650 print_uint(PRINT_ANY, "hwid", ":%u", hwid);
651 close_json_object();
652 close_json_array(PRINT_JSON, name);
653}
654
f72c3ad0 655static void tunnel_key_print_key_opt(struct rtattr *attr)
6217917a
SH
656{
657 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1];
658
659 if (!attr)
660 return;
661
662 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr);
f72c3ad0
XL
663 if (tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE])
664 tunnel_key_print_geneve_options(
665 tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]);
666 else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN])
667 tunnel_key_print_vxlan_options(
668 tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]);
668fd9b2
XL
669 else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN])
670 tunnel_key_print_erspan_options(
671 tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]);
6217917a
SH
672}
673
9f89b0cc
OG
674static void tunnel_key_print_tos_ttl(FILE *f, char *name,
675 struct rtattr *attr)
676{
677 if (!attr)
678 return;
679
680 if (matches(name, "tos") == 0 && rta_getattr_u8(attr) != 0) {
0501fe73 681 print_nl();
9f89b0cc
OG
682 print_uint(PRINT_ANY, "tos", "\ttos 0x%x",
683 rta_getattr_u8(attr));
684 } else if (matches(name, "ttl") == 0 && rta_getattr_u8(attr) != 0) {
0501fe73 685 print_nl();
9f89b0cc
OG
686 print_uint(PRINT_ANY, "ttl", "\tttl %u",
687 rta_getattr_u8(attr));
688 }
689}
690
38b0e6c1 691static int print_tunnel_key(const struct action_util *au, FILE *f, struct rtattr *arg)
d57639a4
AV
692{
693 struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
694 struct tc_tunnel_key *parm;
695
a99ebeee 696 print_string(PRINT_ANY, "kind", "%s ", "tunnel_key");
d57639a4 697 if (!arg)
a99ebeee 698 return 0;
d57639a4
AV
699
700 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_MAX, arg);
701
702 if (!tb[TCA_TUNNEL_KEY_PARMS]) {
d5ddb441 703 fprintf(stderr, "Missing tunnel_key parameters\n");
d57639a4
AV
704 return -1;
705 }
706 parm = RTA_DATA(tb[TCA_TUNNEL_KEY_PARMS]);
707
d57639a4
AV
708 switch (parm->t_action) {
709 case TCA_TUNNEL_KEY_ACT_RELEASE:
8feb516b 710 print_string(PRINT_ANY, "mode", " %s", "unset");
d57639a4
AV
711 break;
712 case TCA_TUNNEL_KEY_ACT_SET:
8feb516b 713 print_string(PRINT_ANY, "mode", " %s", "set");
d57639a4
AV
714 tunnel_key_print_ip_addr(f, "src_ip",
715 tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC]);
716 tunnel_key_print_ip_addr(f, "dst_ip",
717 tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
718 tunnel_key_print_ip_addr(f, "src_ip",
719 tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC]);
720 tunnel_key_print_ip_addr(f, "dst_ip",
721 tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
722 tunnel_key_print_key_id(f, "key_id",
723 tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
449c709c
HHZ
724 tunnel_key_print_dst_port(f, "dst_port",
725 tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
f72c3ad0 726 tunnel_key_print_key_opt(tb[TCA_TUNNEL_KEY_ENC_OPTS]);
8208365d 727 tunnel_key_print_flags(tb);
9f89b0cc
OG
728 tunnel_key_print_tos_ttl(f, "tos",
729 tb[TCA_TUNNEL_KEY_ENC_TOS]);
730 tunnel_key_print_tos_ttl(f, "ttl",
731 tb[TCA_TUNNEL_KEY_ENC_TTL]);
d57639a4
AV
732 break;
733 }
e67aba55 734 print_action_control(f, " ", parm->action, "");
d57639a4 735
0501fe73 736 print_nl();
8feb516b
RM
737 print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
738 print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
739 print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
d57639a4
AV
740
741 if (show_stats) {
742 if (tb[TCA_TUNNEL_KEY_TM]) {
743 struct tcf_t *tm = RTA_DATA(tb[TCA_TUNNEL_KEY_TM]);
744
745 print_tm(f, tm);
746 }
747 }
748
0501fe73 749 print_nl();
d57639a4
AV
750
751 return 0;
752}
753
754struct action_util tunnel_key_action_util = {
755 .id = "tunnel_key",
756 .parse_aopt = parse_tunnel_key,
757 .print_aopt = print_tunnel_key,
758};