]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/f_flower.c
f_flower: fix build with musl libc
[mirror_iproute2.git] / tc / f_flower.c
CommitLineData
30eb304e
JP
1/*
2 * f_flower.c Flower Classifier
3 *
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Jiri Pirko <jiri@resnulli.us>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
30eb304e
JP
15#include <string.h>
16#include <net/if.h>
28747146 17#include <linux/limits.h>
f888f4e2 18#include <linux/if_arp.h>
30eb304e
JP
19#include <linux/if_ether.h>
20#include <linux/ip.h>
745d9172 21#include <linux/tc_act/tc_vlan.h>
7638ee13 22#include <linux/mpls.h>
30eb304e
JP
23
24#include "utils.h"
25#include "tc_util.h"
26#include "rt_names.h"
27
08f66c80
PB
28enum flower_matching_flags {
29 FLOWER_IP_FLAGS,
30};
31
6910d656
SH
32enum flower_endpoint {
33 FLOWER_ENDPOINT_SRC,
34 FLOWER_ENDPOINT_DST
35};
36
eb3b5696
SH
37enum flower_icmp_field {
38 FLOWER_ICMP_FIELD_TYPE,
39 FLOWER_ICMP_FIELD_CODE
40};
41
30eb304e
JP
42static void explain(void)
43{
512caeb2 44 fprintf(stderr,
ac6a4c22 45 "Usage: ... flower [ MATCH-LIST ] [ verbose ]\n"
512caeb2
SH
46 " [ skip_sw | skip_hw ]\n"
47 " [ action ACTION-SPEC ] [ classid CLASSID ]\n"
48 "\n"
49 "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n"
50 " MATCH := { indev DEV-NAME |\n"
51 " vlan_id VID |\n"
52 " vlan_prio PRIORITY |\n"
53 " vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
1f0a5dfd
JL
54 " cvlan_id VID |\n"
55 " cvlan_prio PRIORITY |\n"
56 " cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
c2078f8d
SH
57 " dst_mac MASKED-LLADDR |\n"
58 " src_mac MASKED-LLADDR |\n"
eb3b5696 59 " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
6ea2c2b1
OG
60 " ip_tos MASKED-IP_TOS |\n"
61 " ip_ttl MASKED-IP_TTL |\n"
7638ee13
BL
62 " mpls_label LABEL |\n"
63 " mpls_tc TC |\n"
64 " mpls_bos BOS |\n"
65 " mpls_ttl TTL |\n"
b2a1f740
SH
66 " dst_ip PREFIX |\n"
67 " src_ip PREFIX |\n"
512caeb2 68 " dst_port PORT-NUMBER |\n"
bb9b63b1 69 " src_port PORT-NUMBER |\n"
0c30d14d 70 " tcp_flags MASKED-TCP_FLAGS |\n"
6374961a
SH
71 " type MASKED-ICMP-TYPE |\n"
72 " code MASKED-ICMP-CODE |\n"
c7ec052b
SH
73 " arp_tip IPV4-PREFIX |\n"
74 " arp_sip IPV4-PREFIX |\n"
f888f4e2
SH
75 " arp_op [ request | reply | OP ] |\n"
76 " arp_tha MASKED-LLADDR |\n"
77 " arp_sha MASKED-LLADDR |\n"
10da5528
SH
78 " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
79 " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
bf73c650 80 " enc_key_id [ KEY-ID ] |\n"
761ec9e2
OG
81 " enc_tos MASKED-IP_TOS |\n"
82 " enc_ttl MASKED-IP_TTL |\n"
56155d4d 83 " geneve_opts MASKED-OPTIONS |\n"
08f66c80 84 " ip_flags IP-FLAGS | \n"
a5ae170e 85 " enc_dst_port [ port_number ] }\n"
512caeb2 86 " FILTERID := X:Y:Z\n"
c2078f8d 87 " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
512caeb2
SH
88 " ACTION-SPEC := ... look at individual actions\n"
89 "\n"
328374dc 90 "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
512caeb2
SH
91 "NOTE: There can be only used one mask per one prio. If user needs\n"
92 " to specify different mask, he has to use different prio.\n");
30eb304e
JP
93}
94
95static int flower_parse_eth_addr(char *str, int addr_type, int mask_type,
96 struct nlmsghdr *n)
97{
c2078f8d
SH
98 int ret, err = -1;
99 char addr[ETH_ALEN], *slash;
100
101 slash = strchr(str, '/');
102 if (slash)
103 *slash = '\0';
30eb304e
JP
104
105 ret = ll_addr_a2n(addr, sizeof(addr), str);
106 if (ret < 0)
c2078f8d 107 goto err;
30eb304e 108 addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr));
c2078f8d
SH
109
110 if (slash) {
111 unsigned bits;
112
113 if (!get_unsigned(&bits, slash + 1, 10)) {
114 uint64_t mask;
115
116 /* Extra 16 bit shift to push mac address into
117 * high bits of uint64_t
118 */
119 mask = htonll(0xffffffffffffULL << (16 + 48 - bits));
120 memcpy(addr, &mask, ETH_ALEN);
121 } else {
122 ret = ll_addr_a2n(addr, sizeof(addr), slash + 1);
123 if (ret < 0)
124 goto err;
125 }
126 } else {
127 memset(addr, 0xff, ETH_ALEN);
128 }
30eb304e 129 addattr_l(n, MAX_MSG, mask_type, addr, sizeof(addr));
c2078f8d
SH
130
131 err = 0;
132err:
133 if (slash)
134 *slash = '/';
135 return err;
30eb304e
JP
136}
137
1f0a5dfd
JL
138static bool eth_type_vlan(__be16 ethertype)
139{
140 return ethertype == htons(ETH_P_8021Q) ||
141 ethertype == htons(ETH_P_8021AD);
142}
143
745d9172 144static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
512caeb2
SH
145 __be16 *p_vlan_eth_type,
146 struct nlmsghdr *n)
745d9172
HHZ
147{
148 __be16 vlan_eth_type;
149
1f0a5dfd
JL
150 if (!eth_type_vlan(eth_type)) {
151 fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n",
152 type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype");
745d9172
HHZ
153 return -1;
154 }
155
156 if (ll_proto_a2n(&vlan_eth_type, str))
157 invarg("invalid vlan_ethtype", str);
158 addattr16(n, MAX_MSG, type, vlan_eth_type);
159 *p_vlan_eth_type = vlan_eth_type;
160 return 0;
161}
162
08f66c80
PB
163struct flag_to_string {
164 int flag;
165 enum flower_matching_flags type;
166 char *string;
167};
22a8f019 168
08f66c80
PB
169static struct flag_to_string flags_str[] = {
170 { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOWER_IP_FLAGS, "frag" },
fb4e6abf 171 { TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST, FLOWER_IP_FLAGS, "firstfrag" },
08f66c80 172};
22a8f019 173
08f66c80
PB
174static int flower_parse_matching_flags(char *str,
175 enum flower_matching_flags type,
176 __u32 *mtf, __u32 *mtf_mask)
177{
178 char *token;
179 bool no;
180 bool found;
181 int i;
22a8f019 182
08f66c80
PB
183 token = strtok(str, "/");
184
185 while (token) {
186 if (!strncmp(token, "no", 2)) {
187 no = true;
188 token += 2;
189 } else
190 no = false;
191
192 found = false;
193 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
194 if (type != flags_str[i].type)
195 continue;
196
197 if (!strcmp(token, flags_str[i].string)) {
198 if (no)
199 *mtf &= ~flags_str[i].flag;
200 else
201 *mtf |= flags_str[i].flag;
202
203 *mtf_mask |= flags_str[i].flag;
204 found = true;
205 break;
206 }
207 }
208 if (!found)
22a8f019 209 return -1;
08f66c80
PB
210
211 token = strtok(NULL, "/");
22a8f019
PB
212 }
213
22a8f019
PB
214 return 0;
215}
216
30eb304e
JP
217static int flower_parse_ip_proto(char *str, __be16 eth_type, int type,
218 __u8 *p_ip_proto, struct nlmsghdr *n)
219{
220 int ret;
221 __u8 ip_proto;
222
eb3b5696
SH
223 if (eth_type != htons(ETH_P_IP) && eth_type != htons(ETH_P_IPV6))
224 goto err;
225
30eb304e
JP
226 if (matches(str, "tcp") == 0) {
227 ip_proto = IPPROTO_TCP;
228 } else if (matches(str, "udp") == 0) {
229 ip_proto = IPPROTO_UDP;
a1fb0d48
SH
230 } else if (matches(str, "sctp") == 0) {
231 ip_proto = IPPROTO_SCTP;
eb3b5696
SH
232 } else if (matches(str, "icmp") == 0) {
233 if (eth_type != htons(ETH_P_IP))
234 goto err;
235 ip_proto = IPPROTO_ICMP;
236 } else if (matches(str, "icmpv6") == 0) {
237 if (eth_type != htons(ETH_P_IPV6))
238 goto err;
239 ip_proto = IPPROTO_ICMPV6;
30eb304e
JP
240 } else {
241 ret = get_u8(&ip_proto, str, 16);
242 if (ret)
243 return -1;
244 }
245 addattr8(n, MAX_MSG, type, ip_proto);
246 *p_ip_proto = ip_proto;
247 return 0;
eb3b5696
SH
248
249err:
250 fprintf(stderr, "Illegal \"eth_type\" for ip proto\n");
251 return -1;
30eb304e
JP
252}
253
f888f4e2
SH
254static int __flower_parse_ip_addr(char *str, int family,
255 int addr4_type, int mask4_type,
256 int addr6_type, int mask6_type,
257 struct nlmsghdr *n)
30eb304e
JP
258{
259 int ret;
260 inet_prefix addr;
30eb304e
JP
261 int bits;
262 int i;
263
30eb304e
JP
264 ret = get_prefix(&addr, str, family);
265 if (ret)
266 return -1;
267
bb9b63b1
AV
268 if (family && (addr.family != family)) {
269 fprintf(stderr, "Illegal \"eth_type\" for ip address\n");
30eb304e 270 return -1;
bb9b63b1 271 }
30eb304e
JP
272
273 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
274 addr.data, addr.bytelen);
275
276 memset(addr.data, 0xff, addr.bytelen);
277 bits = addr.bitlen;
278 for (i = 0; i < addr.bytelen / 4; i++) {
279 if (!bits) {
280 addr.data[i] = 0;
281 } else if (bits / 32 >= 1) {
282 bits -= 32;
283 } else {
284 addr.data[i] <<= 32 - bits;
285 addr.data[i] = htonl(addr.data[i]);
286 bits = 0;
287 }
288 }
289
290 addattr_l(n, MAX_MSG, addr.family == AF_INET ? mask4_type : mask6_type,
291 addr.data, addr.bytelen);
292
293 return 0;
294}
295
f888f4e2
SH
296static int flower_parse_ip_addr(char *str, __be16 eth_type,
297 int addr4_type, int mask4_type,
298 int addr6_type, int mask6_type,
299 struct nlmsghdr *n)
300{
301 int family;
302
303 if (eth_type == htons(ETH_P_IP)) {
304 family = AF_INET;
305 } else if (eth_type == htons(ETH_P_IPV6)) {
306 family = AF_INET6;
307 } else if (!eth_type) {
308 family = AF_UNSPEC;
309 } else {
310 return -1;
311 }
312
164a9ff4
RD
313 return __flower_parse_ip_addr(str, family, addr4_type, mask4_type,
314 addr6_type, mask6_type, n);
f888f4e2
SH
315}
316
317static bool flower_eth_type_arp(__be16 eth_type)
318{
319 return eth_type == htons(ETH_P_ARP) || eth_type == htons(ETH_P_RARP);
320}
321
322static int flower_parse_arp_ip_addr(char *str, __be16 eth_type,
323 int addr_type, int mask_type,
324 struct nlmsghdr *n)
325{
326 if (!flower_eth_type_arp(eth_type))
327 return -1;
328
329 return __flower_parse_ip_addr(str, AF_INET, addr_type, mask_type,
330 TCA_FLOWER_UNSPEC, TCA_FLOWER_UNSPEC, n);
331}
332
180136e5
SH
333static int flower_parse_u8(char *str, int value_type, int mask_type,
334 int (*value_from_name)(const char *str,
335 __u8 *value),
336 bool (*value_validate)(__u8 value),
337 struct nlmsghdr *n)
f888f4e2
SH
338{
339 char *slash;
340 int ret, err = -1;
180136e5 341 __u8 value, mask;
f888f4e2
SH
342
343 slash = strchr(str, '/');
344 if (slash)
345 *slash = '\0';
346
180136e5
SH
347 ret = value_from_name ? value_from_name(str, &value) : -1;
348 if (ret < 0) {
f888f4e2
SH
349 ret = get_u8(&value, str, 10);
350 if (ret)
351 goto err;
f888f4e2
SH
352 }
353
180136e5
SH
354 if (value_validate && !value_validate(value))
355 goto err;
356
f888f4e2
SH
357 if (slash) {
358 ret = get_u8(&mask, slash + 1, 10);
359 if (ret)
360 goto err;
361 }
362 else {
363 mask = UINT8_MAX;
364 }
365
180136e5 366 addattr8(n, MAX_MSG, value_type, value);
f888f4e2
SH
367 addattr8(n, MAX_MSG, mask_type, mask);
368
369 err = 0;
370err:
371 if (slash)
372 *slash = '/';
373 return err;
374}
375
9d36e54f
SH
376static const char *flower_print_arp_op_to_name(__u8 op)
377{
378 switch (op) {
379 case ARPOP_REQUEST:
380 return "request";
381 case ARPOP_REPLY:
382 return "reply";
383 default:
384 return NULL;
385 }
386}
387
180136e5
SH
388static int flower_arp_op_from_name(const char *name, __u8 *op)
389{
390 if (!strcmp(name, "request"))
391 *op = ARPOP_REQUEST;
392 else if (!strcmp(name, "reply"))
393 *op = ARPOP_REPLY;
394 else
395 return -1;
396
397 return 0;
398}
399
400static bool flow_arp_op_validate(__u8 op)
401{
402 return !op || op == ARPOP_REQUEST || op == ARPOP_REPLY;
403}
404
405static int flower_parse_arp_op(char *str, __be16 eth_type,
406 int op_type, int mask_type,
407 struct nlmsghdr *n)
408{
409 if (!flower_eth_type_arp(eth_type))
410 return -1;
411
412 return flower_parse_u8(str, op_type, mask_type, flower_arp_op_from_name,
413 flow_arp_op_validate, n);
414}
415
eb3b5696
SH
416static int flower_icmp_attr_type(__be16 eth_type, __u8 ip_proto,
417 enum flower_icmp_field field)
418{
419 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP)
420 return field == FLOWER_ICMP_FIELD_CODE ?
421 TCA_FLOWER_KEY_ICMPV4_CODE :
422 TCA_FLOWER_KEY_ICMPV4_TYPE;
423 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6)
424 return field == FLOWER_ICMP_FIELD_CODE ?
425 TCA_FLOWER_KEY_ICMPV6_CODE :
426 TCA_FLOWER_KEY_ICMPV6_TYPE;
427
428 return -1;
429}
430
6374961a
SH
431static int flower_icmp_attr_mask_type(__be16 eth_type, __u8 ip_proto,
432 enum flower_icmp_field field)
433{
434 if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP)
435 return field == FLOWER_ICMP_FIELD_CODE ?
436 TCA_FLOWER_KEY_ICMPV4_CODE_MASK :
437 TCA_FLOWER_KEY_ICMPV4_TYPE_MASK;
438 else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6)
439 return field == FLOWER_ICMP_FIELD_CODE ?
440 TCA_FLOWER_KEY_ICMPV6_CODE_MASK :
441 TCA_FLOWER_KEY_ICMPV6_TYPE_MASK;
442
443 return -1;
444}
445
eb3b5696
SH
446static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto,
447 enum flower_icmp_field field, struct nlmsghdr *n)
448{
6374961a 449 int value_type, mask_type;
eb3b5696 450
6374961a
SH
451 value_type = flower_icmp_attr_type(eth_type, ip_proto, field);
452 mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, field);
453 if (value_type < 0 || mask_type < 0)
eb3b5696
SH
454 return -1;
455
6374961a 456 return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n);
eb3b5696
SH
457}
458
6910d656 459static int flower_port_attr_type(__u8 ip_proto, enum flower_endpoint endpoint)
30eb304e 460{
6bd5b80c 461 if (ip_proto == IPPROTO_TCP)
6910d656
SH
462 return endpoint == FLOWER_ENDPOINT_SRC ?
463 TCA_FLOWER_KEY_TCP_SRC :
a1fb0d48 464 TCA_FLOWER_KEY_TCP_DST;
6bd5b80c 465 else if (ip_proto == IPPROTO_UDP)
6910d656
SH
466 return endpoint == FLOWER_ENDPOINT_SRC ?
467 TCA_FLOWER_KEY_UDP_SRC :
a1fb0d48 468 TCA_FLOWER_KEY_UDP_DST;
6bd5b80c 469 else if (ip_proto == IPPROTO_SCTP)
6910d656
SH
470 return endpoint == FLOWER_ENDPOINT_SRC ?
471 TCA_FLOWER_KEY_SCTP_SRC :
a1fb0d48 472 TCA_FLOWER_KEY_SCTP_DST;
6bd5b80c 473 else
30eb304e 474 return -1;
a1fb0d48
SH
475}
476
8930840e
AN
477static int flower_port_range_attr_type(__u8 ip_proto, enum flower_endpoint type,
478 __be16 *min_port_type,
479 __be16 *max_port_type)
480{
481 if (ip_proto == IPPROTO_TCP || ip_proto == IPPROTO_UDP ||
482 ip_proto == IPPROTO_SCTP) {
483 if (type == FLOWER_ENDPOINT_SRC) {
484 *min_port_type = TCA_FLOWER_KEY_PORT_SRC_MIN;
485 *max_port_type = TCA_FLOWER_KEY_PORT_SRC_MAX;
486 } else {
487 *min_port_type = TCA_FLOWER_KEY_PORT_DST_MIN;
488 *max_port_type = TCA_FLOWER_KEY_PORT_DST_MAX;
489 }
490 } else {
491 return -1;
492 }
493 return 0;
494}
495
6910d656
SH
496static int flower_parse_port(char *str, __u8 ip_proto,
497 enum flower_endpoint endpoint,
a1fb0d48
SH
498 struct nlmsghdr *n)
499{
8930840e 500 __u16 min, max;
a1fb0d48 501 int ret;
a1fb0d48 502
8930840e 503 ret = sscanf(str, "%hu-%hu", &min, &max);
30eb304e 504
8930840e
AN
505 if (ret == 1) {
506 int type;
30eb304e 507
8930840e
AN
508 type = flower_port_attr_type(ip_proto, endpoint);
509 if (type < 0)
510 return -1;
511 addattr16(n, MAX_MSG, type, htons(min));
512 } else if (ret == 2) {
513 __be16 min_port_type, max_port_type;
30eb304e 514
8930840e
AN
515 if (max <= min) {
516 fprintf(stderr, "max value should be greater than min value\n");
517 return -1;
518 }
519 if (flower_port_range_attr_type(ip_proto, endpoint,
520 &min_port_type, &max_port_type))
521 return -1;
522
523 addattr16(n, MAX_MSG, min_port_type, htons(min));
524 addattr16(n, MAX_MSG, max_port_type, htons(max));
525 } else {
526 return -1;
527 }
30eb304e
JP
528 return 0;
529}
530
0c30d14d
JP
531#define TCP_FLAGS_MAX_MASK 0xfff
532
533static int flower_parse_tcp_flags(char *str, int flags_type, int mask_type,
534 struct nlmsghdr *n)
535{
536 char *slash;
537 int ret, err = -1;
538 __u16 flags;
539
540 slash = strchr(str, '/');
541 if (slash)
542 *slash = '\0';
543
544 ret = get_u16(&flags, str, 16);
545 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
546 goto err;
547
548 addattr16(n, MAX_MSG, flags_type, htons(flags));
549
550 if (slash) {
551 ret = get_u16(&flags, slash + 1, 16);
552 if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
553 goto err;
554 } else {
555 flags = TCP_FLAGS_MAX_MASK;
556 }
557 addattr16(n, MAX_MSG, mask_type, htons(flags));
558
559 err = 0;
560err:
561 if (slash)
562 *slash = '/';
563 return err;
564}
565
6ea2c2b1
OG
566static int flower_parse_ip_tos_ttl(char *str, int key_type, int mask_type,
567 struct nlmsghdr *n)
568{
569 char *slash;
570 int ret, err = -1;
571 __u8 tos_ttl;
572
573 slash = strchr(str, '/');
574 if (slash)
575 *slash = '\0';
576
577 ret = get_u8(&tos_ttl, str, 10);
578 if (ret < 0)
579 ret = get_u8(&tos_ttl, str, 16);
580 if (ret < 0)
581 goto err;
582
583 addattr8(n, MAX_MSG, key_type, tos_ttl);
584
585 if (slash) {
586 ret = get_u8(&tos_ttl, slash + 1, 16);
587 if (ret < 0)
588 goto err;
589 } else {
590 tos_ttl = 0xff;
591 }
592 addattr8(n, MAX_MSG, mask_type, tos_ttl);
593
594 err = 0;
595err:
596 if (slash)
597 *slash = '/';
598 return err;
599}
600
bb9b63b1
AV
601static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n)
602{
603 int ret;
604 __be32 key_id;
605
606 ret = get_be32(&key_id, str, 10);
607 if (!ret)
608 addattr32(n, MAX_MSG, type, key_id);
609
610 return ret;
611}
612
41aa17ff
HHZ
613static int flower_parse_enc_port(char *str, int type, struct nlmsghdr *n)
614{
615 int ret;
616 __be16 port;
617
618 ret = get_be16(&port, str, 10);
619 if (ret)
620 return -1;
621
622 addattr16(n, MAX_MSG, type, port);
623
624 return 0;
625}
626
56155d4d
PJV
627static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n)
628{
629 struct rtattr *nest;
630 char *token;
631 int i, err;
632
633 nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_GENEVE);
634
635 i = 1;
636 token = strsep(&str, ":");
637 while (token) {
638 switch (i) {
639 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS:
640 {
641 __be16 opt_class;
642
643 if (!strlen(token))
644 break;
645 err = get_be16(&opt_class, token, 16);
646 if (err)
647 return err;
648
649 addattr16(n, MAX_MSG, i, opt_class);
650 break;
651 }
652 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE:
653 {
654 __u8 opt_type;
655
656 if (!strlen(token))
657 break;
658 err = get_u8(&opt_type, token, 16);
659 if (err)
660 return err;
661
662 addattr8(n, MAX_MSG, i, opt_type);
663 break;
664 }
665 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA:
666 {
667 size_t token_len = strlen(token);
668 __u8 *opts;
669
670 if (!token_len)
671 break;
672 opts = malloc(token_len / 2);
673 if (!opts)
674 return -1;
675 if (hex2mem(token, opts, token_len / 2) < 0) {
676 free(opts);
677 return -1;
678 }
679 addattr_l(n, MAX_MSG, i, opts, token_len / 2);
680 free(opts);
681
682 break;
683 }
684 default:
685 fprintf(stderr, "Unknown \"geneve_opts\" type\n");
686 return -1;
687 }
688
689 token = strsep(&str, ":");
690 i++;
691 }
692 addattr_nest_end(n, nest);
693
694 return 0;
695}
696
697static int flower_parse_enc_opt_part(char *str, struct nlmsghdr *n)
698{
699 char *token;
700 int err;
701
702 token = strsep(&str, ",");
703 while (token) {
704 err = flower_parse_geneve_opts(token, n);
705 if (err)
706 return err;
707
708 token = strsep(&str, ",");
709 }
710
711 return 0;
712}
713
714static int flower_check_enc_opt_key(char *key)
715{
716 int key_len, col_cnt = 0;
717
718 key_len = strlen(key);
719 while ((key = strchr(key, ':'))) {
720 if (strlen(key) == key_len)
721 return -1;
722
723 key_len = strlen(key) - 1;
724 col_cnt++;
725 key++;
726 }
727
728 if (col_cnt != 2 || !key_len)
729 return -1;
730
731 return 0;
732}
733
734static int flower_parse_enc_opts(char *str, struct nlmsghdr *n)
735{
736 char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX];
737 int data_len, key_len, mask_len, err;
738 char *token, *slash;
739 struct rtattr *nest;
740
741 key_len = 0;
742 mask_len = 0;
743 token = strsep(&str, ",");
744 while (token) {
745 slash = strchr(token, '/');
746 if (slash)
747 *slash = '\0';
748
749 if ((key_len + strlen(token) > XATTR_SIZE_MAX) ||
750 flower_check_enc_opt_key(token))
751 return -1;
752
753 strcpy(&key[key_len], token);
754 key_len += strlen(token) + 1;
755 key[key_len - 1] = ',';
756
757 if (!slash) {
758 /* Pad out mask when not provided */
759 if (mask_len + strlen(token) > XATTR_SIZE_MAX)
760 return -1;
761
762 data_len = strlen(rindex(token, ':'));
763 sprintf(&mask[mask_len], "ffff:ff:");
764 mask_len += 8;
765 memset(&mask[mask_len], 'f', data_len - 1);
766 mask_len += data_len;
767 mask[mask_len - 1] = ',';
768 token = strsep(&str, ",");
769 continue;
770 }
771
772 if (mask_len + strlen(slash + 1) > XATTR_SIZE_MAX)
773 return -1;
774
775 strcpy(&mask[mask_len], slash + 1);
776 mask_len += strlen(slash + 1) + 1;
777 mask[mask_len - 1] = ',';
778
779 *slash = '/';
780 token = strsep(&str, ",");
781 }
782 key[key_len - 1] = '\0';
783 mask[mask_len - 1] = '\0';
784
785 nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS);
786 err = flower_parse_enc_opt_part(key, n);
787 if (err)
788 return err;
789 addattr_nest_end(n, nest);
790
791 nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_MASK);
792 err = flower_parse_enc_opt_part(mask, n);
793 if (err)
794 return err;
795 addattr_nest_end(n, nest);
796
797 return 0;
798}
799
30eb304e
JP
800static int flower_parse_opt(struct filter_util *qu, char *handle,
801 int argc, char **argv, struct nlmsghdr *n)
802{
803 int ret;
804 struct tcmsg *t = NLMSG_DATA(n);
805 struct rtattr *tail;
488b41d0 806 __be16 eth_type = TC_H_MIN(t->tcm_info);
745d9172 807 __be16 vlan_ethtype = 0;
1f0a5dfd 808 __be16 cvlan_ethtype = 0;
30eb304e 809 __u8 ip_proto = 0xff;
cfcabf18 810 __u32 flags = 0;
08f66c80
PB
811 __u32 mtf = 0;
812 __u32 mtf_mask = 0;
30eb304e 813
30eb304e
JP
814 if (handle) {
815 ret = get_u32(&t->tcm_handle, handle, 0);
816 if (ret) {
817 fprintf(stderr, "Illegal \"handle\"\n");
818 return -1;
819 }
820 }
821
822 tail = (struct rtattr *) (((void *) n) + NLMSG_ALIGN(n->nlmsg_len));
823 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
824
488b41d0
JHS
825 if (argc == 0) {
826 /*at minimal we will match all ethertype packets */
827 goto parse_done;
828 }
829
30eb304e
JP
830 while (argc > 0) {
831 if (matches(*argv, "classid") == 0 ||
832 matches(*argv, "flowid") == 0) {
32a121cb 833 unsigned int handle;
30eb304e
JP
834
835 NEXT_ARG();
836 ret = get_tc_classid(&handle, *argv);
837 if (ret) {
838 fprintf(stderr, "Illegal \"classid\"\n");
839 return -1;
840 }
841 addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4);
0d575c4d
AN
842 } else if (matches(*argv, "hw_tc") == 0) {
843 unsigned int handle;
844 __u32 tc;
845 char *end;
846
847 NEXT_ARG();
848 tc = strtoul(*argv, &end, 0);
849 if (*end) {
850 fprintf(stderr, "Illegal TC index\n");
851 return -1;
852 }
853 if (tc >= TC_QOPT_MAX_QUEUE) {
854 fprintf(stderr, "TC index exceeds max range\n");
855 return -1;
856 }
857 handle = TC_H_MAKE(TC_H_MAJ(t->tcm_parent),
858 TC_H_MIN(tc + TC_H_MIN_PRIORITY));
859 addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle,
860 sizeof(handle));
08f66c80 861 } else if (matches(*argv, "ip_flags") == 0) {
22a8f019
PB
862 NEXT_ARG();
863 ret = flower_parse_matching_flags(*argv,
08f66c80
PB
864 FLOWER_IP_FLAGS,
865 &mtf,
866 &mtf_mask);
22a8f019 867 if (ret < 0) {
08f66c80 868 fprintf(stderr, "Illegal \"ip_flags\"\n");
22a8f019
PB
869 return -1;
870 }
ac6a4c22
MRL
871 } else if (matches(*argv, "verbose") == 0) {
872 flags |= TCA_CLS_FLAGS_VERBOSE;
cfcabf18
AV
873 } else if (matches(*argv, "skip_hw") == 0) {
874 flags |= TCA_CLS_FLAGS_SKIP_HW;
875 } else if (matches(*argv, "skip_sw") == 0) {
876 flags |= TCA_CLS_FLAGS_SKIP_SW;
30eb304e 877 } else if (matches(*argv, "indev") == 0) {
30eb304e 878 NEXT_ARG();
625df645
PS
879 if (check_ifname(*argv))
880 invarg("\"indev\" not a valid ifname", *argv);
ee474849 881 addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, *argv);
745d9172
HHZ
882 } else if (matches(*argv, "vlan_id") == 0) {
883 __u16 vid;
884
885 NEXT_ARG();
1f0a5dfd
JL
886 if (!eth_type_vlan(eth_type)) {
887 fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n");
745d9172
HHZ
888 return -1;
889 }
890 ret = get_u16(&vid, *argv, 10);
891 if (ret < 0 || vid & ~0xfff) {
892 fprintf(stderr, "Illegal \"vlan_id\"\n");
893 return -1;
894 }
895 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid);
896 } else if (matches(*argv, "vlan_prio") == 0) {
897 __u8 vlan_prio;
898
899 NEXT_ARG();
1f0a5dfd
JL
900 if (!eth_type_vlan(eth_type)) {
901 fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n");
745d9172
HHZ
902 return -1;
903 }
904 ret = get_u8(&vlan_prio, *argv, 10);
905 if (ret < 0 || vlan_prio & ~0x7) {
906 fprintf(stderr, "Illegal \"vlan_prio\"\n");
907 return -1;
908 }
512caeb2
SH
909 addattr8(n, MAX_MSG,
910 TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio);
745d9172
HHZ
911 } else if (matches(*argv, "vlan_ethtype") == 0) {
912 NEXT_ARG();
913 ret = flower_parse_vlan_eth_type(*argv, eth_type,
512caeb2
SH
914 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
915 &vlan_ethtype, n);
745d9172
HHZ
916 if (ret < 0)
917 return -1;
1f0a5dfd
JL
918 } else if (matches(*argv, "cvlan_id") == 0) {
919 __u16 vid;
920
921 NEXT_ARG();
922 if (!eth_type_vlan(vlan_ethtype)) {
923 fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
924 return -1;
925 }
926 ret = get_u16(&vid, *argv, 10);
927 if (ret < 0 || vid & ~0xfff) {
928 fprintf(stderr, "Illegal \"cvlan_id\"\n");
929 return -1;
930 }
931 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CVLAN_ID, vid);
932 } else if (matches(*argv, "cvlan_prio") == 0) {
933 __u8 cvlan_prio;
934
935 NEXT_ARG();
936 if (!eth_type_vlan(vlan_ethtype)) {
937 fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
938 return -1;
939 }
940 ret = get_u8(&cvlan_prio, *argv, 10);
941 if (ret < 0 || cvlan_prio & ~0x7) {
942 fprintf(stderr, "Illegal \"cvlan_prio\"\n");
943 return -1;
944 }
945 addattr8(n, MAX_MSG,
946 TCA_FLOWER_KEY_CVLAN_PRIO, cvlan_prio);
947 } else if (matches(*argv, "cvlan_ethtype") == 0) {
948 NEXT_ARG();
949 ret = flower_parse_vlan_eth_type(*argv, vlan_ethtype,
950 TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
951 &cvlan_ethtype, n);
952 if (ret < 0)
953 return -1;
7638ee13
BL
954 } else if (matches(*argv, "mpls_label") == 0) {
955 __u32 label;
956
957 NEXT_ARG();
958 if (eth_type != htons(ETH_P_MPLS_UC) &&
959 eth_type != htons(ETH_P_MPLS_MC)) {
960 fprintf(stderr,
961 "Can't set \"mpls_label\" if ethertype isn't MPLS\n");
962 return -1;
963 }
964 ret = get_u32(&label, *argv, 10);
965 if (ret < 0 || label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
966 fprintf(stderr, "Illegal \"mpls_label\"\n");
967 return -1;
968 }
969 addattr32(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_LABEL, label);
970 } else if (matches(*argv, "mpls_tc") == 0) {
971 __u8 tc;
972
973 NEXT_ARG();
974 if (eth_type != htons(ETH_P_MPLS_UC) &&
975 eth_type != htons(ETH_P_MPLS_MC)) {
976 fprintf(stderr,
977 "Can't set \"mpls_tc\" if ethertype isn't MPLS\n");
978 return -1;
979 }
980 ret = get_u8(&tc, *argv, 10);
981 if (ret < 0 || tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
982 fprintf(stderr, "Illegal \"mpls_tc\"\n");
983 return -1;
984 }
985 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_TC, tc);
986 } else if (matches(*argv, "mpls_bos") == 0) {
987 __u8 bos;
988
989 NEXT_ARG();
990 if (eth_type != htons(ETH_P_MPLS_UC) &&
991 eth_type != htons(ETH_P_MPLS_MC)) {
992 fprintf(stderr,
993 "Can't set \"mpls_bos\" if ethertype isn't MPLS\n");
994 return -1;
995 }
996 ret = get_u8(&bos, *argv, 10);
997 if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
998 fprintf(stderr, "Illegal \"mpls_bos\"\n");
999 return -1;
1000 }
1001 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_BOS, bos);
1002 } else if (matches(*argv, "mpls_ttl") == 0) {
1003 __u8 ttl;
1004
1005 NEXT_ARG();
1006 if (eth_type != htons(ETH_P_MPLS_UC) &&
1007 eth_type != htons(ETH_P_MPLS_MC)) {
1008 fprintf(stderr,
1009 "Can't set \"mpls_ttl\" if ethertype isn't MPLS\n");
1010 return -1;
1011 }
1012 ret = get_u8(&ttl, *argv, 10);
1013 if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
1014 fprintf(stderr, "Illegal \"mpls_ttl\"\n");
1015 return -1;
1016 }
1017 addattr8(n, MAX_MSG, TCA_FLOWER_KEY_MPLS_TTL, ttl);
30eb304e
JP
1018 } else if (matches(*argv, "dst_mac") == 0) {
1019 NEXT_ARG();
1020 ret = flower_parse_eth_addr(*argv,
1021 TCA_FLOWER_KEY_ETH_DST,
1022 TCA_FLOWER_KEY_ETH_DST_MASK,
1023 n);
1024 if (ret < 0) {
1025 fprintf(stderr, "Illegal \"dst_mac\"\n");
1026 return -1;
1027 }
1028 } else if (matches(*argv, "src_mac") == 0) {
1029 NEXT_ARG();
1030 ret = flower_parse_eth_addr(*argv,
1031 TCA_FLOWER_KEY_ETH_SRC,
1032 TCA_FLOWER_KEY_ETH_SRC_MASK,
1033 n);
1034 if (ret < 0) {
1035 fprintf(stderr, "Illegal \"src_mac\"\n");
1036 return -1;
1037 }
30eb304e
JP
1038 } else if (matches(*argv, "ip_proto") == 0) {
1039 NEXT_ARG();
1f0a5dfd
JL
1040 ret = flower_parse_ip_proto(*argv, cvlan_ethtype ?
1041 cvlan_ethtype : vlan_ethtype ?
745d9172 1042 vlan_ethtype : eth_type,
30eb304e
JP
1043 TCA_FLOWER_KEY_IP_PROTO,
1044 &ip_proto, n);
1045 if (ret < 0) {
1046 fprintf(stderr, "Illegal \"ip_proto\"\n");
1047 return -1;
1048 }
6ea2c2b1
OG
1049 } else if (matches(*argv, "ip_tos") == 0) {
1050 NEXT_ARG();
1051 ret = flower_parse_ip_tos_ttl(*argv,
1052 TCA_FLOWER_KEY_IP_TOS,
1053 TCA_FLOWER_KEY_IP_TOS_MASK,
1054 n);
1055 if (ret < 0) {
1056 fprintf(stderr, "Illegal \"ip_tos\"\n");
1057 return -1;
1058 }
1059 } else if (matches(*argv, "ip_ttl") == 0) {
1060 NEXT_ARG();
1061 ret = flower_parse_ip_tos_ttl(*argv,
1062 TCA_FLOWER_KEY_IP_TTL,
1063 TCA_FLOWER_KEY_IP_TTL_MASK,
1064 n);
1065 if (ret < 0) {
1066 fprintf(stderr, "Illegal \"ip_ttl\"\n");
1067 return -1;
1068 }
30eb304e
JP
1069 } else if (matches(*argv, "dst_ip") == 0) {
1070 NEXT_ARG();
1f0a5dfd
JL
1071 ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
1072 cvlan_ethtype : vlan_ethtype ?
745d9172 1073 vlan_ethtype : eth_type,
30eb304e
JP
1074 TCA_FLOWER_KEY_IPV4_DST,
1075 TCA_FLOWER_KEY_IPV4_DST_MASK,
1076 TCA_FLOWER_KEY_IPV6_DST,
1077 TCA_FLOWER_KEY_IPV6_DST_MASK,
1078 n);
1079 if (ret < 0) {
1080 fprintf(stderr, "Illegal \"dst_ip\"\n");
1081 return -1;
1082 }
1083 } else if (matches(*argv, "src_ip") == 0) {
1084 NEXT_ARG();
1f0a5dfd
JL
1085 ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
1086 cvlan_ethtype : vlan_ethtype ?
745d9172 1087 vlan_ethtype : eth_type,
30eb304e
JP
1088 TCA_FLOWER_KEY_IPV4_SRC,
1089 TCA_FLOWER_KEY_IPV4_SRC_MASK,
1090 TCA_FLOWER_KEY_IPV6_SRC,
1091 TCA_FLOWER_KEY_IPV6_SRC_MASK,
1092 n);
1093 if (ret < 0) {
1094 fprintf(stderr, "Illegal \"src_ip\"\n");
1095 return -1;
1096 }
1097 } else if (matches(*argv, "dst_port") == 0) {
1098 NEXT_ARG();
dd7d522a
DA
1099 ret = flower_parse_port(*argv, ip_proto,
1100 FLOWER_ENDPOINT_DST, n);
1101 if (ret < 0) {
1102 fprintf(stderr, "Illegal \"dst_port\"\n");
1103 return -1;
30eb304e
JP
1104 }
1105 } else if (matches(*argv, "src_port") == 0) {
1106 NEXT_ARG();
dd7d522a
DA
1107 ret = flower_parse_port(*argv, ip_proto,
1108 FLOWER_ENDPOINT_SRC, n);
1109 if (ret < 0) {
1110 fprintf(stderr, "Illegal \"src_port\"\n");
1111 return -1;
30eb304e 1112 }
0c30d14d
JP
1113 } else if (matches(*argv, "tcp_flags") == 0) {
1114 NEXT_ARG();
1115 ret = flower_parse_tcp_flags(*argv,
1116 TCA_FLOWER_KEY_TCP_FLAGS,
1117 TCA_FLOWER_KEY_TCP_FLAGS_MASK,
1118 n);
1119 if (ret < 0) {
1120 fprintf(stderr, "Illegal \"tcp_flags\"\n");
1121 return -1;
1122 }
eb3b5696
SH
1123 } else if (matches(*argv, "type") == 0) {
1124 NEXT_ARG();
1125 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
1126 FLOWER_ICMP_FIELD_TYPE, n);
1127 if (ret < 0) {
1128 fprintf(stderr, "Illegal \"icmp type\"\n");
1129 return -1;
1130 }
1131 } else if (matches(*argv, "code") == 0) {
1132 NEXT_ARG();
1133 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
1134 FLOWER_ICMP_FIELD_CODE, n);
1135 if (ret < 0) {
1136 fprintf(stderr, "Illegal \"icmp code\"\n");
1137 return -1;
1138 }
f888f4e2
SH
1139 } else if (matches(*argv, "arp_tip") == 0) {
1140 NEXT_ARG();
1141 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
1142 vlan_ethtype : eth_type,
1143 TCA_FLOWER_KEY_ARP_TIP,
1144 TCA_FLOWER_KEY_ARP_TIP_MASK,
1145 n);
1146 if (ret < 0) {
1147 fprintf(stderr, "Illegal \"arp_tip\"\n");
1148 return -1;
1149 }
1150 } else if (matches(*argv, "arp_sip") == 0) {
1151 NEXT_ARG();
1152 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
1153 vlan_ethtype : eth_type,
1154 TCA_FLOWER_KEY_ARP_SIP,
1155 TCA_FLOWER_KEY_ARP_SIP_MASK,
1156 n);
1157 if (ret < 0) {
1158 fprintf(stderr, "Illegal \"arp_sip\"\n");
1159 return -1;
1160 }
1161 } else if (matches(*argv, "arp_op") == 0) {
1162 NEXT_ARG();
1163 ret = flower_parse_arp_op(*argv, vlan_ethtype ?
1164 vlan_ethtype : eth_type,
1165 TCA_FLOWER_KEY_ARP_OP,
1166 TCA_FLOWER_KEY_ARP_OP_MASK,
1167 n);
1168 if (ret < 0) {
1169 fprintf(stderr, "Illegal \"arp_op\"\n");
1170 return -1;
1171 }
1172 } else if (matches(*argv, "arp_tha") == 0) {
1173 NEXT_ARG();
1174 ret = flower_parse_eth_addr(*argv,
1175 TCA_FLOWER_KEY_ARP_THA,
1176 TCA_FLOWER_KEY_ARP_THA_MASK,
1177 n);
1178 if (ret < 0) {
1179 fprintf(stderr, "Illegal \"arp_tha\"\n");
1180 return -1;
1181 }
1182 } else if (matches(*argv, "arp_sha") == 0) {
1183 NEXT_ARG();
1184 ret = flower_parse_eth_addr(*argv,
1185 TCA_FLOWER_KEY_ARP_SHA,
1186 TCA_FLOWER_KEY_ARP_SHA_MASK,
1187 n);
1188 if (ret < 0) {
1189 fprintf(stderr, "Illegal \"arp_sha\"\n");
1190 return -1;
1191 }
bb9b63b1
AV
1192 } else if (matches(*argv, "enc_dst_ip") == 0) {
1193 NEXT_ARG();
1194 ret = flower_parse_ip_addr(*argv, 0,
1195 TCA_FLOWER_KEY_ENC_IPV4_DST,
1196 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
1197 TCA_FLOWER_KEY_ENC_IPV6_DST,
1198 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
1199 n);
1200 if (ret < 0) {
1201 fprintf(stderr, "Illegal \"enc_dst_ip\"\n");
1202 return -1;
1203 }
1204 } else if (matches(*argv, "enc_src_ip") == 0) {
1205 NEXT_ARG();
1206 ret = flower_parse_ip_addr(*argv, 0,
1207 TCA_FLOWER_KEY_ENC_IPV4_SRC,
1208 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
1209 TCA_FLOWER_KEY_ENC_IPV6_SRC,
1210 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
1211 n);
1212 if (ret < 0) {
1213 fprintf(stderr, "Illegal \"enc_src_ip\"\n");
1214 return -1;
1215 }
1216 } else if (matches(*argv, "enc_key_id") == 0) {
1217 NEXT_ARG();
1218 ret = flower_parse_key_id(*argv,
1219 TCA_FLOWER_KEY_ENC_KEY_ID, n);
1220 if (ret < 0) {
1221 fprintf(stderr, "Illegal \"enc_key_id\"\n");
1222 return -1;
1223 }
41aa17ff
HHZ
1224 } else if (matches(*argv, "enc_dst_port") == 0) {
1225 NEXT_ARG();
1226 ret = flower_parse_enc_port(*argv,
1227 TCA_FLOWER_KEY_ENC_UDP_DST_PORT, n);
1228 if (ret < 0) {
1229 fprintf(stderr, "Illegal \"enc_dst_port\"\n");
1230 return -1;
1231 }
761ec9e2
OG
1232 } else if (matches(*argv, "enc_tos") == 0) {
1233 NEXT_ARG();
1234 ret = flower_parse_ip_tos_ttl(*argv,
1235 TCA_FLOWER_KEY_ENC_IP_TOS,
1236 TCA_FLOWER_KEY_ENC_IP_TOS_MASK,
1237 n);
1238 if (ret < 0) {
1239 fprintf(stderr, "Illegal \"enc_tos\"\n");
1240 return -1;
1241 }
1242 } else if (matches(*argv, "enc_ttl") == 0) {
1243 NEXT_ARG();
1244 ret = flower_parse_ip_tos_ttl(*argv,
1245 TCA_FLOWER_KEY_ENC_IP_TTL,
1246 TCA_FLOWER_KEY_ENC_IP_TTL_MASK,
1247 n);
1248 if (ret < 0) {
1249 fprintf(stderr, "Illegal \"enc_ttl\"\n");
1250 return -1;
1251 }
56155d4d
PJV
1252 } else if (matches(*argv, "geneve_opts") == 0) {
1253 NEXT_ARG();
1254 ret = flower_parse_enc_opts(*argv, n);
1255 if (ret < 0) {
1256 fprintf(stderr, "Illegal \"geneve_opts\"\n");
1257 return -1;
1258 }
30eb304e
JP
1259 } else if (matches(*argv, "action") == 0) {
1260 NEXT_ARG();
1261 ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n);
1262 if (ret) {
1263 fprintf(stderr, "Illegal \"action\"\n");
1264 return -1;
1265 }
1266 continue;
1267 } else if (strcmp(*argv, "help") == 0) {
1268 explain();
1269 return -1;
1270 } else {
1271 fprintf(stderr, "What is \"%s\"?\n", *argv);
1272 explain();
1273 return -1;
1274 }
1275 argc--; argv++;
1276 }
1277
488b41d0 1278parse_done:
c85609b2
RD
1279 ret = addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags);
1280 if (ret)
1281 return ret;
cfcabf18 1282
08f66c80
PB
1283 if (mtf_mask) {
1284 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf));
1285 if (ret)
1286 return ret;
1287
1288 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask));
1289 if (ret)
1290 return ret;
1291 }
1292
4f7d406f
BL
1293 if (eth_type != htons(ETH_P_ALL)) {
1294 ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
1295 if (ret)
1296 return ret;
1297 }
488b41d0 1298
32a121cb 1299 tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail;
30eb304e
JP
1300
1301 return 0;
1302}
1303
1304static int __mask_bits(char *addr, size_t len)
1305{
1306 int bits = 0;
1307 bool hole = false;
1308 int i;
1309 int j;
1310
1311 for (i = 0; i < len; i++, addr++) {
1312 for (j = 7; j >= 0; j--) {
1313 if (((*addr) >> j) & 0x1) {
1314 if (hole)
1315 return -1;
1316 bits++;
1317 } else if (bits) {
1318 hole = true;
1319 } else{
1320 return -1;
1321 }
1322 }
1323 }
1324 return bits;
1325}
1326
e28b88a4 1327static void flower_print_eth_addr(char *name, struct rtattr *addr_attr,
30eb304e
JP
1328 struct rtattr *mask_attr)
1329{
e28b88a4
JP
1330 SPRINT_BUF(namefrm);
1331 SPRINT_BUF(out);
30eb304e 1332 SPRINT_BUF(b1);
e28b88a4 1333 size_t done;
30eb304e
JP
1334 int bits;
1335
1336 if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
1337 return;
e28b88a4
JP
1338 done = sprintf(out, "%s",
1339 ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
1340 0, b1, sizeof(b1)));
1341 if (mask_attr && RTA_PAYLOAD(mask_attr) == ETH_ALEN) {
1342 bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
1343 if (bits < 0)
1344 sprintf(out + done, "/%s",
1345 ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
1346 0, b1, sizeof(b1)));
1347 else if (bits < ETH_ALEN * 8)
1348 sprintf(out + done, "/%d", bits);
1349 }
1350
1351 sprintf(namefrm, "\n %s %%s", name);
1352 print_string(PRINT_ANY, name, namefrm, out);
30eb304e
JP
1353}
1354
e28b88a4 1355static void flower_print_eth_type(__be16 *p_eth_type,
30eb304e
JP
1356 struct rtattr *eth_type_attr)
1357{
e28b88a4 1358 SPRINT_BUF(out);
30eb304e
JP
1359 __be16 eth_type;
1360
1361 if (!eth_type_attr)
1362 return;
1363
1364 eth_type = rta_getattr_u16(eth_type_attr);
30eb304e 1365 if (eth_type == htons(ETH_P_IP))
e28b88a4 1366 sprintf(out, "ipv4");
30eb304e 1367 else if (eth_type == htons(ETH_P_IPV6))
e28b88a4 1368 sprintf(out, "ipv6");
f888f4e2 1369 else if (eth_type == htons(ETH_P_ARP))
e28b88a4 1370 sprintf(out, "arp");
f888f4e2 1371 else if (eth_type == htons(ETH_P_RARP))
e28b88a4 1372 sprintf(out, "rarp");
30eb304e 1373 else
e28b88a4
JP
1374 sprintf(out, "%04x", ntohs(eth_type));
1375
1376 print_string(PRINT_ANY, "eth_type", "\n eth_type %s", out);
30eb304e
JP
1377 *p_eth_type = eth_type;
1378}
1379
e28b88a4 1380static void flower_print_ip_proto(__u8 *p_ip_proto,
30eb304e
JP
1381 struct rtattr *ip_proto_attr)
1382{
e28b88a4 1383 SPRINT_BUF(out);
30eb304e
JP
1384 __u8 ip_proto;
1385
1386 if (!ip_proto_attr)
1387 return;
1388
1389 ip_proto = rta_getattr_u8(ip_proto_attr);
30eb304e 1390 if (ip_proto == IPPROTO_TCP)
e28b88a4 1391 sprintf(out, "tcp");
30eb304e 1392 else if (ip_proto == IPPROTO_UDP)
e28b88a4 1393 sprintf(out, "udp");
a1fb0d48 1394 else if (ip_proto == IPPROTO_SCTP)
e28b88a4 1395 sprintf(out, "sctp");
eb3b5696 1396 else if (ip_proto == IPPROTO_ICMP)
e28b88a4 1397 sprintf(out, "icmp");
eb3b5696 1398 else if (ip_proto == IPPROTO_ICMPV6)
e28b88a4 1399 sprintf(out, "icmpv6");
30eb304e 1400 else
e28b88a4
JP
1401 sprintf(out, "%02x", ip_proto);
1402
1403 print_string(PRINT_ANY, "ip_proto", "\n ip_proto %s", out);
30eb304e
JP
1404 *p_ip_proto = ip_proto;
1405}
1406
e8bd3955 1407static void flower_print_ip_attr(const char *name, struct rtattr *key_attr,
6ea2c2b1
OG
1408 struct rtattr *mask_attr)
1409{
e28b88a4
JP
1410 SPRINT_BUF(namefrm);
1411 SPRINT_BUF(out);
1412 size_t done;
1413
6ea2c2b1
OG
1414 if (!key_attr)
1415 return;
1416
e8bd3955 1417 done = sprintf(out, "0x%x", rta_getattr_u8(key_attr));
e28b88a4
JP
1418 if (mask_attr)
1419 sprintf(out + done, "/%x", rta_getattr_u8(mask_attr));
1420
e8bd3955
KL
1421 print_string(PRINT_FP, NULL, "%s ", _SL_);
1422 sprintf(namefrm, "%s %%s", name);
e28b88a4 1423 print_string(PRINT_ANY, name, namefrm, out);
6ea2c2b1
OG
1424}
1425
e28b88a4 1426static void flower_print_matching_flags(char *name,
08f66c80 1427 enum flower_matching_flags type,
22a8f019
PB
1428 struct rtattr *attr,
1429 struct rtattr *mask_attr)
1430{
08f66c80
PB
1431 int i;
1432 int count = 0;
1433 __u32 mtf;
1434 __u32 mtf_mask;
1435
22a8f019
PB
1436 if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
1437 return;
1438
08f66c80
PB
1439 mtf = ntohl(rta_getattr_u32(attr));
1440 mtf_mask = ntohl(rta_getattr_u32(mask_attr));
1441
1442 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
1443 if (type != flags_str[i].type)
1444 continue;
1445 if (mtf_mask & flags_str[i].flag) {
e28b88a4
JP
1446 if (++count == 1) {
1447 print_string(PRINT_FP, NULL, "\n %s ", name);
1448 open_json_object(name);
1449 } else {
1450 print_string(PRINT_FP, NULL, "/", NULL);
1451 }
08f66c80 1452
e28b88a4
JP
1453 print_bool(PRINT_JSON, flags_str[i].string, NULL,
1454 mtf & flags_str[i].flag);
08f66c80 1455 if (mtf & flags_str[i].flag)
e28b88a4
JP
1456 print_string(PRINT_FP, NULL, "%s",
1457 flags_str[i].string);
08f66c80 1458 else
e28b88a4
JP
1459 print_string(PRINT_FP, NULL, "no%s",
1460 flags_str[i].string);
08f66c80
PB
1461 }
1462 }
e28b88a4
JP
1463 if (count)
1464 close_json_object();
22a8f019
PB
1465}
1466
e28b88a4 1467static void flower_print_ip_addr(char *name, __be16 eth_type,
30eb304e
JP
1468 struct rtattr *addr4_attr,
1469 struct rtattr *mask4_attr,
1470 struct rtattr *addr6_attr,
1471 struct rtattr *mask6_attr)
1472{
30eb304e
JP
1473 struct rtattr *addr_attr;
1474 struct rtattr *mask_attr;
e28b88a4
JP
1475 SPRINT_BUF(namefrm);
1476 SPRINT_BUF(out);
1477 size_t done;
30eb304e
JP
1478 int family;
1479 size_t len;
1480 int bits;
1481
1482 if (eth_type == htons(ETH_P_IP)) {
1483 family = AF_INET;
1484 addr_attr = addr4_attr;
1485 mask_attr = mask4_attr;
1486 len = 4;
1487 } else if (eth_type == htons(ETH_P_IPV6)) {
1488 family = AF_INET6;
1489 addr_attr = addr6_attr;
1490 mask_attr = mask6_attr;
1491 len = 16;
1492 } else {
1493 return;
1494 }
1495 if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
1496 return;
30eb304e
JP
1497 if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
1498 return;
e28b88a4 1499 done = sprintf(out, "%s", rt_addr_n2a_rta(family, addr_attr));
30eb304e
JP
1500 bits = __mask_bits(RTA_DATA(mask_attr), len);
1501 if (bits < 0)
e28b88a4 1502 sprintf(out + done, "/%s", rt_addr_n2a_rta(family, mask_attr));
30eb304e 1503 else if (bits < len * 8)
e28b88a4
JP
1504 sprintf(out + done, "/%d", bits);
1505
1506 sprintf(namefrm, "\n %s %%s", name);
1507 print_string(PRINT_ANY, name, namefrm, out);
30eb304e 1508}
e28b88a4 1509static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr,
f888f4e2
SH
1510 struct rtattr *mask_attr)
1511{
e28b88a4 1512 return flower_print_ip_addr(name, htons(ETH_P_IP),
f888f4e2
SH
1513 addr_attr, mask_attr, 0, 0);
1514}
30eb304e 1515
e28b88a4 1516static void flower_print_port(char *name, struct rtattr *attr)
30eb304e 1517{
e28b88a4
JP
1518 SPRINT_BUF(namefrm);
1519
1520 if (!attr)
1521 return;
1522
1523 sprintf(namefrm,"\n %s %%u", name);
0b01f088 1524 print_hu(PRINT_ANY, name, namefrm, rta_getattr_be16(attr));
30eb304e
JP
1525}
1526
8930840e
AN
1527static void flower_print_port_range(char *name, struct rtattr *min_attr,
1528 struct rtattr *max_attr)
1529{
1530 if (!min_attr || !max_attr)
1531 return;
1532
1533 if (is_json_context()) {
1534 open_json_object(name);
1535 print_hu(PRINT_JSON, "start", NULL, rta_getattr_be16(min_attr));
1536 print_hu(PRINT_JSON, "end", NULL, rta_getattr_be16(max_attr));
1537 close_json_object();
1538 } else {
1539 SPRINT_BUF(namefrm);
1540 SPRINT_BUF(out);
1541 size_t done;
1542
1543 done = sprintf(out, "%u", rta_getattr_be16(min_attr));
1544 sprintf(out + done, "-%u", rta_getattr_be16(max_attr));
1545 sprintf(namefrm, "\n %s %%s", name);
1546 print_string(PRINT_ANY, name, namefrm, out);
1547 }
1548}
1549
e8bd3955 1550static void flower_print_tcp_flags(const char *name, struct rtattr *flags_attr,
e28b88a4 1551 struct rtattr *mask_attr)
0c30d14d 1552{
e28b88a4
JP
1553 SPRINT_BUF(namefrm);
1554 SPRINT_BUF(out);
1555 size_t done;
1556
0c30d14d
JP
1557 if (!flags_attr)
1558 return;
e28b88a4 1559
e8bd3955 1560 done = sprintf(out, "0x%x", rta_getattr_be16(flags_attr));
e28b88a4 1561 if (mask_attr)
e8bd3955 1562 sprintf(out + done, "/%x", rta_getattr_be16(mask_attr));
e28b88a4 1563
e8bd3955
KL
1564 print_string(PRINT_FP, NULL, "%s ", _SL_);
1565 sprintf(namefrm, "%s %%s", name);
e28b88a4 1566 print_string(PRINT_ANY, name, namefrm, out);
0c30d14d
JP
1567}
1568
1569
e28b88a4 1570static void flower_print_key_id(const char *name, struct rtattr *attr)
bb9b63b1 1571{
e28b88a4
JP
1572 SPRINT_BUF(namefrm);
1573
1574 if (!attr)
1575 return;
1576
1577 sprintf(namefrm,"\n %s %%u", name);
1578 print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr));
bb9b63b1
AV
1579}
1580
56155d4d
PJV
1581static void flower_print_geneve_opts(const char *name, struct rtattr *attr,
1582 char *strbuf)
1583{
1584 struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1];
1585 int ii, data_len, offset = 0, slen = 0;
1586 struct rtattr *i = RTA_DATA(attr);
1587 int rem = RTA_PAYLOAD(attr);
1588 __u8 type, data_r[rem];
1589 char data[rem * 2 + 1];
1590 __u16 class;
1591
1592 open_json_array(PRINT_JSON, name);
1593 while (rem) {
1594 parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX, i, rem);
1595 class = rta_getattr_be16(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS]);
1596 type = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE]);
1597 data_len = RTA_PAYLOAD(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]);
1598 hexstring_n2a(RTA_DATA(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]),
1599 data_len, data, sizeof(data));
1600 hex2mem(data, data_r, data_len);
1601 offset += data_len + 20;
1602 rem -= data_len + 20;
1603 i = RTA_DATA(attr) + offset;
1604
1605 open_json_object(NULL);
1606 print_uint(PRINT_JSON, "class", NULL, class);
1607 print_uint(PRINT_JSON, "type", NULL, type);
1608 open_json_array(PRINT_JSON, "data");
1609 for (ii = 0; ii < data_len; ii++)
1610 print_uint(PRINT_JSON, NULL, NULL, data_r[ii]);
1611 close_json_array(PRINT_JSON, "data");
1612 close_json_object();
1613
1614 slen += sprintf(strbuf + slen, "%04x:%02x:%s",
1615 class, type, data);
1616 if (rem)
1617 slen += sprintf(strbuf + slen, ",");
1618 }
1619 close_json_array(PRINT_JSON, name);
1620}
1621
1622static void flower_print_geneve_parts(const char *name, struct rtattr *attr,
1623 char *key, char *mask)
1624{
1625 char *namefrm = "\n geneve_opt %s";
1626 char *key_token, *mask_token, *out;
1627 int len;
1628
1629 out = malloc(RTA_PAYLOAD(attr) * 4 + 3);
1630 if (!out)
1631 return;
1632
1633 len = 0;
1634 key_token = strsep(&key, ",");
1635 mask_token = strsep(&mask, ",");
1636 while (key_token) {
1637 len += sprintf(&out[len], "%s/%s,", key_token, mask_token);
1638 mask_token = strsep(&mask, ",");
1639 key_token = strsep(&key, ",");
1640 }
1641
1642 out[len - 1] = '\0';
1643 print_string(PRINT_FP, name, namefrm, out);
1644 free(out);
1645}
1646
1647static void flower_print_enc_opts(const char *name, struct rtattr *attr,
1648 struct rtattr *mask_attr)
1649{
1650 struct rtattr *key_tb[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1];
1651 struct rtattr *msk_tb[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1];
1652 char *key, *msk;
1653
1654 if (!attr)
1655 return;
1656
1657 key = malloc(RTA_PAYLOAD(attr) * 2 + 1);
1658 if (!key)
1659 return;
1660
1661 msk = malloc(RTA_PAYLOAD(attr) * 2 + 1);
1662 if (!msk)
1663 goto err_key_free;
1664
1665 parse_rtattr_nested(key_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, attr);
1666 flower_print_geneve_opts("geneve_opt_key",
1667 key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], key);
1668
1669 parse_rtattr_nested(msk_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, mask_attr);
1670 flower_print_geneve_opts("geneve_opt_mask",
1671 msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], msk);
1672
1673 flower_print_geneve_parts(name, attr, key, msk);
1674
1675 free(msk);
1676err_key_free:
1677 free(key);
1678}
1679
e28b88a4 1680static void flower_print_masked_u8(const char *name, struct rtattr *attr,
9d36e54f
SH
1681 struct rtattr *mask_attr,
1682 const char *(*value_to_str)(__u8 value))
f888f4e2 1683{
9d36e54f
SH
1684 const char *value_str = NULL;
1685 __u8 value, mask;
e28b88a4
JP
1686 SPRINT_BUF(namefrm);
1687 SPRINT_BUF(out);
1688 size_t done;
f888f4e2 1689
9d36e54f 1690 if (!attr)
f888f4e2
SH
1691 return;
1692
9d36e54f 1693 value = rta_getattr_u8(attr);
f888f4e2 1694 mask = mask_attr ? rta_getattr_u8(mask_attr) : UINT8_MAX;
9d36e54f
SH
1695 if (mask == UINT8_MAX && value_to_str)
1696 value_str = value_to_str(value);
f888f4e2 1697
9d36e54f 1698 if (value_str)
e28b88a4 1699 done = sprintf(out, "%s", value_str);
f888f4e2 1700 else
e28b88a4 1701 done = sprintf(out, "%d", value);
f888f4e2
SH
1702
1703 if (mask != UINT8_MAX)
e28b88a4
JP
1704 sprintf(out + done, "/%d", mask);
1705
1706 sprintf(namefrm,"\n %s %%s", name);
1707 print_string(PRINT_ANY, name, namefrm, out);
f888f4e2
SH
1708}
1709
e28b88a4 1710static void flower_print_u8(const char *name, struct rtattr *attr)
7638ee13 1711{
e28b88a4 1712 flower_print_masked_u8(name, attr, NULL, NULL);
7638ee13
BL
1713}
1714
e28b88a4 1715static void flower_print_u32(const char *name, struct rtattr *attr)
7638ee13 1716{
e28b88a4 1717 SPRINT_BUF(namefrm);
7638ee13
BL
1718
1719 if (!attr)
1720 return;
1721
e28b88a4
JP
1722 sprintf(namefrm,"\n %s %%u", name);
1723 print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr));
7638ee13
BL
1724}
1725
e28b88a4 1726static void flower_print_arp_op(const char *name,
9d36e54f
SH
1727 struct rtattr *op_attr,
1728 struct rtattr *mask_attr)
1729{
e28b88a4 1730 flower_print_masked_u8(name, op_attr, mask_attr,
9d36e54f
SH
1731 flower_print_arp_op_to_name);
1732}
1733
30eb304e
JP
1734static int flower_print_opt(struct filter_util *qu, FILE *f,
1735 struct rtattr *opt, __u32 handle)
1736{
1737 struct rtattr *tb[TCA_FLOWER_MAX + 1];
8930840e 1738 __be16 min_port_type, max_port_type;
6374961a 1739 int nl_type, nl_mask_type;
30eb304e
JP
1740 __be16 eth_type = 0;
1741 __u8 ip_proto = 0xff;
1742
1743 if (!opt)
1744 return 0;
1745
1746 parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
1747
1748 if (handle)
e28b88a4 1749 print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
30eb304e
JP
1750
1751 if (tb[TCA_FLOWER_CLASSID]) {
0d575c4d
AN
1752 __u32 h = rta_getattr_u32(tb[TCA_FLOWER_CLASSID]);
1753
1754 if (TC_H_MIN(h) < TC_H_MIN_PRIORITY ||
1755 TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) {
1756 SPRINT_BUF(b1);
e28b88a4
JP
1757 print_string(PRINT_ANY, "classid", "classid %s ",
1758 sprint_tc_classid(h, b1));
0d575c4d 1759 } else {
e28b88a4
JP
1760 print_uint(PRINT_ANY, "hw_tc", "hw_tc %u ",
1761 TC_H_MIN(h) - TC_H_MIN_PRIORITY);
0d575c4d 1762 }
30eb304e
JP
1763 }
1764
1765 if (tb[TCA_FLOWER_INDEV]) {
1766 struct rtattr *attr = tb[TCA_FLOWER_INDEV];
1767
e28b88a4
JP
1768 print_string(PRINT_ANY, "indev", "\n indev %s",
1769 rta_getattr_str(attr));
30eb304e
JP
1770 }
1771
e28b88a4
JP
1772 open_json_object("keys");
1773
745d9172
HHZ
1774 if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
1775 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
1776
e28b88a4
JP
1777 print_uint(PRINT_ANY, "vlan_id", "\n vlan_id %u",
1778 rta_getattr_u16(attr));
745d9172
HHZ
1779 }
1780
1781 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
1782 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
1783
e28b88a4
JP
1784 print_uint(PRINT_ANY, "vlan_prio", "\n vlan_prio %d",
1785 rta_getattr_u8(attr));
745d9172
HHZ
1786 }
1787
1f0a5dfd
JL
1788 if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
1789 SPRINT_BUF(buf);
1790 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE];
1791
1792 print_string(PRINT_ANY, "vlan_ethtype", "\n vlan_ethtype %s",
1793 ll_proto_n2a(rta_getattr_u16(attr),
1794 buf, sizeof(buf)));
1795 }
1796
1797 if (tb[TCA_FLOWER_KEY_CVLAN_ID]) {
1798 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ID];
1799
1800 print_uint(PRINT_ANY, "cvlan_id", "\n cvlan_id %u",
1801 rta_getattr_u16(attr));
1802 }
1803
1804 if (tb[TCA_FLOWER_KEY_CVLAN_PRIO]) {
1805 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_PRIO];
1806
1807 print_uint(PRINT_ANY, "cvlan_prio", "\n cvlan_prio %d",
1808 rta_getattr_u8(attr));
1809 }
1810
1811 if (tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE]) {
1812 SPRINT_BUF(buf);
1813 struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE];
1814
1815 print_string(PRINT_ANY, "cvlan_ethtype", "\n cvlan_ethtype %s",
1816 ll_proto_n2a(rta_getattr_u16(attr),
1817 buf, sizeof(buf)));
1818 }
1819
e28b88a4 1820 flower_print_eth_addr("dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
30eb304e 1821 tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
e28b88a4 1822 flower_print_eth_addr("src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
30eb304e
JP
1823 tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
1824
e28b88a4
JP
1825 flower_print_eth_type(&eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
1826 flower_print_ip_proto(&ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
30eb304e 1827
e28b88a4 1828 flower_print_ip_attr("ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
6ea2c2b1 1829 tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
e28b88a4 1830 flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
6ea2c2b1
OG
1831 tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
1832
e28b88a4
JP
1833 flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
1834 flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
1835 flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
1836 flower_print_u8("mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]);
7638ee13 1837
e28b88a4 1838 flower_print_ip_addr("dst_ip", eth_type,
30eb304e
JP
1839 tb[TCA_FLOWER_KEY_IPV4_DST],
1840 tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
1841 tb[TCA_FLOWER_KEY_IPV6_DST],
1842 tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
1843
e28b88a4 1844 flower_print_ip_addr("src_ip", eth_type,
30eb304e
JP
1845 tb[TCA_FLOWER_KEY_IPV4_SRC],
1846 tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
1847 tb[TCA_FLOWER_KEY_IPV6_SRC],
1848 tb[TCA_FLOWER_KEY_IPV6_SRC_MASK]);
1849
b2141de1 1850 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
6bd5b80c 1851 if (nl_type >= 0)
e28b88a4 1852 flower_print_port("dst_port", tb[nl_type]);
b2141de1 1853 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
6bd5b80c 1854 if (nl_type >= 0)
e28b88a4 1855 flower_print_port("src_port", tb[nl_type]);
30eb304e 1856
8930840e
AN
1857 if (!flower_port_range_attr_type(ip_proto, FLOWER_ENDPOINT_DST,
1858 &min_port_type, &max_port_type))
1859 flower_print_port_range("dst_port",
1860 tb[min_port_type], tb[max_port_type]);
1861
1862 if (!flower_port_range_attr_type(ip_proto, FLOWER_ENDPOINT_SRC,
1863 &min_port_type, &max_port_type))
1864 flower_print_port_range("src_port",
1865 tb[min_port_type], tb[max_port_type]);
1866
e28b88a4 1867 flower_print_tcp_flags("tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
0c30d14d
JP
1868 tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
1869
81f6e5a7
SH
1870 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1871 FLOWER_ICMP_FIELD_TYPE);
6374961a
SH
1872 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1873 FLOWER_ICMP_FIELD_TYPE);
1874 if (nl_type >= 0 && nl_mask_type >= 0)
e28b88a4 1875 flower_print_masked_u8("icmp_type", tb[nl_type],
6374961a
SH
1876 tb[nl_mask_type], NULL);
1877
81f6e5a7
SH
1878 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1879 FLOWER_ICMP_FIELD_CODE);
6374961a
SH
1880 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1881 FLOWER_ICMP_FIELD_CODE);
1882 if (nl_type >= 0 && nl_mask_type >= 0)
e28b88a4 1883 flower_print_masked_u8("icmp_code", tb[nl_type],
6374961a 1884 tb[nl_mask_type], NULL);
eb3b5696 1885
e28b88a4 1886 flower_print_ip4_addr("arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
f888f4e2 1887 tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
e28b88a4 1888 flower_print_ip4_addr("arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
f888f4e2 1889 tb[TCA_FLOWER_KEY_ARP_TIP_MASK]);
e28b88a4 1890 flower_print_arp_op("arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
f888f4e2 1891 tb[TCA_FLOWER_KEY_ARP_OP_MASK]);
e28b88a4 1892 flower_print_eth_addr("arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
f888f4e2 1893 tb[TCA_FLOWER_KEY_ARP_SHA_MASK]);
e28b88a4 1894 flower_print_eth_addr("arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
f888f4e2
SH
1895 tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
1896
e28b88a4 1897 flower_print_ip_addr("enc_dst_ip",
bb9b63b1
AV
1898 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
1899 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1900 tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
1901 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK],
1902 tb[TCA_FLOWER_KEY_ENC_IPV6_DST],
1903 tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
1904
e28b88a4 1905 flower_print_ip_addr("enc_src_ip",
bb9b63b1
AV
1906 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
1907 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1908 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
1909 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK],
1910 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC],
1911 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
1912
e28b88a4 1913 flower_print_key_id("enc_key_id", tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
bb9b63b1 1914
e28b88a4 1915 flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
41aa17ff 1916
761ec9e2
OG
1917 flower_print_ip_attr("enc_tos", tb[TCA_FLOWER_KEY_ENC_IP_TOS],
1918 tb[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]);
1919 flower_print_ip_attr("enc_ttl", tb[TCA_FLOWER_KEY_ENC_IP_TTL],
1920 tb[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]);
56155d4d
PJV
1921 flower_print_enc_opts("enc_opt", tb[TCA_FLOWER_KEY_ENC_OPTS],
1922 tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]);
761ec9e2 1923
e28b88a4 1924 flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS,
22a8f019
PB
1925 tb[TCA_FLOWER_KEY_FLAGS],
1926 tb[TCA_FLOWER_KEY_FLAGS_MASK]);
1927
e28b88a4
JP
1928 close_json_object();
1929
512caeb2 1930 if (tb[TCA_FLOWER_FLAGS]) {
cfcabf18
AV
1931 __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
1932
1933 if (flags & TCA_CLS_FLAGS_SKIP_HW)
e28b88a4 1934 print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true);
cfcabf18 1935 if (flags & TCA_CLS_FLAGS_SKIP_SW)
e28b88a4 1936 print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true);
e57285b8 1937
f6b498f9 1938 if (flags & TCA_CLS_FLAGS_IN_HW) {
e28b88a4 1939 print_bool(PRINT_ANY, "in_hw", "\n in_hw", true);
f6b498f9
VB
1940
1941 if (tb[TCA_FLOWER_IN_HW_COUNT]) {
1942 __u32 count = rta_getattr_u32(tb[TCA_FLOWER_IN_HW_COUNT]);
1943
1944 print_uint(PRINT_ANY, "in_hw_count",
1945 " in_hw_count %u", count);
1946 }
1947 }
e57285b8 1948 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
e28b88a4 1949 print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true);
cfcabf18
AV
1950 }
1951
512caeb2 1952 if (tb[TCA_FLOWER_ACT])
9e713525 1953 tc_print_action(f, tb[TCA_FLOWER_ACT], 0);
30eb304e
JP
1954
1955 return 0;
1956}
1957
1958struct filter_util flower_filter_util = {
1959 .id = "flower",
1960 .parse_fopt = flower_parse_opt,
1961 .print_fopt = flower_print_opt,
1962};