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