net/mlx5: DR, Support IPv4 and IPv6 mixed matcher

Until now SW steering supported matchers that are IPv4 and IPv6.
The limitation was mixed matchers in which the outer header IP version
was different from the inner header IP version.

To support the mixed matcher we create all the possible ste_builder
combinations, once we create a rule we select the correct one to
be used for rule creation.

Signed-off-by: Alex Vesker <valex@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
Alex Vesker 2019-10-27 09:10:17 +02:00 committed by Saeed Mahameed
parent 1cdc14e9d1
commit 667f264676
3 changed files with 52 additions and 43 deletions

View File

@ -146,17 +146,15 @@ dr_matcher_supp_flex_parser_vxlan_gpe(struct mlx5dr_domain *dmn)
int mlx5dr_matcher_select_builders(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher,
bool ipv6)
enum mlx5dr_ipv outer_ipv,
enum mlx5dr_ipv inner_ipv)
{
if (ipv6) {
nic_matcher->ste_builder = nic_matcher->ste_builder6;
nic_matcher->num_of_builders = nic_matcher->num_of_builders6;
} else {
nic_matcher->ste_builder = nic_matcher->ste_builder4;
nic_matcher->num_of_builders = nic_matcher->num_of_builders4;
}
nic_matcher->ste_builder =
nic_matcher->ste_builder_arr[outer_ipv][inner_ipv];
nic_matcher->num_of_builders =
nic_matcher->num_of_builders_arr[outer_ipv][inner_ipv];
if (!nic_matcher->num_of_builders) {
if (!nic_matcher->ste_builder) {
mlx5dr_dbg(matcher->tbl->dmn,
"Rule not supported on this matcher due to IP related fields\n");
return -EINVAL;
@ -167,26 +165,19 @@ int mlx5dr_matcher_select_builders(struct mlx5dr_matcher *matcher,
static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher,
bool ipv6)
enum mlx5dr_ipv outer_ipv,
enum mlx5dr_ipv inner_ipv)
{
struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
struct mlx5dr_domain *dmn = matcher->tbl->dmn;
struct mlx5dr_match_param mask = {};
struct mlx5dr_match_misc3 *misc3;
struct mlx5dr_ste_build *sb;
u8 *num_of_builders;
bool inner, rx;
int idx = 0;
int ret, i;
if (ipv6) {
sb = nic_matcher->ste_builder6;
num_of_builders = &nic_matcher->num_of_builders6;
} else {
sb = nic_matcher->ste_builder4;
num_of_builders = &nic_matcher->num_of_builders4;
}
sb = nic_matcher->ste_builder_arr[outer_ipv][inner_ipv];
rx = nic_dmn->ste_type == MLX5DR_STE_TYPE_RX;
/* Create a temporary mask to track and clear used mask fields */
@ -249,7 +240,7 @@ static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher,
if (DR_MASK_IS_L2_DST(mask.outer, mask.misc, outer))
mlx5dr_ste_build_eth_l2_dst(&sb[idx++], &mask, inner, rx);
if (ipv6) {
if (outer_ipv == DR_RULE_IPV6) {
if (dr_mask_is_dst_addr_set(&mask.outer))
mlx5dr_ste_build_eth_l3_ipv6_dst(&sb[idx++], &mask,
inner, rx);
@ -325,7 +316,7 @@ static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher,
if (DR_MASK_IS_L2_DST(mask.inner, mask.misc, inner))
mlx5dr_ste_build_eth_l2_dst(&sb[idx++], &mask, inner, rx);
if (ipv6) {
if (inner_ipv == DR_RULE_IPV6) {
if (dr_mask_is_dst_addr_set(&mask.inner))
mlx5dr_ste_build_eth_l3_ipv6_dst(&sb[idx++], &mask,
inner, rx);
@ -373,7 +364,8 @@ static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher,
}
}
*num_of_builders = idx;
nic_matcher->ste_builder = sb;
nic_matcher->num_of_builders_arr[outer_ipv][inner_ipv] = idx;
return 0;
}
@ -524,24 +516,33 @@ static void dr_matcher_uninit(struct mlx5dr_matcher *matcher)
}
}
static int dr_matcher_init_nic(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher)
static int dr_matcher_set_all_ste_builders(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher)
{
struct mlx5dr_domain *dmn = matcher->tbl->dmn;
int ret, ret_v4, ret_v6;
ret_v4 = dr_matcher_set_ste_builders(matcher, nic_matcher, false);
ret_v6 = dr_matcher_set_ste_builders(matcher, nic_matcher, true);
dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV4, DR_RULE_IPV4);
dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV4, DR_RULE_IPV6);
dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV6, DR_RULE_IPV4);
dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV6, DR_RULE_IPV6);
if (ret_v4 && ret_v6) {
if (!nic_matcher->ste_builder) {
mlx5dr_dbg(dmn, "Cannot generate IPv4 or IPv6 rules with given mask\n");
return -EINVAL;
}
if (!ret_v4)
nic_matcher->ste_builder = nic_matcher->ste_builder4;
else
nic_matcher->ste_builder = nic_matcher->ste_builder6;
return 0;
}
static int dr_matcher_init_nic(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher)
{
struct mlx5dr_domain *dmn = matcher->tbl->dmn;
int ret;
ret = dr_matcher_set_all_ste_builders(matcher, nic_matcher);
if (ret)
return ret;
nic_matcher->e_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
DR_CHUNK_SIZE_1,

View File

@ -954,12 +954,12 @@ static int dr_rule_destroy_rule(struct mlx5dr_rule *rule)
return 0;
}
static bool dr_rule_is_ipv6(struct mlx5dr_match_param *param)
static enum mlx5dr_ipv dr_rule_get_ipv(struct mlx5dr_match_spec *spec)
{
return (param->outer.ip_version == 6 ||
param->inner.ip_version == 6 ||
param->outer.ethertype == ETH_P_IPV6 ||
param->inner.ethertype == ETH_P_IPV6);
if (spec->ip_version == 6 || spec->ethertype == ETH_P_IPV6)
return DR_RULE_IPV6;
return DR_RULE_IPV4;
}
static bool dr_rule_skip(enum mlx5dr_domain_type domain,
@ -1023,7 +1023,8 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule,
ret = mlx5dr_matcher_select_builders(matcher,
nic_matcher,
dr_rule_is_ipv6(param));
dr_rule_get_ipv(&param->outer),
dr_rule_get_ipv(&param->inner));
if (ret)
goto out_err;

