Except ct_label, just a place holder for now. Parsing of ct_state definitely should be handled better.
Signed-off-by: Marcelo Ricardo Leitner <mleit...@redhat.com> --- include/uapi/linux/pkt_cls.h | 9 ++ tc/f_flower.c | 158 ++++++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 95d0db2a8350dffb1dd20816591f3b179913fb2e..ba1f3bc01b2fdfd810e37a2b3853a1da1f838acf 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -490,6 +490,15 @@ enum { TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */ TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */ + TCA_FLOWER_KEY_CT_ZONE, /* u16 */ + TCA_FLOWER_KEY_CT_ZONE_MASK, /* u16 */ + TCA_FLOWER_KEY_CT_STATE, /* u8 */ + TCA_FLOWER_KEY_CT_STATE_MASK, /* u8 */ + TCA_FLOWER_KEY_CT_MARK, /* u32 */ + TCA_FLOWER_KEY_CT_MARK_MASK, /* u32 */ + TCA_FLOWER_KEY_CT_LABEL, /* 128 bits */ + TCA_FLOWER_KEY_CT_LABEL_MASK, /* 128 bits */ + __TCA_FLOWER_MAX, }; diff --git a/tc/f_flower.c b/tc/f_flower.c index c563666702b50973703f37c0174bfae3f242fdf3..40706d7156131f0b6603a4abdbe9108451e5cff7 100644 --- a/tc/f_flower.c +++ b/tc/f_flower.c @@ -81,7 +81,11 @@ static void explain(void) " enc_ttl MASKED-IP_TTL |\n" " geneve_opts MASKED-OPTIONS |\n" " ip_flags IP-FLAGS | \n" - " enc_dst_port [ port_number ] }\n" + " enc_dst_port [ port_number ] | \n" + " ct_mark MASKED-MARK | \n" + " ct_zone MASKED-ZONE | \n" + " ct_state MASKED-state | \n" + " ct_label MASKED-label } \n" " FILTERID := X:Y:Z\n" " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n" " ACTION-SPEC := ... look at individual actions\n" @@ -331,7 +335,7 @@ static int flower_parse_arp_ip_addr(char *str, __be16 eth_type, static int flower_parse_u8(char *str, int value_type, int mask_type, int (*value_from_name)(const char *str, - __u8 *value), + __u8 *value), bool (*value_validate)(__u8 value), struct nlmsghdr *n) { @@ -372,6 +376,92 @@ err: return err; } +static int flower_parse_u16(char *str, int value_type, int mask_type, + int (*value_from_name)(const char *str, + __u16 *value), + bool (*value_validate)(__u16 value), + struct nlmsghdr *n) +{ + char *slash; + int ret, err = -1; + __u16 value, mask; + + slash = strchr(str, '/'); + if (slash) + *slash = '\0'; + + ret = value_from_name ? value_from_name(str, &value) : -1; + if (ret < 0) { + ret = get_u16(&value, str, 10); + if (ret) + goto err; + } + + if (value_validate && !value_validate(value)) + goto err; + + if (slash) { + ret = get_u16(&mask, slash + 1, 10); + if (ret) + goto err; + } + else { + mask = UINT16_MAX; + } + + addattr16(n, MAX_MSG, value_type, value); + addattr16(n, MAX_MSG, mask_type, mask); + + err = 0; +err: + if (slash) + *slash = '/'; + return err; +} + +static int flower_parse_u32(char *str, int value_type, int mask_type, + int (*value_from_name)(const char *str, + __u32 *value), + bool (*value_validate)(__u32 value), + struct nlmsghdr *n) +{ + char *slash; + int ret, err = -1; + __u32 value, mask; + + slash = strchr(str, '/'); + if (slash) + *slash = '\0'; + + ret = value_from_name ? value_from_name(str, &value) : -1; + if (ret < 0) { + ret = get_u32(&value, str, 10); + if (ret) + goto err; + } + + if (value_validate && !value_validate(value)) + goto err; + + if (slash) { + ret = get_u32(&mask, slash + 1, 10); + if (ret) + goto err; + } + else { + mask = UINT32_MAX; + } + + addattr32(n, MAX_MSG, value_type, value); + addattr32(n, MAX_MSG, mask_type, mask); + + err = 0; +err: + if (slash) + *slash = '/'; + return err; +} + static const char *flower_print_arp_op_to_name(__u8 op) { switch (op) { @@ -796,6 +886,40 @@ static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) return 0; } +static int flower_parse_ct_mark(char *str, struct nlmsghdr *n) +{ + return flower_parse_u32(str, + TCA_FLOWER_KEY_CT_MARK, + TCA_FLOWER_KEY_CT_MARK_MASK, + NULL, NULL, n); +} + +static int flower_parse_ct_zone(char *str, struct nlmsghdr *n) +{ + return flower_parse_u16(str, + TCA_FLOWER_KEY_CT_ZONE, + TCA_FLOWER_KEY_CT_ZONE_MASK, + NULL, NULL, n); +} + +static int flower_parse_ct_state(char *str, struct nlmsghdr *n) +{ + return flower_parse_u8(str, + TCA_FLOWER_KEY_CT_STATE, + TCA_FLOWER_KEY_CT_STATE_MASK, + NULL, NULL, n); +} + +/* +static int flower_parse_ct_label(char *str, struct nlmsghdr *n) +{ + return flower_parse_u128_masked(str, + TCA_FLOWER_KEY_CT_LABEL, + TCA_FLOWER_KEY_CT_LABEL_MASK, + n); +} +*/ + static int flower_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { @@ -1255,6 +1379,35 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, fprintf(stderr, "Illegal \"geneve_opts\"\n"); return -1; } + } else if (matches(*argv, "ct_mark") == 0) { + NEXT_ARG(); + ret = flower_parse_ct_mark(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"ct_mark\"\n"); + return -1; + } + } else if (matches(*argv, "ct_zone") == 0) { + NEXT_ARG(); + ret = flower_parse_ct_zone(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"ct_zone\"\n"); + return -1; + } + } else if (matches(*argv, "ct_state") == 0) { + NEXT_ARG(); + ret = flower_parse_ct_state(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"ct_state\"\n"); + return -1; + } +/* } else if (matches(*argv, "ct_label") == 0) { + NEXT_ARG(); + ret = flower_parse_ct_label(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"ct_label\"\n"); + return -1; + } +*/ } else if (matches(*argv, "action") == 0) { NEXT_ARG(); ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); @@ -1919,6 +2072,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, tb[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]); flower_print_enc_opts("enc_opt", tb[TCA_FLOWER_KEY_ENC_OPTS], tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); + /* FIXME: print ct fields */ flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS, tb[TCA_FLOWER_KEY_FLAGS], -- 2.20.1