2 * f_flower.c Flower Classifier
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.
9 * Authors: Jiri Pirko <jiri@resnulli.us>
17 #include <linux/if_arp.h>
18 #include <linux/if_ether.h>
20 #include <linux/tc_act/tc_vlan.h>
21 #include <linux/mpls.h>
27 enum flower_matching_flags
{
31 enum flower_endpoint
{
36 enum flower_icmp_field
{
37 FLOWER_ICMP_FIELD_TYPE
,
38 FLOWER_ICMP_FIELD_CODE
41 static void explain(void)
44 "Usage: ... flower [ MATCH-LIST ] [ verbose ]\n"
45 " [ skip_sw | skip_hw ]\n"
46 " [ action ACTION-SPEC ] [ classid CLASSID ]\n"
48 "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n"
49 " MATCH := { indev DEV-NAME |\n"
51 " vlan_prio PRIORITY |\n"
52 " vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
54 " cvlan_prio PRIORITY |\n"
55 " cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
56 " dst_mac MASKED-LLADDR |\n"
57 " src_mac MASKED-LLADDR |\n"
58 " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
59 " ip_tos MASKED-IP_TOS |\n"
60 " ip_ttl MASKED-IP_TTL |\n"
61 " mpls_label LABEL |\n"
67 " dst_port PORT-NUMBER |\n"
68 " src_port PORT-NUMBER |\n"
69 " tcp_flags MASKED-TCP_FLAGS |\n"
70 " type MASKED-ICMP-TYPE |\n"
71 " code MASKED-ICMP-CODE |\n"
72 " arp_tip IPV4-PREFIX |\n"
73 " arp_sip IPV4-PREFIX |\n"
74 " arp_op [ request | reply | OP ] |\n"
75 " arp_tha MASKED-LLADDR |\n"
76 " arp_sha MASKED-LLADDR |\n"
77 " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
78 " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
79 " enc_key_id [ KEY-ID ] |\n"
80 " enc_tos MASKED-IP_TOS |\n"
81 " enc_ttl MASKED-IP_TTL |\n"
82 " ip_flags IP-FLAGS | \n"
83 " enc_dst_port [ port_number ] }\n"
84 " FILTERID := X:Y:Z\n"
85 " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
86 " ACTION-SPEC := ... look at individual actions\n"
88 "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
89 "NOTE: There can be only used one mask per one prio. If user needs\n"
90 " to specify different mask, he has to use different prio.\n");
93 static int flower_parse_eth_addr(char *str
, int addr_type
, int mask_type
,
97 char addr
[ETH_ALEN
], *slash
;
99 slash
= strchr(str
, '/');
103 ret
= ll_addr_a2n(addr
, sizeof(addr
), str
);
106 addattr_l(n
, MAX_MSG
, addr_type
, addr
, sizeof(addr
));
111 if (!get_unsigned(&bits
, slash
+ 1, 10)) {
114 /* Extra 16 bit shift to push mac address into
115 * high bits of uint64_t
117 mask
= htonll(0xffffffffffffULL
<< (16 + 48 - bits
));
118 memcpy(addr
, &mask
, ETH_ALEN
);
120 ret
= ll_addr_a2n(addr
, sizeof(addr
), slash
+ 1);
125 memset(addr
, 0xff, ETH_ALEN
);
127 addattr_l(n
, MAX_MSG
, mask_type
, addr
, sizeof(addr
));
136 static bool eth_type_vlan(__be16 ethertype
)
138 return ethertype
== htons(ETH_P_8021Q
) ||
139 ethertype
== htons(ETH_P_8021AD
);
142 static int flower_parse_vlan_eth_type(char *str
, __be16 eth_type
, int type
,
143 __be16
*p_vlan_eth_type
,
146 __be16 vlan_eth_type
;
148 if (!eth_type_vlan(eth_type
)) {
149 fprintf(stderr
, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n",
150 type
== TCA_FLOWER_KEY_VLAN_ETH_TYPE
? "vlan_ethtype" : "cvlan_ethtype");
154 if (ll_proto_a2n(&vlan_eth_type
, str
))
155 invarg("invalid vlan_ethtype", str
);
156 addattr16(n
, MAX_MSG
, type
, vlan_eth_type
);
157 *p_vlan_eth_type
= vlan_eth_type
;
161 struct flag_to_string
{
163 enum flower_matching_flags type
;
167 static struct flag_to_string flags_str
[] = {
168 { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT
, FLOWER_IP_FLAGS
, "frag" },
169 { TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST
, FLOWER_IP_FLAGS
, "firstfrag" },
172 static int flower_parse_matching_flags(char *str
,
173 enum flower_matching_flags type
,
174 __u32
*mtf
, __u32
*mtf_mask
)
181 token
= strtok(str
, "/");
184 if (!strncmp(token
, "no", 2)) {
191 for (i
= 0; i
< ARRAY_SIZE(flags_str
); i
++) {
192 if (type
!= flags_str
[i
].type
)
195 if (!strcmp(token
, flags_str
[i
].string
)) {
197 *mtf
&= ~flags_str
[i
].flag
;
199 *mtf
|= flags_str
[i
].flag
;
201 *mtf_mask
|= flags_str
[i
].flag
;
209 token
= strtok(NULL
, "/");
215 static int flower_parse_ip_proto(char *str
, __be16 eth_type
, int type
,
216 __u8
*p_ip_proto
, struct nlmsghdr
*n
)
221 if (eth_type
!= htons(ETH_P_IP
) && eth_type
!= htons(ETH_P_IPV6
))
224 if (matches(str
, "tcp") == 0) {
225 ip_proto
= IPPROTO_TCP
;
226 } else if (matches(str
, "udp") == 0) {
227 ip_proto
= IPPROTO_UDP
;
228 } else if (matches(str
, "sctp") == 0) {
229 ip_proto
= IPPROTO_SCTP
;
230 } else if (matches(str
, "icmp") == 0) {
231 if (eth_type
!= htons(ETH_P_IP
))
233 ip_proto
= IPPROTO_ICMP
;
234 } else if (matches(str
, "icmpv6") == 0) {
235 if (eth_type
!= htons(ETH_P_IPV6
))
237 ip_proto
= IPPROTO_ICMPV6
;
239 ret
= get_u8(&ip_proto
, str
, 16);
243 addattr8(n
, MAX_MSG
, type
, ip_proto
);
244 *p_ip_proto
= ip_proto
;
248 fprintf(stderr
, "Illegal \"eth_type\" for ip proto\n");
252 static int __flower_parse_ip_addr(char *str
, int family
,
253 int addr4_type
, int mask4_type
,
254 int addr6_type
, int mask6_type
,
262 ret
= get_prefix(&addr
, str
, family
);
266 if (family
&& (addr
.family
!= family
)) {
267 fprintf(stderr
, "Illegal \"eth_type\" for ip address\n");
271 addattr_l(n
, MAX_MSG
, addr
.family
== AF_INET
? addr4_type
: addr6_type
,
272 addr
.data
, addr
.bytelen
);
274 memset(addr
.data
, 0xff, addr
.bytelen
);
276 for (i
= 0; i
< addr
.bytelen
/ 4; i
++) {
279 } else if (bits
/ 32 >= 1) {
282 addr
.data
[i
] <<= 32 - bits
;
283 addr
.data
[i
] = htonl(addr
.data
[i
]);
288 addattr_l(n
, MAX_MSG
, addr
.family
== AF_INET
? mask4_type
: mask6_type
,
289 addr
.data
, addr
.bytelen
);
294 static int flower_parse_ip_addr(char *str
, __be16 eth_type
,
295 int addr4_type
, int mask4_type
,
296 int addr6_type
, int mask6_type
,
301 if (eth_type
== htons(ETH_P_IP
)) {
303 } else if (eth_type
== htons(ETH_P_IPV6
)) {
305 } else if (!eth_type
) {
311 return __flower_parse_ip_addr(str
, family
, addr4_type
, mask4_type
,
312 addr6_type
, mask6_type
, n
);
315 static bool flower_eth_type_arp(__be16 eth_type
)
317 return eth_type
== htons(ETH_P_ARP
) || eth_type
== htons(ETH_P_RARP
);
320 static int flower_parse_arp_ip_addr(char *str
, __be16 eth_type
,
321 int addr_type
, int mask_type
,
324 if (!flower_eth_type_arp(eth_type
))
327 return __flower_parse_ip_addr(str
, AF_INET
, addr_type
, mask_type
,
328 TCA_FLOWER_UNSPEC
, TCA_FLOWER_UNSPEC
, n
);
331 static int flower_parse_u8(char *str
, int value_type
, int mask_type
,
332 int (*value_from_name
)(const char *str
,
334 bool (*value_validate
)(__u8 value
),
341 slash
= strchr(str
, '/');
345 ret
= value_from_name
? value_from_name(str
, &value
) : -1;
347 ret
= get_u8(&value
, str
, 10);
352 if (value_validate
&& !value_validate(value
))
356 ret
= get_u8(&mask
, slash
+ 1, 10);
364 addattr8(n
, MAX_MSG
, value_type
, value
);
365 addattr8(n
, MAX_MSG
, mask_type
, mask
);
374 static const char *flower_print_arp_op_to_name(__u8 op
)
386 static int flower_arp_op_from_name(const char *name
, __u8
*op
)
388 if (!strcmp(name
, "request"))
390 else if (!strcmp(name
, "reply"))
398 static bool flow_arp_op_validate(__u8 op
)
400 return !op
|| op
== ARPOP_REQUEST
|| op
== ARPOP_REPLY
;
403 static int flower_parse_arp_op(char *str
, __be16 eth_type
,
404 int op_type
, int mask_type
,
407 if (!flower_eth_type_arp(eth_type
))
410 return flower_parse_u8(str
, op_type
, mask_type
, flower_arp_op_from_name
,
411 flow_arp_op_validate
, n
);
414 static int flower_icmp_attr_type(__be16 eth_type
, __u8 ip_proto
,
415 enum flower_icmp_field field
)
417 if (eth_type
== htons(ETH_P_IP
) && ip_proto
== IPPROTO_ICMP
)
418 return field
== FLOWER_ICMP_FIELD_CODE
?
419 TCA_FLOWER_KEY_ICMPV4_CODE
:
420 TCA_FLOWER_KEY_ICMPV4_TYPE
;
421 else if (eth_type
== htons(ETH_P_IPV6
) && ip_proto
== IPPROTO_ICMPV6
)
422 return field
== FLOWER_ICMP_FIELD_CODE
?
423 TCA_FLOWER_KEY_ICMPV6_CODE
:
424 TCA_FLOWER_KEY_ICMPV6_TYPE
;
429 static int flower_icmp_attr_mask_type(__be16 eth_type
, __u8 ip_proto
,
430 enum flower_icmp_field field
)
432 if (eth_type
== htons(ETH_P_IP
) && ip_proto
== IPPROTO_ICMP
)
433 return field
== FLOWER_ICMP_FIELD_CODE
?
434 TCA_FLOWER_KEY_ICMPV4_CODE_MASK
:
435 TCA_FLOWER_KEY_ICMPV4_TYPE_MASK
;
436 else if (eth_type
== htons(ETH_P_IPV6
) && ip_proto
== IPPROTO_ICMPV6
)
437 return field
== FLOWER_ICMP_FIELD_CODE
?
438 TCA_FLOWER_KEY_ICMPV6_CODE_MASK
:
439 TCA_FLOWER_KEY_ICMPV6_TYPE_MASK
;
444 static int flower_parse_icmp(char *str
, __u16 eth_type
, __u8 ip_proto
,
445 enum flower_icmp_field field
, struct nlmsghdr
*n
)
447 int value_type
, mask_type
;
449 value_type
= flower_icmp_attr_type(eth_type
, ip_proto
, field
);
450 mask_type
= flower_icmp_attr_mask_type(eth_type
, ip_proto
, field
);
451 if (value_type
< 0 || mask_type
< 0)
454 return flower_parse_u8(str
, value_type
, mask_type
, NULL
, NULL
, n
);
457 static int flower_port_attr_type(__u8 ip_proto
, enum flower_endpoint endpoint
)
459 if (ip_proto
== IPPROTO_TCP
)
460 return endpoint
== FLOWER_ENDPOINT_SRC
?
461 TCA_FLOWER_KEY_TCP_SRC
:
462 TCA_FLOWER_KEY_TCP_DST
;
463 else if (ip_proto
== IPPROTO_UDP
)
464 return endpoint
== FLOWER_ENDPOINT_SRC
?
465 TCA_FLOWER_KEY_UDP_SRC
:
466 TCA_FLOWER_KEY_UDP_DST
;
467 else if (ip_proto
== IPPROTO_SCTP
)
468 return endpoint
== FLOWER_ENDPOINT_SRC
?
469 TCA_FLOWER_KEY_SCTP_SRC
:
470 TCA_FLOWER_KEY_SCTP_DST
;
475 static int flower_parse_port(char *str
, __u8 ip_proto
,
476 enum flower_endpoint endpoint
,
483 type
= flower_port_attr_type(ip_proto
, endpoint
);
487 ret
= get_be16(&port
, str
, 10);
491 addattr16(n
, MAX_MSG
, type
, port
);
496 #define TCP_FLAGS_MAX_MASK 0xfff
498 static int flower_parse_tcp_flags(char *str
, int flags_type
, int mask_type
,
505 slash
= strchr(str
, '/');
509 ret
= get_u16(&flags
, str
, 16);
510 if (ret
< 0 || flags
& ~TCP_FLAGS_MAX_MASK
)
513 addattr16(n
, MAX_MSG
, flags_type
, htons(flags
));
516 ret
= get_u16(&flags
, slash
+ 1, 16);
517 if (ret
< 0 || flags
& ~TCP_FLAGS_MAX_MASK
)
520 flags
= TCP_FLAGS_MAX_MASK
;
522 addattr16(n
, MAX_MSG
, mask_type
, htons(flags
));
531 static int flower_parse_ip_tos_ttl(char *str
, int key_type
, int mask_type
,
538 slash
= strchr(str
, '/');
542 ret
= get_u8(&tos_ttl
, str
, 10);
544 ret
= get_u8(&tos_ttl
, str
, 16);
548 addattr8(n
, MAX_MSG
, key_type
, tos_ttl
);
551 ret
= get_u8(&tos_ttl
, slash
+ 1, 16);
557 addattr8(n
, MAX_MSG
, mask_type
, tos_ttl
);
566 static int flower_parse_key_id(const char *str
, int type
, struct nlmsghdr
*n
)
571 ret
= get_be32(&key_id
, str
, 10);
573 addattr32(n
, MAX_MSG
, type
, key_id
);
578 static int flower_parse_enc_port(char *str
, int type
, struct nlmsghdr
*n
)
583 ret
= get_be16(&port
, str
, 10);
587 addattr16(n
, MAX_MSG
, type
, port
);
592 static int flower_parse_opt(struct filter_util
*qu
, char *handle
,
593 int argc
, char **argv
, struct nlmsghdr
*n
)
596 struct tcmsg
*t
= NLMSG_DATA(n
);
598 __be16 eth_type
= TC_H_MIN(t
->tcm_info
);
599 __be16 vlan_ethtype
= 0;
600 __be16 cvlan_ethtype
= 0;
601 __u8 ip_proto
= 0xff;
607 ret
= get_u32(&t
->tcm_handle
, handle
, 0);
609 fprintf(stderr
, "Illegal \"handle\"\n");
614 tail
= (struct rtattr
*) (((void *) n
) + NLMSG_ALIGN(n
->nlmsg_len
));
615 addattr_l(n
, MAX_MSG
, TCA_OPTIONS
, NULL
, 0);
618 /*at minimal we will match all ethertype packets */
623 if (matches(*argv
, "classid") == 0 ||
624 matches(*argv
, "flowid") == 0) {
628 ret
= get_tc_classid(&handle
, *argv
);
630 fprintf(stderr
, "Illegal \"classid\"\n");
633 addattr_l(n
, MAX_MSG
, TCA_FLOWER_CLASSID
, &handle
, 4);
634 } else if (matches(*argv
, "hw_tc") == 0) {
640 tc
= strtoul(*argv
, &end
, 0);
642 fprintf(stderr
, "Illegal TC index\n");
645 if (tc
>= TC_QOPT_MAX_QUEUE
) {
646 fprintf(stderr
, "TC index exceeds max range\n");
649 handle
= TC_H_MAKE(TC_H_MAJ(t
->tcm_parent
),
650 TC_H_MIN(tc
+ TC_H_MIN_PRIORITY
));
651 addattr_l(n
, MAX_MSG
, TCA_FLOWER_CLASSID
, &handle
,
653 } else if (matches(*argv
, "ip_flags") == 0) {
655 ret
= flower_parse_matching_flags(*argv
,
660 fprintf(stderr
, "Illegal \"ip_flags\"\n");
663 } else if (matches(*argv
, "verbose") == 0) {
664 flags
|= TCA_CLS_FLAGS_VERBOSE
;
665 } else if (matches(*argv
, "skip_hw") == 0) {
666 flags
|= TCA_CLS_FLAGS_SKIP_HW
;
667 } else if (matches(*argv
, "skip_sw") == 0) {
668 flags
|= TCA_CLS_FLAGS_SKIP_SW
;
669 } else if (matches(*argv
, "indev") == 0) {
671 if (check_ifname(*argv
))
672 invarg("\"indev\" not a valid ifname", *argv
);
673 addattrstrz(n
, MAX_MSG
, TCA_FLOWER_INDEV
, *argv
);
674 } else if (matches(*argv
, "vlan_id") == 0) {
678 if (!eth_type_vlan(eth_type
)) {
679 fprintf(stderr
, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n");
682 ret
= get_u16(&vid
, *argv
, 10);
683 if (ret
< 0 || vid
& ~0xfff) {
684 fprintf(stderr
, "Illegal \"vlan_id\"\n");
687 addattr16(n
, MAX_MSG
, TCA_FLOWER_KEY_VLAN_ID
, vid
);
688 } else if (matches(*argv
, "vlan_prio") == 0) {
692 if (!eth_type_vlan(eth_type
)) {
693 fprintf(stderr
, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n");
696 ret
= get_u8(&vlan_prio
, *argv
, 10);
697 if (ret
< 0 || vlan_prio
& ~0x7) {
698 fprintf(stderr
, "Illegal \"vlan_prio\"\n");
702 TCA_FLOWER_KEY_VLAN_PRIO
, vlan_prio
);
703 } else if (matches(*argv
, "vlan_ethtype") == 0) {
705 ret
= flower_parse_vlan_eth_type(*argv
, eth_type
,
706 TCA_FLOWER_KEY_VLAN_ETH_TYPE
,
710 } else if (matches(*argv
, "cvlan_id") == 0) {
714 if (!eth_type_vlan(vlan_ethtype
)) {
715 fprintf(stderr
, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
718 ret
= get_u16(&vid
, *argv
, 10);
719 if (ret
< 0 || vid
& ~0xfff) {
720 fprintf(stderr
, "Illegal \"cvlan_id\"\n");
723 addattr16(n
, MAX_MSG
, TCA_FLOWER_KEY_CVLAN_ID
, vid
);
724 } else if (matches(*argv
, "cvlan_prio") == 0) {
728 if (!eth_type_vlan(vlan_ethtype
)) {
729 fprintf(stderr
, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
732 ret
= get_u8(&cvlan_prio
, *argv
, 10);
733 if (ret
< 0 || cvlan_prio
& ~0x7) {
734 fprintf(stderr
, "Illegal \"cvlan_prio\"\n");
738 TCA_FLOWER_KEY_CVLAN_PRIO
, cvlan_prio
);
739 } else if (matches(*argv
, "cvlan_ethtype") == 0) {
741 ret
= flower_parse_vlan_eth_type(*argv
, vlan_ethtype
,
742 TCA_FLOWER_KEY_CVLAN_ETH_TYPE
,
746 } else if (matches(*argv
, "mpls_label") == 0) {
750 if (eth_type
!= htons(ETH_P_MPLS_UC
) &&
751 eth_type
!= htons(ETH_P_MPLS_MC
)) {
753 "Can't set \"mpls_label\" if ethertype isn't MPLS\n");
756 ret
= get_u32(&label
, *argv
, 10);
757 if (ret
< 0 || label
& ~(MPLS_LS_LABEL_MASK
>> MPLS_LS_LABEL_SHIFT
)) {
758 fprintf(stderr
, "Illegal \"mpls_label\"\n");
761 addattr32(n
, MAX_MSG
, TCA_FLOWER_KEY_MPLS_LABEL
, label
);
762 } else if (matches(*argv
, "mpls_tc") == 0) {
766 if (eth_type
!= htons(ETH_P_MPLS_UC
) &&
767 eth_type
!= htons(ETH_P_MPLS_MC
)) {
769 "Can't set \"mpls_tc\" if ethertype isn't MPLS\n");
772 ret
= get_u8(&tc
, *argv
, 10);
773 if (ret
< 0 || tc
& ~(MPLS_LS_TC_MASK
>> MPLS_LS_TC_SHIFT
)) {
774 fprintf(stderr
, "Illegal \"mpls_tc\"\n");
777 addattr8(n
, MAX_MSG
, TCA_FLOWER_KEY_MPLS_TC
, tc
);
778 } else if (matches(*argv
, "mpls_bos") == 0) {
782 if (eth_type
!= htons(ETH_P_MPLS_UC
) &&
783 eth_type
!= htons(ETH_P_MPLS_MC
)) {
785 "Can't set \"mpls_bos\" if ethertype isn't MPLS\n");
788 ret
= get_u8(&bos
, *argv
, 10);
789 if (ret
< 0 || bos
& ~(MPLS_LS_S_MASK
>> MPLS_LS_S_SHIFT
)) {
790 fprintf(stderr
, "Illegal \"mpls_bos\"\n");
793 addattr8(n
, MAX_MSG
, TCA_FLOWER_KEY_MPLS_BOS
, bos
);
794 } else if (matches(*argv
, "mpls_ttl") == 0) {
798 if (eth_type
!= htons(ETH_P_MPLS_UC
) &&
799 eth_type
!= htons(ETH_P_MPLS_MC
)) {
801 "Can't set \"mpls_ttl\" if ethertype isn't MPLS\n");
804 ret
= get_u8(&ttl
, *argv
, 10);
805 if (ret
< 0 || ttl
& ~(MPLS_LS_TTL_MASK
>> MPLS_LS_TTL_SHIFT
)) {
806 fprintf(stderr
, "Illegal \"mpls_ttl\"\n");
809 addattr8(n
, MAX_MSG
, TCA_FLOWER_KEY_MPLS_TTL
, ttl
);
810 } else if (matches(*argv
, "dst_mac") == 0) {
812 ret
= flower_parse_eth_addr(*argv
,
813 TCA_FLOWER_KEY_ETH_DST
,
814 TCA_FLOWER_KEY_ETH_DST_MASK
,
817 fprintf(stderr
, "Illegal \"dst_mac\"\n");
820 } else if (matches(*argv
, "src_mac") == 0) {
822 ret
= flower_parse_eth_addr(*argv
,
823 TCA_FLOWER_KEY_ETH_SRC
,
824 TCA_FLOWER_KEY_ETH_SRC_MASK
,
827 fprintf(stderr
, "Illegal \"src_mac\"\n");
830 } else if (matches(*argv
, "ip_proto") == 0) {
832 ret
= flower_parse_ip_proto(*argv
, cvlan_ethtype
?
833 cvlan_ethtype
: vlan_ethtype
?
834 vlan_ethtype
: eth_type
,
835 TCA_FLOWER_KEY_IP_PROTO
,
838 fprintf(stderr
, "Illegal \"ip_proto\"\n");
841 } else if (matches(*argv
, "ip_tos") == 0) {
843 ret
= flower_parse_ip_tos_ttl(*argv
,
844 TCA_FLOWER_KEY_IP_TOS
,
845 TCA_FLOWER_KEY_IP_TOS_MASK
,
848 fprintf(stderr
, "Illegal \"ip_tos\"\n");
851 } else if (matches(*argv
, "ip_ttl") == 0) {
853 ret
= flower_parse_ip_tos_ttl(*argv
,
854 TCA_FLOWER_KEY_IP_TTL
,
855 TCA_FLOWER_KEY_IP_TTL_MASK
,
858 fprintf(stderr
, "Illegal \"ip_ttl\"\n");
861 } else if (matches(*argv
, "dst_ip") == 0) {
863 ret
= flower_parse_ip_addr(*argv
, cvlan_ethtype
?
864 cvlan_ethtype
: vlan_ethtype
?
865 vlan_ethtype
: eth_type
,
866 TCA_FLOWER_KEY_IPV4_DST
,
867 TCA_FLOWER_KEY_IPV4_DST_MASK
,
868 TCA_FLOWER_KEY_IPV6_DST
,
869 TCA_FLOWER_KEY_IPV6_DST_MASK
,
872 fprintf(stderr
, "Illegal \"dst_ip\"\n");
875 } else if (matches(*argv
, "src_ip") == 0) {
877 ret
= flower_parse_ip_addr(*argv
, cvlan_ethtype
?
878 cvlan_ethtype
: vlan_ethtype
?
879 vlan_ethtype
: eth_type
,
880 TCA_FLOWER_KEY_IPV4_SRC
,
881 TCA_FLOWER_KEY_IPV4_SRC_MASK
,
882 TCA_FLOWER_KEY_IPV6_SRC
,
883 TCA_FLOWER_KEY_IPV6_SRC_MASK
,
886 fprintf(stderr
, "Illegal \"src_ip\"\n");
889 } else if (matches(*argv
, "dst_port") == 0) {
891 ret
= flower_parse_port(*argv
, ip_proto
,
892 FLOWER_ENDPOINT_DST
, n
);
894 fprintf(stderr
, "Illegal \"dst_port\"\n");
897 } else if (matches(*argv
, "src_port") == 0) {
899 ret
= flower_parse_port(*argv
, ip_proto
,
900 FLOWER_ENDPOINT_SRC
, n
);
902 fprintf(stderr
, "Illegal \"src_port\"\n");
905 } else if (matches(*argv
, "tcp_flags") == 0) {
907 ret
= flower_parse_tcp_flags(*argv
,
908 TCA_FLOWER_KEY_TCP_FLAGS
,
909 TCA_FLOWER_KEY_TCP_FLAGS_MASK
,
912 fprintf(stderr
, "Illegal \"tcp_flags\"\n");
915 } else if (matches(*argv
, "type") == 0) {
917 ret
= flower_parse_icmp(*argv
, eth_type
, ip_proto
,
918 FLOWER_ICMP_FIELD_TYPE
, n
);
920 fprintf(stderr
, "Illegal \"icmp type\"\n");
923 } else if (matches(*argv
, "code") == 0) {
925 ret
= flower_parse_icmp(*argv
, eth_type
, ip_proto
,
926 FLOWER_ICMP_FIELD_CODE
, n
);
928 fprintf(stderr
, "Illegal \"icmp code\"\n");
931 } else if (matches(*argv
, "arp_tip") == 0) {
933 ret
= flower_parse_arp_ip_addr(*argv
, vlan_ethtype
?
934 vlan_ethtype
: eth_type
,
935 TCA_FLOWER_KEY_ARP_TIP
,
936 TCA_FLOWER_KEY_ARP_TIP_MASK
,
939 fprintf(stderr
, "Illegal \"arp_tip\"\n");
942 } else if (matches(*argv
, "arp_sip") == 0) {
944 ret
= flower_parse_arp_ip_addr(*argv
, vlan_ethtype
?
945 vlan_ethtype
: eth_type
,
946 TCA_FLOWER_KEY_ARP_SIP
,
947 TCA_FLOWER_KEY_ARP_SIP_MASK
,
950 fprintf(stderr
, "Illegal \"arp_sip\"\n");
953 } else if (matches(*argv
, "arp_op") == 0) {
955 ret
= flower_parse_arp_op(*argv
, vlan_ethtype
?
956 vlan_ethtype
: eth_type
,
957 TCA_FLOWER_KEY_ARP_OP
,
958 TCA_FLOWER_KEY_ARP_OP_MASK
,
961 fprintf(stderr
, "Illegal \"arp_op\"\n");
964 } else if (matches(*argv
, "arp_tha") == 0) {
966 ret
= flower_parse_eth_addr(*argv
,
967 TCA_FLOWER_KEY_ARP_THA
,
968 TCA_FLOWER_KEY_ARP_THA_MASK
,
971 fprintf(stderr
, "Illegal \"arp_tha\"\n");
974 } else if (matches(*argv
, "arp_sha") == 0) {
976 ret
= flower_parse_eth_addr(*argv
,
977 TCA_FLOWER_KEY_ARP_SHA
,
978 TCA_FLOWER_KEY_ARP_SHA_MASK
,
981 fprintf(stderr
, "Illegal \"arp_sha\"\n");
984 } else if (matches(*argv
, "enc_dst_ip") == 0) {
986 ret
= flower_parse_ip_addr(*argv
, 0,
987 TCA_FLOWER_KEY_ENC_IPV4_DST
,
988 TCA_FLOWER_KEY_ENC_IPV4_DST_MASK
,
989 TCA_FLOWER_KEY_ENC_IPV6_DST
,
990 TCA_FLOWER_KEY_ENC_IPV6_DST_MASK
,
993 fprintf(stderr
, "Illegal \"enc_dst_ip\"\n");
996 } else if (matches(*argv
, "enc_src_ip") == 0) {
998 ret
= flower_parse_ip_addr(*argv
, 0,
999 TCA_FLOWER_KEY_ENC_IPV4_SRC
,
1000 TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK
,
1001 TCA_FLOWER_KEY_ENC_IPV6_SRC
,
1002 TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK
,
1005 fprintf(stderr
, "Illegal \"enc_src_ip\"\n");
1008 } else if (matches(*argv
, "enc_key_id") == 0) {
1010 ret
= flower_parse_key_id(*argv
,
1011 TCA_FLOWER_KEY_ENC_KEY_ID
, n
);
1013 fprintf(stderr
, "Illegal \"enc_key_id\"\n");
1016 } else if (matches(*argv
, "enc_dst_port") == 0) {
1018 ret
= flower_parse_enc_port(*argv
,
1019 TCA_FLOWER_KEY_ENC_UDP_DST_PORT
, n
);
1021 fprintf(stderr
, "Illegal \"enc_dst_port\"\n");
1024 } else if (matches(*argv
, "enc_tos") == 0) {
1026 ret
= flower_parse_ip_tos_ttl(*argv
,
1027 TCA_FLOWER_KEY_ENC_IP_TOS
,
1028 TCA_FLOWER_KEY_ENC_IP_TOS_MASK
,
1031 fprintf(stderr
, "Illegal \"enc_tos\"\n");
1034 } else if (matches(*argv
, "enc_ttl") == 0) {
1036 ret
= flower_parse_ip_tos_ttl(*argv
,
1037 TCA_FLOWER_KEY_ENC_IP_TTL
,
1038 TCA_FLOWER_KEY_ENC_IP_TTL_MASK
,
1041 fprintf(stderr
, "Illegal \"enc_ttl\"\n");
1044 } else if (matches(*argv
, "action") == 0) {
1046 ret
= parse_action(&argc
, &argv
, TCA_FLOWER_ACT
, n
);
1048 fprintf(stderr
, "Illegal \"action\"\n");
1052 } else if (strcmp(*argv
, "help") == 0) {
1056 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
1064 ret
= addattr32(n
, MAX_MSG
, TCA_FLOWER_FLAGS
, flags
);
1069 ret
= addattr32(n
, MAX_MSG
, TCA_FLOWER_KEY_FLAGS
, htonl(mtf
));
1073 ret
= addattr32(n
, MAX_MSG
, TCA_FLOWER_KEY_FLAGS_MASK
, htonl(mtf_mask
));
1078 if (eth_type
!= htons(ETH_P_ALL
)) {
1079 ret
= addattr16(n
, MAX_MSG
, TCA_FLOWER_KEY_ETH_TYPE
, eth_type
);
1084 tail
->rta_len
= (((void *)n
)+n
->nlmsg_len
) - (void *)tail
;
1089 static int __mask_bits(char *addr
, size_t len
)
1096 for (i
= 0; i
< len
; i
++, addr
++) {
1097 for (j
= 7; j
>= 0; j
--) {
1098 if (((*addr
) >> j
) & 0x1) {
1112 static void flower_print_eth_addr(char *name
, struct rtattr
*addr_attr
,
1113 struct rtattr
*mask_attr
)
1115 SPRINT_BUF(namefrm
);
1121 if (!addr_attr
|| RTA_PAYLOAD(addr_attr
) != ETH_ALEN
)
1123 done
= sprintf(out
, "%s",
1124 ll_addr_n2a(RTA_DATA(addr_attr
), ETH_ALEN
,
1125 0, b1
, sizeof(b1
)));
1126 if (mask_attr
&& RTA_PAYLOAD(mask_attr
) == ETH_ALEN
) {
1127 bits
= __mask_bits(RTA_DATA(mask_attr
), ETH_ALEN
);
1129 sprintf(out
+ done
, "/%s",
1130 ll_addr_n2a(RTA_DATA(mask_attr
), ETH_ALEN
,
1131 0, b1
, sizeof(b1
)));
1132 else if (bits
< ETH_ALEN
* 8)
1133 sprintf(out
+ done
, "/%d", bits
);
1136 sprintf(namefrm
, "\n %s %%s", name
);
1137 print_string(PRINT_ANY
, name
, namefrm
, out
);
1140 static void flower_print_eth_type(__be16
*p_eth_type
,
1141 struct rtattr
*eth_type_attr
)
1149 eth_type
= rta_getattr_u16(eth_type_attr
);
1150 if (eth_type
== htons(ETH_P_IP
))
1151 sprintf(out
, "ipv4");
1152 else if (eth_type
== htons(ETH_P_IPV6
))
1153 sprintf(out
, "ipv6");
1154 else if (eth_type
== htons(ETH_P_ARP
))
1155 sprintf(out
, "arp");
1156 else if (eth_type
== htons(ETH_P_RARP
))
1157 sprintf(out
, "rarp");
1159 sprintf(out
, "%04x", ntohs(eth_type
));
1161 print_string(PRINT_ANY
, "eth_type", "\n eth_type %s", out
);
1162 *p_eth_type
= eth_type
;
1165 static void flower_print_ip_proto(__u8
*p_ip_proto
,
1166 struct rtattr
*ip_proto_attr
)
1174 ip_proto
= rta_getattr_u8(ip_proto_attr
);
1175 if (ip_proto
== IPPROTO_TCP
)
1176 sprintf(out
, "tcp");
1177 else if (ip_proto
== IPPROTO_UDP
)
1178 sprintf(out
, "udp");
1179 else if (ip_proto
== IPPROTO_SCTP
)
1180 sprintf(out
, "sctp");
1181 else if (ip_proto
== IPPROTO_ICMP
)
1182 sprintf(out
, "icmp");
1183 else if (ip_proto
== IPPROTO_ICMPV6
)
1184 sprintf(out
, "icmpv6");
1186 sprintf(out
, "%02x", ip_proto
);
1188 print_string(PRINT_ANY
, "ip_proto", "\n ip_proto %s", out
);
1189 *p_ip_proto
= ip_proto
;
1192 static void flower_print_ip_attr(const char *name
, struct rtattr
*key_attr
,
1193 struct rtattr
*mask_attr
)
1195 SPRINT_BUF(namefrm
);
1202 done
= sprintf(out
, "0x%x", rta_getattr_u8(key_attr
));
1204 sprintf(out
+ done
, "/%x", rta_getattr_u8(mask_attr
));
1206 print_string(PRINT_FP
, NULL
, "%s ", _SL_
);
1207 sprintf(namefrm
, "%s %%s", name
);
1208 print_string(PRINT_ANY
, name
, namefrm
, out
);
1211 static void flower_print_matching_flags(char *name
,
1212 enum flower_matching_flags type
,
1213 struct rtattr
*attr
,
1214 struct rtattr
*mask_attr
)
1221 if (!mask_attr
|| RTA_PAYLOAD(mask_attr
) != 4)
1224 mtf
= ntohl(rta_getattr_u32(attr
));
1225 mtf_mask
= ntohl(rta_getattr_u32(mask_attr
));
1227 for (i
= 0; i
< ARRAY_SIZE(flags_str
); i
++) {
1228 if (type
!= flags_str
[i
].type
)
1230 if (mtf_mask
& flags_str
[i
].flag
) {
1232 print_string(PRINT_FP
, NULL
, "\n %s ", name
);
1233 open_json_object(name
);
1235 print_string(PRINT_FP
, NULL
, "/", NULL
);
1238 print_bool(PRINT_JSON
, flags_str
[i
].string
, NULL
,
1239 mtf
& flags_str
[i
].flag
);
1240 if (mtf
& flags_str
[i
].flag
)
1241 print_string(PRINT_FP
, NULL
, "%s",
1242 flags_str
[i
].string
);
1244 print_string(PRINT_FP
, NULL
, "no%s",
1245 flags_str
[i
].string
);
1249 close_json_object();
1252 static void flower_print_ip_addr(char *name
, __be16 eth_type
,
1253 struct rtattr
*addr4_attr
,
1254 struct rtattr
*mask4_attr
,
1255 struct rtattr
*addr6_attr
,
1256 struct rtattr
*mask6_attr
)
1258 struct rtattr
*addr_attr
;
1259 struct rtattr
*mask_attr
;
1260 SPRINT_BUF(namefrm
);
1267 if (eth_type
== htons(ETH_P_IP
)) {
1269 addr_attr
= addr4_attr
;
1270 mask_attr
= mask4_attr
;
1272 } else if (eth_type
== htons(ETH_P_IPV6
)) {
1274 addr_attr
= addr6_attr
;
1275 mask_attr
= mask6_attr
;
1280 if (!addr_attr
|| RTA_PAYLOAD(addr_attr
) != len
)
1282 if (!mask_attr
|| RTA_PAYLOAD(mask_attr
) != len
)
1284 done
= sprintf(out
, "%s", rt_addr_n2a_rta(family
, addr_attr
));
1285 bits
= __mask_bits(RTA_DATA(mask_attr
), len
);
1287 sprintf(out
+ done
, "/%s", rt_addr_n2a_rta(family
, mask_attr
));
1288 else if (bits
< len
* 8)
1289 sprintf(out
+ done
, "/%d", bits
);
1291 sprintf(namefrm
, "\n %s %%s", name
);
1292 print_string(PRINT_ANY
, name
, namefrm
, out
);
1294 static void flower_print_ip4_addr(char *name
, struct rtattr
*addr_attr
,
1295 struct rtattr
*mask_attr
)
1297 return flower_print_ip_addr(name
, htons(ETH_P_IP
),
1298 addr_attr
, mask_attr
, 0, 0);
1301 static void flower_print_port(char *name
, struct rtattr
*attr
)
1303 SPRINT_BUF(namefrm
);
1308 sprintf(namefrm
,"\n %s %%u", name
);
1309 print_hu(PRINT_ANY
, name
, namefrm
, rta_getattr_be16(attr
));
1312 static void flower_print_tcp_flags(const char *name
, struct rtattr
*flags_attr
,
1313 struct rtattr
*mask_attr
)
1315 SPRINT_BUF(namefrm
);
1322 done
= sprintf(out
, "0x%x", rta_getattr_be16(flags_attr
));
1324 sprintf(out
+ done
, "/%x", rta_getattr_be16(mask_attr
));
1326 print_string(PRINT_FP
, NULL
, "%s ", _SL_
);
1327 sprintf(namefrm
, "%s %%s", name
);
1328 print_string(PRINT_ANY
, name
, namefrm
, out
);
1332 static void flower_print_key_id(const char *name
, struct rtattr
*attr
)
1334 SPRINT_BUF(namefrm
);
1339 sprintf(namefrm
,"\n %s %%u", name
);
1340 print_uint(PRINT_ANY
, name
, namefrm
, rta_getattr_be32(attr
));
1343 static void flower_print_masked_u8(const char *name
, struct rtattr
*attr
,
1344 struct rtattr
*mask_attr
,
1345 const char *(*value_to_str
)(__u8 value
))
1347 const char *value_str
= NULL
;
1349 SPRINT_BUF(namefrm
);
1356 value
= rta_getattr_u8(attr
);
1357 mask
= mask_attr
? rta_getattr_u8(mask_attr
) : UINT8_MAX
;
1358 if (mask
== UINT8_MAX
&& value_to_str
)
1359 value_str
= value_to_str(value
);
1362 done
= sprintf(out
, "%s", value_str
);
1364 done
= sprintf(out
, "%d", value
);
1366 if (mask
!= UINT8_MAX
)
1367 sprintf(out
+ done
, "/%d", mask
);
1369 sprintf(namefrm
,"\n %s %%s", name
);
1370 print_string(PRINT_ANY
, name
, namefrm
, out
);
1373 static void flower_print_u8(const char *name
, struct rtattr
*attr
)
1375 flower_print_masked_u8(name
, attr
, NULL
, NULL
);
1378 static void flower_print_u32(const char *name
, struct rtattr
*attr
)
1380 SPRINT_BUF(namefrm
);
1385 sprintf(namefrm
,"\n %s %%u", name
);
1386 print_uint(PRINT_ANY
, name
, namefrm
, rta_getattr_u32(attr
));
1389 static void flower_print_arp_op(const char *name
,
1390 struct rtattr
*op_attr
,
1391 struct rtattr
*mask_attr
)
1393 flower_print_masked_u8(name
, op_attr
, mask_attr
,
1394 flower_print_arp_op_to_name
);
1397 static int flower_print_opt(struct filter_util
*qu
, FILE *f
,
1398 struct rtattr
*opt
, __u32 handle
)
1400 struct rtattr
*tb
[TCA_FLOWER_MAX
+ 1];
1401 int nl_type
, nl_mask_type
;
1402 __be16 eth_type
= 0;
1403 __u8 ip_proto
= 0xff;
1408 parse_rtattr_nested(tb
, TCA_FLOWER_MAX
, opt
);
1411 print_uint(PRINT_ANY
, "handle", "handle 0x%x ", handle
);
1413 if (tb
[TCA_FLOWER_CLASSID
]) {
1414 __u32 h
= rta_getattr_u32(tb
[TCA_FLOWER_CLASSID
]);
1416 if (TC_H_MIN(h
) < TC_H_MIN_PRIORITY
||
1417 TC_H_MIN(h
) > (TC_H_MIN_PRIORITY
+ TC_QOPT_MAX_QUEUE
- 1)) {
1419 print_string(PRINT_ANY
, "classid", "classid %s ",
1420 sprint_tc_classid(h
, b1
));
1422 print_uint(PRINT_ANY
, "hw_tc", "hw_tc %u ",
1423 TC_H_MIN(h
) - TC_H_MIN_PRIORITY
);
1427 if (tb
[TCA_FLOWER_INDEV
]) {
1428 struct rtattr
*attr
= tb
[TCA_FLOWER_INDEV
];
1430 print_string(PRINT_ANY
, "indev", "\n indev %s",
1431 rta_getattr_str(attr
));
1434 open_json_object("keys");
1436 if (tb
[TCA_FLOWER_KEY_VLAN_ID
]) {
1437 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_VLAN_ID
];
1439 print_uint(PRINT_ANY
, "vlan_id", "\n vlan_id %u",
1440 rta_getattr_u16(attr
));
1443 if (tb
[TCA_FLOWER_KEY_VLAN_PRIO
]) {
1444 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_VLAN_PRIO
];
1446 print_uint(PRINT_ANY
, "vlan_prio", "\n vlan_prio %d",
1447 rta_getattr_u8(attr
));
1450 if (tb
[TCA_FLOWER_KEY_VLAN_ETH_TYPE
]) {
1452 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_VLAN_ETH_TYPE
];
1454 print_string(PRINT_ANY
, "vlan_ethtype", "\n vlan_ethtype %s",
1455 ll_proto_n2a(rta_getattr_u16(attr
),
1459 if (tb
[TCA_FLOWER_KEY_CVLAN_ID
]) {
1460 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_CVLAN_ID
];
1462 print_uint(PRINT_ANY
, "cvlan_id", "\n cvlan_id %u",
1463 rta_getattr_u16(attr
));
1466 if (tb
[TCA_FLOWER_KEY_CVLAN_PRIO
]) {
1467 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_CVLAN_PRIO
];
1469 print_uint(PRINT_ANY
, "cvlan_prio", "\n cvlan_prio %d",
1470 rta_getattr_u8(attr
));
1473 if (tb
[TCA_FLOWER_KEY_CVLAN_ETH_TYPE
]) {
1475 struct rtattr
*attr
= tb
[TCA_FLOWER_KEY_CVLAN_ETH_TYPE
];
1477 print_string(PRINT_ANY
, "cvlan_ethtype", "\n cvlan_ethtype %s",
1478 ll_proto_n2a(rta_getattr_u16(attr
),
1482 flower_print_eth_addr("dst_mac", tb
[TCA_FLOWER_KEY_ETH_DST
],
1483 tb
[TCA_FLOWER_KEY_ETH_DST_MASK
]);
1484 flower_print_eth_addr("src_mac", tb
[TCA_FLOWER_KEY_ETH_SRC
],
1485 tb
[TCA_FLOWER_KEY_ETH_SRC_MASK
]);
1487 flower_print_eth_type(ð_type
, tb
[TCA_FLOWER_KEY_ETH_TYPE
]);
1488 flower_print_ip_proto(&ip_proto
, tb
[TCA_FLOWER_KEY_IP_PROTO
]);
1490 flower_print_ip_attr("ip_tos", tb
[TCA_FLOWER_KEY_IP_TOS
],
1491 tb
[TCA_FLOWER_KEY_IP_TOS_MASK
]);
1492 flower_print_ip_attr("ip_ttl", tb
[TCA_FLOWER_KEY_IP_TTL
],
1493 tb
[TCA_FLOWER_KEY_IP_TTL_MASK
]);
1495 flower_print_u32("mpls_label", tb
[TCA_FLOWER_KEY_MPLS_LABEL
]);
1496 flower_print_u8("mpls_tc", tb
[TCA_FLOWER_KEY_MPLS_TC
]);
1497 flower_print_u8("mpls_bos", tb
[TCA_FLOWER_KEY_MPLS_BOS
]);
1498 flower_print_u8("mpls_ttl", tb
[TCA_FLOWER_KEY_MPLS_TTL
]);
1500 flower_print_ip_addr("dst_ip", eth_type
,
1501 tb
[TCA_FLOWER_KEY_IPV4_DST
],
1502 tb
[TCA_FLOWER_KEY_IPV4_DST_MASK
],
1503 tb
[TCA_FLOWER_KEY_IPV6_DST
],
1504 tb
[TCA_FLOWER_KEY_IPV6_DST_MASK
]);
1506 flower_print_ip_addr("src_ip", eth_type
,
1507 tb
[TCA_FLOWER_KEY_IPV4_SRC
],
1508 tb
[TCA_FLOWER_KEY_IPV4_SRC_MASK
],
1509 tb
[TCA_FLOWER_KEY_IPV6_SRC
],
1510 tb
[TCA_FLOWER_KEY_IPV6_SRC_MASK
]);
1512 nl_type
= flower_port_attr_type(ip_proto
, FLOWER_ENDPOINT_DST
);
1514 flower_print_port("dst_port", tb
[nl_type
]);
1515 nl_type
= flower_port_attr_type(ip_proto
, FLOWER_ENDPOINT_SRC
);
1517 flower_print_port("src_port", tb
[nl_type
]);
1519 flower_print_tcp_flags("tcp_flags", tb
[TCA_FLOWER_KEY_TCP_FLAGS
],
1520 tb
[TCA_FLOWER_KEY_TCP_FLAGS_MASK
]);
1522 nl_type
= flower_icmp_attr_type(eth_type
, ip_proto
,
1523 FLOWER_ICMP_FIELD_TYPE
);
1524 nl_mask_type
= flower_icmp_attr_mask_type(eth_type
, ip_proto
,
1525 FLOWER_ICMP_FIELD_TYPE
);
1526 if (nl_type
>= 0 && nl_mask_type
>= 0)
1527 flower_print_masked_u8("icmp_type", tb
[nl_type
],
1528 tb
[nl_mask_type
], NULL
);
1530 nl_type
= flower_icmp_attr_type(eth_type
, ip_proto
,
1531 FLOWER_ICMP_FIELD_CODE
);
1532 nl_mask_type
= flower_icmp_attr_mask_type(eth_type
, ip_proto
,
1533 FLOWER_ICMP_FIELD_CODE
);
1534 if (nl_type
>= 0 && nl_mask_type
>= 0)
1535 flower_print_masked_u8("icmp_code", tb
[nl_type
],
1536 tb
[nl_mask_type
], NULL
);
1538 flower_print_ip4_addr("arp_sip", tb
[TCA_FLOWER_KEY_ARP_SIP
],
1539 tb
[TCA_FLOWER_KEY_ARP_SIP_MASK
]);
1540 flower_print_ip4_addr("arp_tip", tb
[TCA_FLOWER_KEY_ARP_TIP
],
1541 tb
[TCA_FLOWER_KEY_ARP_TIP_MASK
]);
1542 flower_print_arp_op("arp_op", tb
[TCA_FLOWER_KEY_ARP_OP
],
1543 tb
[TCA_FLOWER_KEY_ARP_OP_MASK
]);
1544 flower_print_eth_addr("arp_sha", tb
[TCA_FLOWER_KEY_ARP_SHA
],
1545 tb
[TCA_FLOWER_KEY_ARP_SHA_MASK
]);
1546 flower_print_eth_addr("arp_tha", tb
[TCA_FLOWER_KEY_ARP_THA
],
1547 tb
[TCA_FLOWER_KEY_ARP_THA_MASK
]);
1549 flower_print_ip_addr("enc_dst_ip",
1550 tb
[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK
] ?
1551 htons(ETH_P_IP
) : htons(ETH_P_IPV6
),
1552 tb
[TCA_FLOWER_KEY_ENC_IPV4_DST
],
1553 tb
[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK
],
1554 tb
[TCA_FLOWER_KEY_ENC_IPV6_DST
],
1555 tb
[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK
]);
1557 flower_print_ip_addr("enc_src_ip",
1558 tb
[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK
] ?
1559 htons(ETH_P_IP
) : htons(ETH_P_IPV6
),
1560 tb
[TCA_FLOWER_KEY_ENC_IPV4_SRC
],
1561 tb
[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK
],
1562 tb
[TCA_FLOWER_KEY_ENC_IPV6_SRC
],
1563 tb
[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK
]);
1565 flower_print_key_id("enc_key_id", tb
[TCA_FLOWER_KEY_ENC_KEY_ID
]);
1567 flower_print_port("enc_dst_port", tb
[TCA_FLOWER_KEY_ENC_UDP_DST_PORT
]);
1569 flower_print_ip_attr("enc_tos", tb
[TCA_FLOWER_KEY_ENC_IP_TOS
],
1570 tb
[TCA_FLOWER_KEY_ENC_IP_TOS_MASK
]);
1571 flower_print_ip_attr("enc_ttl", tb
[TCA_FLOWER_KEY_ENC_IP_TTL
],
1572 tb
[TCA_FLOWER_KEY_ENC_IP_TTL_MASK
]);
1574 flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS
,
1575 tb
[TCA_FLOWER_KEY_FLAGS
],
1576 tb
[TCA_FLOWER_KEY_FLAGS_MASK
]);
1578 close_json_object();
1580 if (tb
[TCA_FLOWER_FLAGS
]) {
1581 __u32 flags
= rta_getattr_u32(tb
[TCA_FLOWER_FLAGS
]);
1583 if (flags
& TCA_CLS_FLAGS_SKIP_HW
)
1584 print_bool(PRINT_ANY
, "skip_hw", "\n skip_hw", true);
1585 if (flags
& TCA_CLS_FLAGS_SKIP_SW
)
1586 print_bool(PRINT_ANY
, "skip_sw", "\n skip_sw", true);
1588 if (flags
& TCA_CLS_FLAGS_IN_HW
)
1589 print_bool(PRINT_ANY
, "in_hw", "\n in_hw", true);
1590 else if (flags
& TCA_CLS_FLAGS_NOT_IN_HW
)
1591 print_bool(PRINT_ANY
, "not_in_hw", "\n not_in_hw", true);
1594 if (tb
[TCA_FLOWER_ACT
])
1595 tc_print_action(f
, tb
[TCA_FLOWER_ACT
], 0);
1600 struct filter_util flower_filter_util
= {
1602 .parse_fopt
= flower_parse_opt
,
1603 .print_fopt
= flower_print_opt
,