]> git.proxmox.com Git - mirror_iproute2.git/blob - tc/f_flower.c
Merge branch 'master' into net-next
[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 char ifname[IFNAMSIZ] = {};
633
634 NEXT_ARG();
635 strncpy(ifname, *argv, sizeof(ifname) - 1);
636 addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, ifname);
637 } else if (matches(*argv, "vlan_id") == 0) {
638 __u16 vid;
639
640 NEXT_ARG();
641 if (eth_type != htons(ETH_P_8021Q)) {
642 fprintf(stderr,
643 "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n");
644 return -1;
645 }
646 ret = get_u16(&vid, *argv, 10);
647 if (ret < 0 || vid & ~0xfff) {
648 fprintf(stderr, "Illegal \"vlan_id\"\n");
649 return -1;
650 }
651 addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid);
652 } else if (matches(*argv, "vlan_prio") == 0) {
653 __u8 vlan_prio;
654
655 NEXT_ARG();
656 if (eth_type != htons(ETH_P_8021Q)) {
657 fprintf(stderr,
658 "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n");
659 return -1;
660 }
661 ret = get_u8(&vlan_prio, *argv, 10);
662 if (ret < 0 || vlan_prio & ~0x7) {
663 fprintf(stderr, "Illegal \"vlan_prio\"\n");
664 return -1;
665 }
666 addattr8(n, MAX_MSG,
667 TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio);
668 } else if (matches(*argv, "vlan_ethtype") == 0) {
669 NEXT_ARG();
670 ret = flower_parse_vlan_eth_type(*argv, eth_type,
671 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
672 &vlan_ethtype, n);
673 if (ret < 0)
674 return -1;
675 } else if (matches(*argv, "dst_mac") == 0) {
676 NEXT_ARG();
677 ret = flower_parse_eth_addr(*argv,
678 TCA_FLOWER_KEY_ETH_DST,
679 TCA_FLOWER_KEY_ETH_DST_MASK,
680 n);
681 if (ret < 0) {
682 fprintf(stderr, "Illegal \"dst_mac\"\n");
683 return -1;
684 }
685 } else if (matches(*argv, "src_mac") == 0) {
686 NEXT_ARG();
687 ret = flower_parse_eth_addr(*argv,
688 TCA_FLOWER_KEY_ETH_SRC,
689 TCA_FLOWER_KEY_ETH_SRC_MASK,
690 n);
691 if (ret < 0) {
692 fprintf(stderr, "Illegal \"src_mac\"\n");
693 return -1;
694 }
695 } else if (matches(*argv, "ip_proto") == 0) {
696 NEXT_ARG();
697 ret = flower_parse_ip_proto(*argv, vlan_ethtype ?
698 vlan_ethtype : eth_type,
699 TCA_FLOWER_KEY_IP_PROTO,
700 &ip_proto, n);
701 if (ret < 0) {
702 fprintf(stderr, "Illegal \"ip_proto\"\n");
703 return -1;
704 }
705 } else if (matches(*argv, "ip_tos") == 0) {
706 NEXT_ARG();
707 ret = flower_parse_ip_tos_ttl(*argv,
708 TCA_FLOWER_KEY_IP_TOS,
709 TCA_FLOWER_KEY_IP_TOS_MASK,
710 n);
711 if (ret < 0) {
712 fprintf(stderr, "Illegal \"ip_tos\"\n");
713 return -1;
714 }
715 } else if (matches(*argv, "ip_ttl") == 0) {
716 NEXT_ARG();
717 ret = flower_parse_ip_tos_ttl(*argv,
718 TCA_FLOWER_KEY_IP_TTL,
719 TCA_FLOWER_KEY_IP_TTL_MASK,
720 n);
721 if (ret < 0) {
722 fprintf(stderr, "Illegal \"ip_ttl\"\n");
723 return -1;
724 }
725 } else if (matches(*argv, "dst_ip") == 0) {
726 NEXT_ARG();
727 ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
728 vlan_ethtype : eth_type,
729 TCA_FLOWER_KEY_IPV4_DST,
730 TCA_FLOWER_KEY_IPV4_DST_MASK,
731 TCA_FLOWER_KEY_IPV6_DST,
732 TCA_FLOWER_KEY_IPV6_DST_MASK,
733 n);
734 if (ret < 0) {
735 fprintf(stderr, "Illegal \"dst_ip\"\n");
736 return -1;
737 }
738 } else if (matches(*argv, "src_ip") == 0) {
739 NEXT_ARG();
740 ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
741 vlan_ethtype : eth_type,
742 TCA_FLOWER_KEY_IPV4_SRC,
743 TCA_FLOWER_KEY_IPV4_SRC_MASK,
744 TCA_FLOWER_KEY_IPV6_SRC,
745 TCA_FLOWER_KEY_IPV6_SRC_MASK,
746 n);
747 if (ret < 0) {
748 fprintf(stderr, "Illegal \"src_ip\"\n");
749 return -1;
750 }
751 } else if (matches(*argv, "dst_port") == 0) {
752 NEXT_ARG();
753 ret = flower_parse_port(*argv, ip_proto,
754 FLOWER_ENDPOINT_DST, n);
755 if (ret < 0) {
756 fprintf(stderr, "Illegal \"dst_port\"\n");
757 return -1;
758 }
759 } else if (matches(*argv, "src_port") == 0) {
760 NEXT_ARG();
761 ret = flower_parse_port(*argv, ip_proto,
762 FLOWER_ENDPOINT_SRC, n);
763 if (ret < 0) {
764 fprintf(stderr, "Illegal \"src_port\"\n");
765 return -1;
766 }
767 } else if (matches(*argv, "tcp_flags") == 0) {
768 NEXT_ARG();
769 ret = flower_parse_tcp_flags(*argv,
770 TCA_FLOWER_KEY_TCP_FLAGS,
771 TCA_FLOWER_KEY_TCP_FLAGS_MASK,
772 n);
773 if (ret < 0) {
774 fprintf(stderr, "Illegal \"tcp_flags\"\n");
775 return -1;
776 }
777 } else if (matches(*argv, "type") == 0) {
778 NEXT_ARG();
779 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
780 FLOWER_ICMP_FIELD_TYPE, n);
781 if (ret < 0) {
782 fprintf(stderr, "Illegal \"icmp type\"\n");
783 return -1;
784 }
785 } else if (matches(*argv, "code") == 0) {
786 NEXT_ARG();
787 ret = flower_parse_icmp(*argv, eth_type, ip_proto,
788 FLOWER_ICMP_FIELD_CODE, n);
789 if (ret < 0) {
790 fprintf(stderr, "Illegal \"icmp code\"\n");
791 return -1;
792 }
793 } else if (matches(*argv, "arp_tip") == 0) {
794 NEXT_ARG();
795 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
796 vlan_ethtype : eth_type,
797 TCA_FLOWER_KEY_ARP_TIP,
798 TCA_FLOWER_KEY_ARP_TIP_MASK,
799 n);
800 if (ret < 0) {
801 fprintf(stderr, "Illegal \"arp_tip\"\n");
802 return -1;
803 }
804 } else if (matches(*argv, "arp_sip") == 0) {
805 NEXT_ARG();
806 ret = flower_parse_arp_ip_addr(*argv, vlan_ethtype ?
807 vlan_ethtype : eth_type,
808 TCA_FLOWER_KEY_ARP_SIP,
809 TCA_FLOWER_KEY_ARP_SIP_MASK,
810 n);
811 if (ret < 0) {
812 fprintf(stderr, "Illegal \"arp_sip\"\n");
813 return -1;
814 }
815 } else if (matches(*argv, "arp_op") == 0) {
816 NEXT_ARG();
817 ret = flower_parse_arp_op(*argv, vlan_ethtype ?
818 vlan_ethtype : eth_type,
819 TCA_FLOWER_KEY_ARP_OP,
820 TCA_FLOWER_KEY_ARP_OP_MASK,
821 n);
822 if (ret < 0) {
823 fprintf(stderr, "Illegal \"arp_op\"\n");
824 return -1;
825 }
826 } else if (matches(*argv, "arp_tha") == 0) {
827 NEXT_ARG();
828 ret = flower_parse_eth_addr(*argv,
829 TCA_FLOWER_KEY_ARP_THA,
830 TCA_FLOWER_KEY_ARP_THA_MASK,
831 n);
832 if (ret < 0) {
833 fprintf(stderr, "Illegal \"arp_tha\"\n");
834 return -1;
835 }
836 } else if (matches(*argv, "arp_sha") == 0) {
837 NEXT_ARG();
838 ret = flower_parse_eth_addr(*argv,
839 TCA_FLOWER_KEY_ARP_SHA,
840 TCA_FLOWER_KEY_ARP_SHA_MASK,
841 n);
842 if (ret < 0) {
843 fprintf(stderr, "Illegal \"arp_sha\"\n");
844 return -1;
845 }
846 } else if (matches(*argv, "enc_dst_ip") == 0) {
847 NEXT_ARG();
848 ret = flower_parse_ip_addr(*argv, 0,
849 TCA_FLOWER_KEY_ENC_IPV4_DST,
850 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
851 TCA_FLOWER_KEY_ENC_IPV6_DST,
852 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
853 n);
854 if (ret < 0) {
855 fprintf(stderr, "Illegal \"enc_dst_ip\"\n");
856 return -1;
857 }
858 } else if (matches(*argv, "enc_src_ip") == 0) {
859 NEXT_ARG();
860 ret = flower_parse_ip_addr(*argv, 0,
861 TCA_FLOWER_KEY_ENC_IPV4_SRC,
862 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
863 TCA_FLOWER_KEY_ENC_IPV6_SRC,
864 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
865 n);
866 if (ret < 0) {
867 fprintf(stderr, "Illegal \"enc_src_ip\"\n");
868 return -1;
869 }
870 } else if (matches(*argv, "enc_key_id") == 0) {
871 NEXT_ARG();
872 ret = flower_parse_key_id(*argv,
873 TCA_FLOWER_KEY_ENC_KEY_ID, n);
874 if (ret < 0) {
875 fprintf(stderr, "Illegal \"enc_key_id\"\n");
876 return -1;
877 }
878 } else if (matches(*argv, "enc_dst_port") == 0) {
879 NEXT_ARG();
880 ret = flower_parse_enc_port(*argv,
881 TCA_FLOWER_KEY_ENC_UDP_DST_PORT, n);
882 if (ret < 0) {
883 fprintf(stderr, "Illegal \"enc_dst_port\"\n");
884 return -1;
885 }
886 } else if (matches(*argv, "action") == 0) {
887 NEXT_ARG();
888 ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n);
889 if (ret) {
890 fprintf(stderr, "Illegal \"action\"\n");
891 return -1;
892 }
893 continue;
894 } else if (strcmp(*argv, "help") == 0) {
895 explain();
896 return -1;
897 } else {
898 fprintf(stderr, "What is \"%s\"?\n", *argv);
899 explain();
900 return -1;
901 }
902 argc--; argv++;
903 }
904
905 parse_done:
906 ret = addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags);
907 if (ret)
908 return ret;
909
910 if (mtf_mask) {
911 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf));
912 if (ret)
913 return ret;
914
915 ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask));
916 if (ret)
917 return ret;
918 }
919
920 if (eth_type != htons(ETH_P_ALL)) {
921 ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
922 if (ret)
923 return ret;
924 }
925
926 tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail;
927
928 return 0;
929 }
930
931 static int __mask_bits(char *addr, size_t len)
932 {
933 int bits = 0;
934 bool hole = false;
935 int i;
936 int j;
937
938 for (i = 0; i < len; i++, addr++) {
939 for (j = 7; j >= 0; j--) {
940 if (((*addr) >> j) & 0x1) {
941 if (hole)
942 return -1;
943 bits++;
944 } else if (bits) {
945 hole = true;
946 } else{
947 return -1;
948 }
949 }
950 }
951 return bits;
952 }
953
954 static void flower_print_eth_addr(FILE *f, char *name,
955 struct rtattr *addr_attr,
956 struct rtattr *mask_attr)
957 {
958 SPRINT_BUF(b1);
959 int bits;
960
961 if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN)
962 return;
963 fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN,
964 0, b1, sizeof(b1)));
965 if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN)
966 return;
967 bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN);
968 if (bits < 0)
969 fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN,
970 0, b1, sizeof(b1)));
971 else if (bits < ETH_ALEN * 8)
972 fprintf(f, "/%d", bits);
973 }
974
975 static void flower_print_eth_type(FILE *f, __be16 *p_eth_type,
976 struct rtattr *eth_type_attr)
977 {
978 __be16 eth_type;
979
980 if (!eth_type_attr)
981 return;
982
983 eth_type = rta_getattr_u16(eth_type_attr);
984 fprintf(f, "\n eth_type ");
985 if (eth_type == htons(ETH_P_IP))
986 fprintf(f, "ipv4");
987 else if (eth_type == htons(ETH_P_IPV6))
988 fprintf(f, "ipv6");
989 else if (eth_type == htons(ETH_P_ARP))
990 fprintf(f, "arp");
991 else if (eth_type == htons(ETH_P_RARP))
992 fprintf(f, "rarp");
993 else
994 fprintf(f, "%04x", ntohs(eth_type));
995 *p_eth_type = eth_type;
996 }
997
998 static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto,
999 struct rtattr *ip_proto_attr)
1000 {
1001 __u8 ip_proto;
1002
1003 if (!ip_proto_attr)
1004 return;
1005
1006 ip_proto = rta_getattr_u8(ip_proto_attr);
1007 fprintf(f, "\n ip_proto ");
1008 if (ip_proto == IPPROTO_TCP)
1009 fprintf(f, "tcp");
1010 else if (ip_proto == IPPROTO_UDP)
1011 fprintf(f, "udp");
1012 else if (ip_proto == IPPROTO_SCTP)
1013 fprintf(f, "sctp");
1014 else if (ip_proto == IPPROTO_ICMP)
1015 fprintf(f, "icmp");
1016 else if (ip_proto == IPPROTO_ICMPV6)
1017 fprintf(f, "icmpv6");
1018 else
1019 fprintf(f, "%02x", ip_proto);
1020 *p_ip_proto = ip_proto;
1021 }
1022
1023 static void flower_print_ip_attr(FILE *f, char *name,
1024 struct rtattr *key_attr,
1025 struct rtattr *mask_attr)
1026 {
1027 if (!key_attr)
1028 return;
1029
1030 fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr));
1031 if (!mask_attr)
1032 return;
1033 fprintf(f, "/%x", rta_getattr_u8(mask_attr));
1034 }
1035
1036 static void flower_print_matching_flags(FILE *f, char *name,
1037 enum flower_matching_flags type,
1038 struct rtattr *attr,
1039 struct rtattr *mask_attr)
1040 {
1041 int i;
1042 int count = 0;
1043 __u32 mtf;
1044 __u32 mtf_mask;
1045
1046 if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
1047 return;
1048
1049 mtf = ntohl(rta_getattr_u32(attr));
1050 mtf_mask = ntohl(rta_getattr_u32(mask_attr));
1051
1052 for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
1053 if (type != flags_str[i].type)
1054 continue;
1055 if (mtf_mask & flags_str[i].flag) {
1056 if (++count == 1)
1057 fprintf(f, "\n %s ", name);
1058 else
1059 fprintf(f, "/");
1060
1061 if (mtf & flags_str[i].flag)
1062 fprintf(f, "%s", flags_str[i].string);
1063 else
1064 fprintf(f, "no%s", flags_str[i].string);
1065 }
1066 }
1067 }
1068
1069 static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
1070 struct rtattr *addr4_attr,
1071 struct rtattr *mask4_attr,
1072 struct rtattr *addr6_attr,
1073 struct rtattr *mask6_attr)
1074 {
1075 struct rtattr *addr_attr;
1076 struct rtattr *mask_attr;
1077 int family;
1078 size_t len;
1079 int bits;
1080
1081 if (eth_type == htons(ETH_P_IP)) {
1082 family = AF_INET;
1083 addr_attr = addr4_attr;
1084 mask_attr = mask4_attr;
1085 len = 4;
1086 } else if (eth_type == htons(ETH_P_IPV6)) {
1087 family = AF_INET6;
1088 addr_attr = addr6_attr;
1089 mask_attr = mask6_attr;
1090 len = 16;
1091 } else {
1092 return;
1093 }
1094 if (!addr_attr || RTA_PAYLOAD(addr_attr) != len)
1095 return;
1096 fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr));
1097 if (!mask_attr || RTA_PAYLOAD(mask_attr) != len)
1098 return;
1099 bits = __mask_bits(RTA_DATA(mask_attr), len);
1100 if (bits < 0)
1101 fprintf(f, "/%s", rt_addr_n2a_rta(family, mask_attr));
1102 else if (bits < len * 8)
1103 fprintf(f, "/%d", bits);
1104 }
1105 static void flower_print_ip4_addr(FILE *f, char *name,
1106 struct rtattr *addr_attr,
1107 struct rtattr *mask_attr)
1108 {
1109 return flower_print_ip_addr(f, name, htons(ETH_P_IP),
1110 addr_attr, mask_attr, 0, 0);
1111 }
1112
1113 static void flower_print_port(FILE *f, char *name, struct rtattr *attr)
1114 {
1115 if (attr)
1116 fprintf(f, "\n %s %d", name, rta_getattr_be16(attr));
1117 }
1118
1119 static void flower_print_tcp_flags(FILE *f, char *name,
1120 struct rtattr *flags_attr,
1121 struct rtattr *mask_attr)
1122 {
1123 if (!flags_attr)
1124 return;
1125 fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr));
1126 if (!mask_attr)
1127 return;
1128 fprintf(f, "/%x", rta_getattr_be16(mask_attr));
1129 }
1130
1131
1132 static void flower_print_key_id(FILE *f, const char *name,
1133 struct rtattr *attr)
1134 {
1135 if (attr)
1136 fprintf(f, "\n %s %d", name, rta_getattr_be32(attr));
1137 }
1138
1139 static void flower_print_masked_u8(FILE *f, const char *name,
1140 struct rtattr *attr,
1141 struct rtattr *mask_attr,
1142 const char *(*value_to_str)(__u8 value))
1143 {
1144 const char *value_str = NULL;
1145 __u8 value, mask;
1146
1147 if (!attr)
1148 return;
1149
1150 value = rta_getattr_u8(attr);
1151 mask = mask_attr ? rta_getattr_u8(mask_attr) : UINT8_MAX;
1152 if (mask == UINT8_MAX && value_to_str)
1153 value_str = value_to_str(value);
1154
1155 fprintf(f, "\n %s ", name);
1156
1157 if (value_str)
1158 fputs(value_str, f);
1159 else
1160 fprintf(f, "%d", value);
1161
1162 if (mask != UINT8_MAX)
1163 fprintf(f, "/%d", mask);
1164 }
1165
1166 static void flower_print_arp_op(FILE *f, const char *name,
1167 struct rtattr *op_attr,
1168 struct rtattr *mask_attr)
1169 {
1170 flower_print_masked_u8(f, name, op_attr, mask_attr,
1171 flower_print_arp_op_to_name);
1172 }
1173
1174 static int flower_print_opt(struct filter_util *qu, FILE *f,
1175 struct rtattr *opt, __u32 handle)
1176 {
1177 struct rtattr *tb[TCA_FLOWER_MAX + 1];
1178 int nl_type, nl_mask_type;
1179 __be16 eth_type = 0;
1180 __u8 ip_proto = 0xff;
1181
1182 if (!opt)
1183 return 0;
1184
1185 parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
1186
1187 if (handle)
1188 fprintf(f, "handle 0x%x ", handle);
1189
1190 if (tb[TCA_FLOWER_CLASSID]) {
1191 SPRINT_BUF(b1);
1192 fprintf(f, "classid %s ",
1193 sprint_tc_classid(rta_getattr_u32(tb[TCA_FLOWER_CLASSID]),
1194 b1));
1195 }
1196
1197 if (tb[TCA_FLOWER_INDEV]) {
1198 struct rtattr *attr = tb[TCA_FLOWER_INDEV];
1199
1200 fprintf(f, "\n indev %s", rta_getattr_str(attr));
1201 }
1202
1203 if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
1204 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
1205
1206 fprintf(f, "\n vlan_id %d", rta_getattr_u16(attr));
1207 }
1208
1209 if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
1210 struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
1211
1212 fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr));
1213 }
1214
1215 flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
1216 tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
1217 flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
1218 tb[TCA_FLOWER_KEY_ETH_SRC_MASK]);
1219
1220 flower_print_eth_type(f, &eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
1221 flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
1222
1223 flower_print_ip_attr(f, "ip_tos", tb[TCA_FLOWER_KEY_IP_TOS],
1224 tb[TCA_FLOWER_KEY_IP_TOS_MASK]);
1225 flower_print_ip_attr(f, "ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
1226 tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
1227
1228 flower_print_ip_addr(f, "dst_ip", eth_type,
1229 tb[TCA_FLOWER_KEY_IPV4_DST],
1230 tb[TCA_FLOWER_KEY_IPV4_DST_MASK],
1231 tb[TCA_FLOWER_KEY_IPV6_DST],
1232 tb[TCA_FLOWER_KEY_IPV6_DST_MASK]);
1233
1234 flower_print_ip_addr(f, "src_ip", eth_type,
1235 tb[TCA_FLOWER_KEY_IPV4_SRC],
1236 tb[TCA_FLOWER_KEY_IPV4_SRC_MASK],
1237 tb[TCA_FLOWER_KEY_IPV6_SRC],
1238 tb[TCA_FLOWER_KEY_IPV6_SRC_MASK]);
1239
1240 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST);
1241 if (nl_type >= 0)
1242 flower_print_port(f, "dst_port", tb[nl_type]);
1243 nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC);
1244 if (nl_type >= 0)
1245 flower_print_port(f, "src_port", tb[nl_type]);
1246
1247 flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
1248 tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
1249
1250 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1251 FLOWER_ICMP_FIELD_TYPE);
1252 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1253 FLOWER_ICMP_FIELD_TYPE);
1254 if (nl_type >= 0 && nl_mask_type >= 0)
1255 flower_print_masked_u8(f, "icmp_type", tb[nl_type],
1256 tb[nl_mask_type], NULL);
1257
1258 nl_type = flower_icmp_attr_type(eth_type, ip_proto,
1259 FLOWER_ICMP_FIELD_CODE);
1260 nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
1261 FLOWER_ICMP_FIELD_CODE);
1262 if (nl_type >= 0 && nl_mask_type >= 0)
1263 flower_print_masked_u8(f, "icmp_code", tb[nl_type],
1264 tb[nl_mask_type], NULL);
1265
1266 flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
1267 tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
1268 flower_print_ip4_addr(f, "arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
1269 tb[TCA_FLOWER_KEY_ARP_TIP_MASK]);
1270 flower_print_arp_op(f, "arp_op", tb[TCA_FLOWER_KEY_ARP_OP],
1271 tb[TCA_FLOWER_KEY_ARP_OP_MASK]);
1272 flower_print_eth_addr(f, "arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA],
1273 tb[TCA_FLOWER_KEY_ARP_SHA_MASK]);
1274 flower_print_eth_addr(f, "arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
1275 tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
1276
1277 flower_print_ip_addr(f, "enc_dst_ip",
1278 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
1279 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1280 tb[TCA_FLOWER_KEY_ENC_IPV4_DST],
1281 tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK],
1282 tb[TCA_FLOWER_KEY_ENC_IPV6_DST],
1283 tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
1284
1285 flower_print_ip_addr(f, "enc_src_ip",
1286 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ?
1287 htons(ETH_P_IP) : htons(ETH_P_IPV6),
1288 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC],
1289 tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK],
1290 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC],
1291 tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
1292
1293 flower_print_key_id(f, "enc_key_id",
1294 tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
1295
1296 flower_print_port(f, "enc_dst_port",
1297 tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
1298
1299 flower_print_matching_flags(f, "ip_flags",
1300 FLOWER_IP_FLAGS,
1301 tb[TCA_FLOWER_KEY_FLAGS],
1302 tb[TCA_FLOWER_KEY_FLAGS_MASK]);
1303
1304 if (tb[TCA_FLOWER_FLAGS]) {
1305 __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
1306
1307 if (flags & TCA_CLS_FLAGS_SKIP_HW)
1308 fprintf(f, "\n skip_hw");
1309 if (flags & TCA_CLS_FLAGS_SKIP_SW)
1310 fprintf(f, "\n skip_sw");
1311
1312 if (flags & TCA_CLS_FLAGS_IN_HW)
1313 fprintf(f, "\n in_hw");
1314 else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
1315 fprintf(f, "\n not_in_hw");
1316 }
1317
1318 if (tb[TCA_FLOWER_ACT])
1319 tc_print_action(f, tb[TCA_FLOWER_ACT]);
1320
1321 return 0;
1322 }
1323
1324 struct filter_util flower_filter_util = {
1325 .id = "flower",
1326 .parse_fopt = flower_parse_opt,
1327 .print_fopt = flower_print_opt,
1328 };