tc: flower: add support for tcp flags
Allow user to insert a flower classifier filter rule which includes match for tcp flags. Signed-off-by: Jiri Pirko <jiri@mellanox.com>
This commit is contained in:
parent
2ecb169280
commit
0c30d14d0a
|
|
@ -35,6 +35,8 @@ flower \- flow based traffic control filter
|
||||||
.IR PREFIX " | { "
|
.IR PREFIX " | { "
|
||||||
.BR dst_port " | " src_port " } "
|
.BR dst_port " | " src_port " } "
|
||||||
.IR port_number " } | "
|
.IR port_number " } | "
|
||||||
|
.B tcp_flags
|
||||||
|
.IR MASKED_TCP_FLAGS " | "
|
||||||
.B type
|
.B type
|
||||||
.IR MASKED_TYPE " | "
|
.IR MASKED_TYPE " | "
|
||||||
.B code
|
.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
|
.BR ip_proto " values " udp ", " tcp " and " sctp
|
||||||
which have to be specified in beforehand.
|
which have to be specified in beforehand.
|
||||||
.TP
|
.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"
|
.BI type " MASKED_TYPE"
|
||||||
.TQ
|
.TQ
|
||||||
.BI code " MASKED_CODE"
|
.BI code " MASKED_CODE"
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ static void explain(void)
|
||||||
" src_ip PREFIX |\n"
|
" src_ip PREFIX |\n"
|
||||||
" dst_port PORT-NUMBER |\n"
|
" dst_port PORT-NUMBER |\n"
|
||||||
" src_port PORT-NUMBER |\n"
|
" src_port PORT-NUMBER |\n"
|
||||||
|
" tcp_flags MASKED-TCP_FLAGS |\n"
|
||||||
" type MASKED-ICMP-TYPE |\n"
|
" type MASKED-ICMP-TYPE |\n"
|
||||||
" code MASKED-ICMP-CODE |\n"
|
" code MASKED-ICMP-CODE |\n"
|
||||||
" arp_tip IPV4-PREFIX |\n"
|
" arp_tip IPV4-PREFIX |\n"
|
||||||
|
|
@ -474,6 +475,41 @@ static int flower_parse_port(char *str, __u8 ip_proto,
|
||||||
return 0;
|
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)
|
static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -671,6 +707,16 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||||
fprintf(stderr, "Illegal \"src_port\"\n");
|
fprintf(stderr, "Illegal \"src_port\"\n");
|
||||||
return -1;
|
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) {
|
} else if (matches(*argv, "type") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
ret = flower_parse_icmp(*argv, eth_type, ip_proto,
|
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));
|
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,
|
static void flower_print_key_id(FILE *f, const char *name,
|
||||||
struct rtattr *attr)
|
struct rtattr *attr)
|
||||||
{
|
{
|
||||||
|
|
@ -1110,6 +1169,9 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
||||||
if (nl_type >= 0)
|
if (nl_type >= 0)
|
||||||
flower_print_port(f, "src_port", tb[nl_type]);
|
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,
|
nl_type = flower_icmp_attr_type(eth_type, ip_proto,
|
||||||
FLOWER_ICMP_FIELD_TYPE);
|
FLOWER_ICMP_FIELD_TYPE);
|
||||||
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
|
nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue