]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
tc: flower: add support for tcp flags
authorJiri Pirko <jiri@mellanox.com>
Tue, 23 May 2017 21:51:39 +0000 (23:51 +0200)
committerStephen Hemminger <stephen@networkplumber.org>
Wed, 31 May 2017 00:41:32 +0000 (17:41 -0700)
Allow user to insert a flower classifier filter rule which includes
match for tcp flags.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
man/man8/tc-flower.8
tc/f_flower.c

index ba290657c22452ede01af0755f183a33cd241c12..76480798d72f9fd3ab71d0bad76466f4854c6efd 100644 (file)
@@ -35,6 +35,8 @@ flower \- flow based traffic control filter
 .IR PREFIX " | { "
 .BR dst_port " | " src_port " } "
 .IR port_number " } | "
+.B tcp_flags
+.IR MASKED_TCP_FLAGS " | "
 .B type
 .IR MASKED_TYPE " | "
 .B code
@@ -136,6 +138,12 @@ Match on layer 4 protocol source or destination port number. Only available for
 .BR ip_proto " values " udp ", " tcp  " and " sctp
 which have to be specified in beforehand.
 .TP
+.BI tcp_flags " MASKED_TCP_FLAGS"
+Match on TCP flags represented as 12bit bitfield in in hexadecimal format.
+A mask may be optionally provided to limit the bits which are matched. A mask
+is provided by following the value with a slash and then the mask. If the mask
+is missing then a match on all bits is assumed.
+.TP
 .BI type " MASKED_TYPE"
 .TQ
 .BI code " MASKED_CODE"
index ebc63ca6b2a27f6f4893efe32d3b7513b504d6d5..1b6b46ea0177b0e69b054952a81d917339a20a79 100644 (file)
@@ -57,6 +57,7 @@ static void explain(void)
                "                       src_ip PREFIX |\n"
                "                       dst_port PORT-NUMBER |\n"
                "                       src_port PORT-NUMBER |\n"
+               "                       tcp_flags MASKED-TCP_FLAGS |\n"
                "                       type MASKED-ICMP-TYPE |\n"
                "                       code MASKED-ICMP-CODE |\n"
                "                       arp_tip IPV4-PREFIX |\n"
@@ -474,6 +475,41 @@ static int flower_parse_port(char *str, __u8 ip_proto,
        return 0;
 }
 
+#define TCP_FLAGS_MAX_MASK 0xfff
+
+static int flower_parse_tcp_flags(char *str, int flags_type, int mask_type,
+                                 struct nlmsghdr *n)
+{
+       char *slash;
+       int ret, err = -1;
+       __u16 flags;
+
+       slash = strchr(str, '/');
+       if (slash)
+               *slash = '\0';
+
+       ret = get_u16(&flags, str, 16);
+       if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
+               goto err;
+
+       addattr16(n, MAX_MSG, flags_type, htons(flags));
+
+       if (slash) {
+               ret = get_u16(&flags, slash + 1, 16);
+               if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
+                       goto err;
+       } else {
+               flags = TCP_FLAGS_MAX_MASK;
+       }
+       addattr16(n, MAX_MSG, mask_type, htons(flags));
+
+       err = 0;
+err:
+       if (slash)
+               *slash = '/';
+       return err;
+}
+
 static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n)
 {
        int ret;
@@ -671,6 +707,16 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
                                fprintf(stderr, "Illegal \"src_port\"\n");
                                return -1;
                        }
+               } else if (matches(*argv, "tcp_flags") == 0) {
+                       NEXT_ARG();
+                       ret = flower_parse_tcp_flags(*argv,
+                                                    TCA_FLOWER_KEY_TCP_FLAGS,
+                                                    TCA_FLOWER_KEY_TCP_FLAGS_MASK,
+                                                    n);
+                       if (ret < 0) {
+                               fprintf(stderr, "Illegal \"tcp_flags\"\n");
+                               return -1;
+                       }
                } else if (matches(*argv, "type") == 0) {
                        NEXT_ARG();
                        ret = flower_parse_icmp(*argv, eth_type, ip_proto,
@@ -1000,6 +1046,19 @@ static void flower_print_port(FILE *f, char *name, struct rtattr *attr)
                fprintf(f, "\n  %s %d", name, rta_getattr_be16(attr));
 }
 
+static void flower_print_tcp_flags(FILE *f, char *name,
+                                 struct rtattr *flags_attr,
+                                 struct rtattr *mask_attr)
+{
+       if (!flags_attr)
+               return;
+       fprintf(f, "\n  %s %x", name, rta_getattr_be16(flags_attr));
+       if (!mask_attr)
+               return;
+       fprintf(f, "/%x", rta_getattr_be16(mask_attr));
+}
+
+
 static void flower_print_key_id(FILE *f, const char *name,
                                struct rtattr *attr)
 {
@@ -1110,6 +1169,9 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
        if (nl_type >= 0)
                flower_print_port(f, "src_port", tb[nl_type]);
 
+       flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
+                              tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
+
        nl_type = flower_icmp_attr_type(eth_type, ip_proto,
                                        FLOWER_ICMP_FIELD_TYPE);
        nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,