From 8912f0302a56bd1d95b3059d1ec92dce19885df0 Mon Sep 17 00:00:00 2001 From: "Rywacki, Kamil" Date: Thu, 8 Oct 2020 01:25:02 +0200 Subject: flower: add ip_proto and icmp4|6 support --- include/netlink-private/types.h | 9 ++ include/netlink/route/cls/flower.h | 18 +++ lib/route/cls/flower.c | 231 ++++++++++++++++++++++++++++- libnl-route-3.sym | 18 +++ 4 files changed, 275 insertions(+), 1 deletion(-) --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -649,6 +649,15 @@ struct rtnl_flower uint32_t fl_cvlan_id; uint32_t fl_cvlan_prio; uint16_t fl_cvlan_eth_type; + uint8_t fl_ip_proto; + uint8_t fl_icmpv4_code; + uint8_t fl_icmpv4_code_mask; + uint8_t fl_icmpv4_type; + uint8_t fl_icmpv4_type_mask; + uint8_t fl_icmpv6_code; + uint8_t fl_icmpv6_code_mask; + uint8_t fl_icmpv6_type; + uint8_t fl_icmpv6_type_mask; int fl_mask; }; --- a/include/netlink/route/cls/flower.h +++ b/include/netlink/route/cls/flower.h @@ -54,6 +54,24 @@ extern int rtnl_flower_set_cvlan_prio(st extern int rtnl_flower_get_cvlan_prio(struct rtnl_cls *, uint32_t *); extern int rtnl_flower_set_cvlan_eth_type(struct rtnl_cls *, uint16_t); extern int rtnl_flower_get_cvlan_eth_type(struct rtnl_cls *, uint16_t *); +extern int rtnl_flower_set_ip_proto(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_ip_proto(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv4_code(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv4_code(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv4_code_mask(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv4_code_mask(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv4_type(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv4_type(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv4_type_mask(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv4_type_mask(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv6_code(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv6_code(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv6_code_mask(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv6_code_mask(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv6_type(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv6_type(struct rtnl_cls *, uint8_t *); +extern int rtnl_flower_set_icmpv6_type_mask(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_icmpv6_type_mask(struct rtnl_cls *, uint8_t *); #ifdef __cplusplus } --- a/lib/route/cls/flower.c +++ b/lib/route/cls/flower.c @@ -45,6 +45,15 @@ #define FLOWER_ATTR_KEY_CVLAN_ID (0x1 << 13) #define FLOWER_ATTR_KEY_CVLAN_PRIO (0x1 << 14) #define FLOWER_ATTR_KEY_CVLAN_ETH_TYPE (0x1 << 15) +#define FLOWER_ATTR_KEY_IP_PROTO (0x1 << 16) +#define FLOWER_ATTR_KEY_ICMPV4_CODE (0x1 << 17) +#define FLOWER_ATTR_KEY_ICMPV4_CODE_MASK (0x1 << 18) +#define FLOWER_ATTR_KEY_ICMPV4_TYPE (0x1 << 19) +#define FLOWER_ATTR_KEY_ICMPV4_TYPE_MASK (0x1 << 20) +#define FLOWER_ATTR_KEY_ICMPV6_CODE (0x1 << 21) +#define FLOWER_ATTR_KEY_ICMPV6_CODE_MASK (0x1 << 22) +#define FLOWER_ATTR_KEY_ICMPV6_TYPE (0x1 << 23) +#define FLOWER_ATTR_KEY_ICMPV6_TYPE_MASK (0x1 << 24) /** @endcond */ #ifndef MIN @@ -89,6 +98,15 @@ static struct nla_policy flower_policy[T [TCA_FLOWER_KEY_CVLAN_ID] = {.type = NLA_U16}, [TCA_FLOWER_KEY_CVLAN_PRIO] = {.type = NLA_U8}, [TCA_FLOWER_KEY_CVLAN_ETH_TYPE] = {.type = NLA_U16}, + [TCA_FLOWER_KEY_IP_PROTO] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV4_CODE] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV4_CODE_MASK] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV4_TYPE] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV6_CODE] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV6_CODE_MASK] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV6_TYPE] = {.type = NLA_U8}, + [TCA_FLOWER_KEY_ICMPV6_TYPE_MASK] = {.type = NLA_U8}, }; static int flower_msg_parser(struct rtnl_tc *tc, void *data) @@ -182,6 +200,55 @@ static int flower_msg_parser(struct rtnl f->fl_mask |= FLOWER_ATTR_KEY_CVLAN_ETH_TYPE; } + if (tb[TCA_FLOWER_KEY_IP_PROTO]) { + f->fl_ip_proto = nla_get_u8(tb[TCA_FLOWER_KEY_IP_PROTO]); + f->fl_mask |= FLOWER_ATTR_KEY_IP_PROTO; + } + + if (tb[TCA_FLOWER_KEY_ICMPV4_CODE]) { + f->fl_icmpv4_code = nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV4_CODE]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV4_CODE; + } + + if (tb[TCA_FLOWER_KEY_ICMPV4_CODE_MASK]) { + f->fl_icmpv4_code_mask = + nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV4_CODE_MASK]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV4_CODE_MASK; + } + + if (tb[TCA_FLOWER_KEY_ICMPV4_TYPE]) { + f->fl_icmpv4_type = nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV4_TYPE]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV4_TYPE; + } + + if (tb[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK]) { + f->fl_icmpv4_type_mask = + nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV4_TYPE_MASK]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV4_TYPE_MASK; + } + + if (tb[TCA_FLOWER_KEY_ICMPV6_CODE]) { + f->fl_icmpv6_code = nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV6_CODE]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV6_CODE; + } + + if (tb[TCA_FLOWER_KEY_ICMPV6_CODE_MASK]) { + f->fl_icmpv6_code_mask = + nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV6_CODE_MASK]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV6_CODE_MASK; + } + + if (tb[TCA_FLOWER_KEY_ICMPV6_TYPE]) { + f->fl_icmpv6_type = nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV6_TYPE]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV6_TYPE; + } + + if (tb[TCA_FLOWER_KEY_ICMPV6_TYPE_MASK]) { + f->fl_icmpv6_type_mask = + nla_get_u8(tb[TCA_FLOWER_KEY_ICMPV6_TYPE_MASK]); + f->fl_mask |= FLOWER_ATTR_KEY_ICMPV6_TYPE_MASK; + } + if (tb[TCA_FLOWER_ACT]) { f->fl_mask |= FLOWER_ATTR_ACTION; err = rtnl_act_parse(&f->fl_act, tb[TCA_FLOWER_ACT]); @@ -356,7 +423,39 @@ static int flower_msg_fill(struct rtnl_t (uint8_t) f->fl_cvlan_prio); if (f->fl_mask & FLOWER_ATTR_KEY_CVLAN_ETH_TYPE) - NLA_PUT_U16(msg, TCA_FLOWER_KEY_CVLAN_ETH_TYPE, htons(f->fl_cvlan_eth_type)); + NLA_PUT_U16(msg, TCA_FLOWER_KEY_CVLAN_ETH_TYPE, + htons(f->fl_cvlan_eth_type)); + + if (f->fl_mask & FLOWER_ATTR_KEY_IP_PROTO) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_IP_PROTO, f->fl_ip_proto); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV4_CODE) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV4_CODE, f->fl_icmpv4_code); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV4_CODE_MASK) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV4_CODE_MASK, + f->fl_icmpv4_code_mask); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV4_TYPE) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV4_TYPE, f->fl_icmpv4_type); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV4_TYPE_MASK) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV4_TYPE_MASK, + f->fl_icmpv4_type_mask); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV6_CODE) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV6_CODE, f->fl_icmpv6_code); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV6_CODE_MASK) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV6_CODE_MASK, + f->fl_icmpv6_code_mask); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV6_TYPE) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV6_TYPE, f->fl_icmpv6_type); + + if (f->fl_mask & FLOWER_ATTR_KEY_ICMPV6_TYPE_MASK) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_ICMPV6_TYPE_MASK, + f->fl_icmpv6_type_mask); if (f->fl_mask & FLOWER_ATTR_ACTION) { int err; @@ -736,6 +835,136 @@ int rtnl_flower_get_cvlan_eth_type(struc return 0; } +int rtnl_flower_set_ip_proto(struct rtnl_cls *cls, uint8_t ip_proto) +{ + SETTER(cls, fl_ip_proto, &ip_proto, sizeof(ip_proto), + FLOWER_ATTR_KEY_IP_PROTO); + return 0; +} + +int rtnl_flower_get_ip_proto(struct rtnl_cls *cls, uint8_t *ip_proto) +{ + GETTER(cls, fl_ip_proto, ip_proto, sizeof(*ip_proto), + FLOWER_ATTR_KEY_IP_PROTO); + return 0; +} + +/* ICMPV4 CODE sector */ +int rtnl_flower_set_icmpv4_code(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv4_code, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV4_CODE); + return 0; +} + +int rtnl_flower_get_icmpv4_code(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv4_code, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV4_CODE); + return 0; +} + +int rtnl_flower_set_icmpv4_code_mask(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv4_code_mask, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV4_CODE_MASK); + return 0; +} + +int rtnl_flower_get_icmpv4_code_mask(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv4_code_mask, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV4_CODE_MASK); + return 0; +} + +/* ICMPV4 TYPE sector */ +int rtnl_flower_set_icmpv4_type(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv4_type, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV4_TYPE); + return 0; +} + +int rtnl_flower_get_icmpv4_type(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv4_type, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV4_TYPE); + return 0; +} + +int rtnl_flower_set_icmpv4_type_mask(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv4_type_mask, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV4_TYPE_MASK); + return 0; +} + +int rtnl_flower_get_icmpv4_type_mask(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv4_type_mask, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV4_TYPE_MASK); + return 0; +} + +/* ICMPV6 CODE sector*/ +int rtnl_flower_set_icmpv6_code(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv6_code, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV6_CODE); + return 0; +} + +int rtnl_flower_get_icmpv6_code(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv6_code, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV6_CODE); + return 0; +} + +int rtnl_flower_set_icmpv6_code_mask(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv6_code_mask, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV6_CODE_MASK); + return 0; +} + +int rtnl_flower_get_icmpv6_code_mask(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv6_code_mask, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV6_CODE_MASK); + return 0; +} + +/* ICMPV6 TYPE sector*/ +int rtnl_flower_set_icmpv6_type(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv6_type, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV6_TYPE); + return 0; +} + +int rtnl_flower_get_icmpv6_type(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv6_type, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV6_TYPE); + return 0; +} + +int rtnl_flower_set_icmpv6_type_mask(struct rtnl_cls *cls, uint8_t val) +{ + SETTER(cls, fl_icmpv6_type_mask, &val, sizeof(val), + FLOWER_ATTR_KEY_ICMPV6_TYPE_MASK); + return 0; +} + +int rtnl_flower_get_icmpv6_type_mask(struct rtnl_cls *cls, uint8_t *val) +{ + GETTER(cls, fl_icmpv6_type_mask, val, sizeof(*val), + FLOWER_ATTR_KEY_ICMPV6_TYPE_MASK); + return 0; +} + /** @} */ static struct rtnl_tc_ops flower_ops = { --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -925,6 +925,24 @@ global: rtnl_flower_get_cvlan_prio; rtnl_flower_set_cvlan_eth_type; rtnl_flower_get_cvlan_eth_type; + rtnl_flower_set_ip_proto; + rtnl_flower_get_ip_proto; + rtnl_flower_set_icmpv4_code; + rtnl_flower_get_icmpv4_code; + rtnl_flower_set_icmpv4_code_mask; + rtnl_flower_get_icmpv4_code_mask; + rtnl_flower_set_icmpv4_type; + rtnl_flower_get_icmpv4_type; + rtnl_flower_set_icmpv4_type_mask; + rtnl_flower_get_icmpv4_type_mask; + rtnl_flower_set_icmpv6_code; + rtnl_flower_get_icmpv6_code; + rtnl_flower_set_icmpv6_code_mask; + rtnl_flower_get_icmpv6_code_mask; + rtnl_flower_set_icmpv6_type; + rtnl_flower_get_icmpv6_type; + rtnl_flower_set_icmpv6_type_mask; + rtnl_flower_get_icmpv6_type_mask; # The following symbols were added during the development of 3.2.26. # Keep them in libnl_3 to avoid breaking users.