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

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
Loading
Loading
Loading
Loading
+43 −42
Original line number Diff line number Diff line
@@ -76,13 +76,14 @@ 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 |
		     MLX5_GET(fte_match_set_lyr_2_4, value, dmac_15_0)};
	MASK_VAL_L2(u16, ethertype, ethertype);
	MASK_VAL_L2(u8, ip_version, ip_version);

	PRINT_MASKED_VALP(smac, u8 *, p, "%pM");
	PRINT_MASKED_VALP(dmac, u8 *, p, "%pM");
	PRINT_MASKED_VAL(ethertype, p, "%04x");

	if (ethertype.m == 0xffff) {
		if (ethertype.v == ETH_P_IP) {
	if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IP) ||
	    (ip_version.m == 0xf && ip_version.v == 4)) {
#define MASK_VAL_L2_BE(type, name, fld) \
	MASK_VAL_BE(type, fte_match_set_lyr_2_4, name, mask, value, fld)
		MASK_VAL_L2_BE(u32, src_ipv4,
@@ -94,7 +95,8 @@ static void print_lyr_2_4_hdrs(struct trace_seq *p,
				  "%pI4");
		PRINT_MASKED_VALP(dst_ipv4, typeof(&dst_ipv4.v), p,
				  "%pI4");
		} else if (ethertype.v == ETH_P_IPV6) {
	} else if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IPV6) ||
		   (ip_version.m == 0xf && ip_version.v == 6)) {
		static const struct in6_addr full_ones = {
			.in6_u.u6_addr32 = {__constant_htonl(0xffffffff),
					    __constant_htonl(0xffffffff),
@@ -128,7 +130,6 @@ static void print_lyr_2_4_hdrs(struct trace_seq *p,
			trace_seq_printf(p, "dst_ipv6=%pI6 ",
					 &dst_ipv6.v);
	}
	}

#define PRINT_MASKED_VAL_L2(type, name, fld, p, format) {\
	MASK_VAL_L2(type, name, fld);		         \
+4 −3
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ mlx5_tc_ct_get_ct_priv(struct mlx5e_priv *priv)
}

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)
{
	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,

		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,
			 match.mask->ip_proto);
		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,
	attr->counter = entry->counter;
	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,
				    entry->zone & MLX5_CT_ZONE_MASK,
				    MLX5_CT_ZONE_MASK);
+4 −4
Original line number Diff line number Diff line
@@ -545,8 +545,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
				 ntohl(match.key->dst));

			key_basic.n_proto = htons(ETH_P_IP);
			mlx5e_tc_set_ethertype(headers_c, headers_v,
					       &match_basic);
			mlx5e_tc_set_ethertype(priv->mdev, &match_basic, true,
					       headers_c, headers_v);
		} else if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
			struct flow_match_ipv6_addrs match;

@@ -570,8 +570,8 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
								  ipv6));

			key_basic.n_proto = htons(ETH_P_IPV6);
			mlx5e_tc_set_ethertype(headers_c, headers_v,
					       &match_basic);
			mlx5e_tc_set_ethertype(priv->mdev, &match_basic, true,
					       headers_c, headers_v);
		}
	}

+31 −9
Original line number Diff line number Diff line
@@ -2020,14 +2020,31 @@ u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow)
	return flow->tunnel_id;
}

void mlx5e_tc_set_ethertype(void *headers_c, void *headers_v,
			    struct flow_match_basic *match)
{
void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev,
			    struct flow_match_basic *match, bool outer,
			    void *headers_c, void *headers_v)
{
	bool ip_version_cap;

	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,
			     struct mlx5e_tc_flow *flow,
@@ -2250,7 +2267,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
		struct flow_match_basic 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)
			*match_level = MLX5_MATCH_L2;
@@ -3126,16 +3145,19 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
{
	const struct flow_action_entry *act;
	bool modify_ip_header;
	void *headers_c;
	void *headers_v;
	u16 ethertype;
	u8 ip_proto;
	int i, err;

	headers_c = get_match_headers_criteria(actions, spec);
	headers_v = get_match_headers_value(actions, spec);
	ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);

	/* 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;

	modify_ip_header = false;
+3 −2
Original line number Diff line number Diff line
@@ -170,8 +170,9 @@ void dealloc_mod_hdr_actions(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts);
struct mlx5e_tc_flow;
u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow);

void mlx5e_tc_set_ethertype(void *headers_c, void *headers_v,
			    struct flow_match_basic *match);
void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev,
			    struct flow_match_basic *match, bool outer,
			    void *headers_c, void *headers_v);

#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)