View File

@ -106,6 +106,12 @@ enum mlx5dr_action_type {
DR_ACTION_TYP_MAX,
};
enum mlx5dr_ipv {
DR_RULE_IPV4,
DR_RULE_IPV6,
DR_RULE_IPV_MAX,
};
struct mlx5dr_icm_pool;
struct mlx5dr_icm_chunk;
struct mlx5dr_icm_bucket;
@ -679,11 +685,11 @@ struct mlx5dr_matcher_rx_tx {
struct mlx5dr_ste_htbl *s_htbl;
struct mlx5dr_ste_htbl *e_anchor;
struct mlx5dr_ste_build *ste_builder;
struct mlx5dr_ste_build ste_builder4[DR_RULE_MAX_STES];
struct mlx5dr_ste_build ste_builder6[DR_RULE_MAX_STES];
struct mlx5dr_ste_build ste_builder_arr[DR_RULE_IPV_MAX]
[DR_RULE_IPV_MAX]
[DR_RULE_MAX_STES];
u8 num_of_builders;
u8 num_of_builders4;
u8 num_of_builders6;
u8 num_of_builders_arr[DR_RULE_IPV_MAX][DR_RULE_IPV_MAX];
u64 default_icm_addr;
struct mlx5dr_table_rx_tx *nic_tbl;
};
@ -812,7 +818,8 @@ mlx5dr_matcher_supp_flex_parser_icmp_v6(struct mlx5dr_cmd_caps *caps)
int mlx5dr_matcher_select_builders(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher,
bool ipv6);
enum mlx5dr_ipv outer_ipv,
enum mlx5dr_ipv inner_ipv);
static inline u32
mlx5dr_icm_pool_chunk_size_to_entries(enum mlx5dr_icm_chunk_size chunk_size)