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