Commit fca53304 authored by Eli Britstein's avatar Eli Britstein Committed by Saeed Mahameed

net/mlx5e: Optimize performance for IPv4/IPv6 ethertype

The HW is optimized for IPv4/IPv6. For such cases, pending capability,
avoid matching on ethertype, and use ip_version field instead.
Signed-off-by: default avatarEli Britstein <elibr@mellanox.com>
Reviewed-by: default avatarRoi Dayan <roid@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 4a5d5d73
...@@ -76,58 +76,59 @@ static void print_lyr_2_4_hdrs(struct trace_seq *p, ...@@ -76,58 +76,59 @@ static void print_lyr_2_4_hdrs(struct trace_seq *p,
.v = MLX5_GET(fte_match_set_lyr_2_4, value, dmac_47_16) << 16 | .v = MLX5_GET(fte_match_set_lyr_2_4, value, dmac_47_16) << 16 |
MLX5_GET(fte_match_set_lyr_2_4, value, dmac_15_0)}; MLX5_GET(fte_match_set_lyr_2_4, value, dmac_15_0)};
MASK_VAL_L2(u16, ethertype, ethertype); MASK_VAL_L2(u16, ethertype, ethertype);
MASK_VAL_L2(u8, ip_version, ip_version);
PRINT_MASKED_VALP(smac, u8 *, p, "%pM"); PRINT_MASKED_VALP(smac, u8 *, p, "%pM");
PRINT_MASKED_VALP(dmac, u8 *, p, "%pM"); PRINT_MASKED_VALP(dmac, u8 *, p, "%pM");
PRINT_MASKED_VAL(ethertype, p, "%04x"); PRINT_MASKED_VAL(ethertype, p, "%04x");
if (ethertype.m == 0xffff) { if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IP) ||
if (ethertype.v == ETH_P_IP) { (ip_version.m == 0xf && ip_version.v == 4)) {
#define MASK_VAL_L2_BE(type, name, fld) \ #define MASK_VAL_L2_BE(type, name, fld) \
MASK_VAL_BE(type, fte_match_set_lyr_2_4, name, mask, value, fld) MASK_VAL_BE(type, fte_match_set_lyr_2_4, name, mask, value, fld)
MASK_VAL_L2_BE(u32, src_ipv4, MASK_VAL_L2_BE(u32, src_ipv4,
src_ipv4_src_ipv6.ipv4_layout.ipv4); src_ipv4_src_ipv6.ipv4_layout.ipv4);
MASK_VAL_L2_BE(u32, dst_ipv4, MASK_VAL_L2_BE(u32, dst_ipv4,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4); dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
PRINT_MASKED_VALP(src_ipv4, typeof(&src_ipv4.v), p, PRINT_MASKED_VALP(src_ipv4, typeof(&src_ipv4.v), p,
"%pI4"); "%pI4");
PRINT_MASKED_VALP(dst_ipv4, typeof(&dst_ipv4.v), p, PRINT_MASKED_VALP(dst_ipv4, typeof(&dst_ipv4.v), p,
"%pI4"); "%pI4");
} else if (ethertype.v == ETH_P_IPV6) { } else if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IPV6) ||
static const struct in6_addr full_ones = { (ip_version.m == 0xf && ip_version.v == 6)) {
.in6_u.u6_addr32 = {__constant_htonl(0xffffffff), static const struct in6_addr full_ones = {
__constant_htonl(0xffffffff), .in6_u.u6_addr32 = {__constant_htonl(0xffffffff),
__constant_htonl(0xffffffff), __constant_htonl(0xffffffff),
__constant_htonl(0xffffffff)}, __constant_htonl(0xffffffff),
}; __constant_htonl(0xffffffff)},
DECLARE_MASK_VAL(struct in6_addr, src_ipv6); };
DECLARE_MASK_VAL(struct in6_addr, dst_ipv6); DECLARE_MASK_VAL(struct in6_addr, src_ipv6);
DECLARE_MASK_VAL(struct in6_addr, dst_ipv6);
memcpy(src_ipv6.m.in6_u.u6_addr8, memcpy(src_ipv6.m.in6_u.u6_addr8,
MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
src_ipv4_src_ipv6.ipv6_layout.ipv6), src_ipv4_src_ipv6.ipv6_layout.ipv6),
sizeof(src_ipv6.m)); sizeof(src_ipv6.m));
memcpy(dst_ipv6.m.in6_u.u6_addr8, memcpy(dst_ipv6.m.in6_u.u6_addr8,
MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6), dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
sizeof(dst_ipv6.m)); sizeof(dst_ipv6.m));
memcpy(src_ipv6.v.in6_u.u6_addr8, memcpy(src_ipv6.v.in6_u.u6_addr8,
MLX5_ADDR_OF(fte_match_set_lyr_2_4, value, MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
src_ipv4_src_ipv6.ipv6_layout.ipv6), src_ipv4_src_ipv6.ipv6_layout.ipv6),
sizeof(src_ipv6.v)); sizeof(src_ipv6.v));
memcpy(dst_ipv6.v.in6_u.u6_addr8, memcpy(dst_ipv6.v.in6_u.u6_addr8,
MLX5_ADDR_OF(fte_match_set_lyr_2_4, value, MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6), dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
sizeof(dst_ipv6.v)); sizeof(dst_ipv6.v));
if (!memcmp(&src_ipv6.m, &full_ones, sizeof(full_ones))) if (!memcmp(&src_ipv6.m, &full_ones, sizeof(full_ones)))
trace_seq_printf(p, "src_ipv6=%pI6 ", trace_seq_printf(p, "src_ipv6=%pI6 ",
&src_ipv6.v); &src_ipv6.v);
if (!memcmp(&dst_ipv6.m, &full_ones, sizeof(full_ones))) if (!memcmp(&dst_ipv6.m, &full_ones, sizeof(full_ones)))
trace_seq_printf(p, "dst_ipv6=%pI6 ", trace_seq_printf(p, "dst_ipv6=%pI6 ",
&dst_ipv6.v); &dst_ipv6.v);
}
} }
#define PRINT_MASKED_VAL_L2(type, name, fld, p, format) {\ #define PRINT_MASKED_VAL_L2(type, name, fld, p, format) {\
......
...@@ -119,7 +119,7 @@ mlx5_tc_ct_get_ct_priv(struct mlx5e_priv *priv) ...@@ -119,7 +119,7 @@ mlx5_tc_ct_get_ct_priv(struct mlx5e_priv *priv)
} }
static int static int
mlx5_tc_ct_set_tuple_match(struct mlx5_flow_spec *spec, mlx5_tc_ct_set_tuple_match(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec,
struct flow_rule *rule) struct flow_rule *rule)
{ {
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
...@@ -134,7 +134,8 @@ mlx5_tc_ct_set_tuple_match(struct mlx5_flow_spec *spec, ...@@ -134,7 +134,8 @@ mlx5_tc_ct_set_tuple_match(struct mlx5_flow_spec *spec,
flow_rule_match_basic(rule, &match); flow_rule_match_basic(rule, &match);
mlx5e_tc_set_ethertype(headers_c, headers_v, &match); mlx5e_tc_set_ethertype(priv->mdev, &match, true, headers_c,
headers_v);
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol, MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
match.mask->ip_proto); match.mask->ip_proto);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
...@@ -530,7 +531,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, ...@@ -530,7 +531,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
attr->counter = entry->counter; attr->counter = entry->counter;
attr->flags |= MLX5_ESW_ATTR_FLAG_NO_IN_PORT; attr->flags |= MLX5_ESW_ATTR_FLAG_NO_IN_PORT;
mlx5_tc_ct_set_tuple_match(spec, flow_rule); mlx5_tc_ct_set_tuple_match(netdev_priv(ct_priv->netdev), spec, flow_rule);
mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG,
entry->zone & MLX5_CT_ZONE_MASK, entry->zone & MLX5_CT_ZONE_MASK,
MLX5_CT_ZONE_MASK); MLX5_CT_ZONE_MASK);
......
...@@ -545,8 +545,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, ...@@ -545,8 +545,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
ntohl(match.key->dst)); ntohl(match.key->dst));
key_basic.n_proto = htons(ETH_P_IP); key_basic.n_proto = htons(ETH_P_IP);
mlx5e_tc_set_ethertype(headers_c, headers_v, mlx5e_tc_set_ethertype(priv->mdev, &match_basic, true,
&match_basic); headers_c, headers_v);
} else if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { } else if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
struct flow_match_ipv6_addrs match; struct flow_match_ipv6_addrs match;
...@@ -570,8 +570,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, ...@@ -570,8 +570,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
ipv6)); ipv6));
key_basic.n_proto = htons(ETH_P_IPV6); key_basic.n_proto = htons(ETH_P_IPV6);
mlx5e_tc_set_ethertype(headers_c, headers_v, mlx5e_tc_set_ethertype(priv->mdev, &match_basic, true,
&match_basic); headers_c, headers_v);
} }
} }
......
...@@ -2020,13 +2020,30 @@ u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow) ...@@ -2020,13 +2020,30 @@ u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow)
return flow->tunnel_id; return flow->tunnel_id;
} }
void mlx5e_tc_set_ethertype(void *headers_c, void *headers_v, void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev,
struct flow_match_basic *match) struct flow_match_basic *match, bool outer,
{ void *headers_c, void *headers_v)
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype, {
ntohs(match->mask->n_proto)); bool ip_version_cap;
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
ntohs(match->key->n_proto)); ip_version_cap = outer ?
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
ft_field_support.outer_ip_version) :
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
ft_field_support.inner_ip_version);
if (ip_version_cap && match->mask->n_proto == htons(0xFFFF) &&
(match->key->n_proto == htons(ETH_P_IP) ||
match->key->n_proto == htons(ETH_P_IPV6))) {
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_version);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
match->key->n_proto == htons(ETH_P_IP) ? 4 : 6);
} else {
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
ntohs(match->mask->n_proto));
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
ntohs(match->key->n_proto));
}
} }
static int parse_tunnel_attr(struct mlx5e_priv *priv, static int parse_tunnel_attr(struct mlx5e_priv *priv,
...@@ -2250,7 +2267,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, ...@@ -2250,7 +2267,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct flow_match_basic match; struct flow_match_basic match;
flow_rule_match_basic(rule, &match); flow_rule_match_basic(rule, &match);
mlx5e_tc_set_ethertype(headers_c, headers_v, &match); mlx5e_tc_set_ethertype(priv->mdev, &match,
match_level == outer_match_level,
headers_c, headers_v);
if (match.mask->n_proto) if (match.mask->n_proto)
*match_level = MLX5_MATCH_L2; *match_level = MLX5_MATCH_L2;
...@@ -3126,16 +3145,19 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec, ...@@ -3126,16 +3145,19 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
{ {
const struct flow_action_entry *act; const struct flow_action_entry *act;
bool modify_ip_header; bool modify_ip_header;
void *headers_c;
void *headers_v; void *headers_v;
u16 ethertype; u16 ethertype;
u8 ip_proto; u8 ip_proto;
int i, err; int i, err;
headers_c = get_match_headers_criteria(actions, spec);
headers_v = get_match_headers_value(actions, spec); headers_v = get_match_headers_value(actions, spec);
ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
/* for non-IP we only re-write MACs, so we're okay */ /* for non-IP we only re-write MACs, so we're okay */
if (ethertype != ETH_P_IP && ethertype != ETH_P_IPV6) if (MLX5_GET(fte_match_set_lyr_2_4, headers_c, ip_version) == 0 &&
ethertype != ETH_P_IP && ethertype != ETH_P_IPV6)
goto out_ok; goto out_ok;
modify_ip_header = false; modify_ip_header = false;
......
...@@ -170,8 +170,9 @@ void dealloc_mod_hdr_actions(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts); ...@@ -170,8 +170,9 @@ void dealloc_mod_hdr_actions(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts);
struct mlx5e_tc_flow; struct mlx5e_tc_flow;
u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow); u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow);
void mlx5e_tc_set_ethertype(void *headers_c, void *headers_v, void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev,
struct flow_match_basic *match); struct flow_match_basic *match, bool outer,
void *headers_c, void *headers_v);
#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment