Skip to content

Commit

Permalink
mlx5: DR, Add check for unsupported fields in match param
Browse files Browse the repository at this point in the history
When a matcher is being built, we "consume" (clear) mask fields one by
one, and to verify that we do support all the required fields we check
if the whole mask was consumed, else the matching request includes
unsupported fields.

Signed-off-by: Muhammad Sammar <muhammads@nvidia.com>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
  • Loading branch information
Muhammad Sammar authored and Yishai Hadas committed Jan 27, 2022
1 parent 5c4d000 commit 02e6759
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 194 deletions.
123 changes: 97 additions & 26 deletions providers/mlx5/dr_matcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,47 @@ static bool dr_mask_is_tnl_mpls_over_udp(struct dr_match_param *mask,
dr_matcher_supp_tnl_mpls_over_udp(&dmn->info.caps);
}

static bool dr_matcher_is_mask_consumed(struct dr_match_param *mask)
static bool dr_matcher_mask_is_all_zero(uint8_t *mask, uint32_t size)
{
int i;
return (*mask == 0) && memcmp(mask, mask + 1, size - 1) == 0;
}

static bool dr_matcher_is_mask_consumed(uint8_t *mask, uint8_t match_criteria)
{
/* Check that all mask data was consumed */
if (match_criteria & DR_MATCHER_CRITERIA_OUTER &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_spec)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_spec);

if (match_criteria & DR_MATCHER_CRITERIA_MISC &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_set_misc)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_set_misc);

if (match_criteria & DR_MATCHER_CRITERIA_INNER &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_spec)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_spec);

for (i = 0; i < sizeof(struct dr_match_param); i++)
if (((uint8_t *)mask)[i] != 0)
return false;
if (match_criteria & DR_MATCHER_CRITERIA_MISC2 &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_set_misc2)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_set_misc2);

if (match_criteria & DR_MATCHER_CRITERIA_MISC3 &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_set_misc3)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_set_misc3);

if (match_criteria & DR_MATCHER_CRITERIA_MISC4 &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_set_misc4)))
return false;
mask += DEVX_ST_SZ_BYTES(dr_match_set_misc4);

if (match_criteria & DR_MATCHER_CRITERIA_MISC5 &&
!dr_matcher_mask_is_all_zero(mask, DEVX_ST_SZ_BYTES(dr_match_set_misc5)))
return false;

return true;
}
Expand Down Expand Up @@ -542,7 +576,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (caps->definer_format_sup & (1 << DR_MATCHER_DEFINER_0)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def0(ste_ctx, &sb[idx++], &mask, caps, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -552,7 +586,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (dmn->info.caps.definer_format_sup & (1 << DR_MATCHER_DEFINER_2)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def2(ste_ctx, &sb[idx++], &mask, caps, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -562,7 +596,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (caps->definer_format_sup & (1 << DR_MATCHER_DEFINER_16)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def16(ste_ctx, &sb[idx++], &mask, caps, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -572,7 +606,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (caps->definer_format_sup & (1 << DR_MATCHER_DEFINER_22)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def22(ste_ctx, &sb[idx++], &mask, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -582,7 +616,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (caps->definer_format_sup & (1 << DR_MATCHER_DEFINER_24)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def24(ste_ctx, &sb[idx++], &mask, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -592,7 +626,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (caps->definer_format_sup & (1 << DR_MATCHER_DEFINER_25)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def25(ste_ctx, &sb[idx++], &mask, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand All @@ -607,7 +641,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (!ret && dst_ipv6)
ret = dr_ste_build_def6(ste_ctx, &sb[idx++], &mask, false, rx);

if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(&sb[0], 0, sizeof(*sb));
Expand All @@ -618,7 +652,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (dmn->info.caps.definer_format_sup & (1 << DR_MATCHER_DEFINER_28)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def28(ste_ctx, &sb[idx++], &mask, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(struct dr_ste_build));
Expand All @@ -628,7 +662,7 @@ static int dr_matcher_set_definer_builders(struct mlx5dv_dr_matcher *matcher,
if (dmn->info.caps.definer_format_sup & (1ULL << DR_MATCHER_DEFINER_33)) {
dr_matcher_copy_mask(&mask, &matcher->mask, matcher->match_criteria);
ret = dr_ste_build_def33(ste_ctx, &sb[idx++], &mask, false, rx);
if (!ret && dr_matcher_is_mask_consumed(&mask))
if (!ret && dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria))
goto done;

memset(sb, 0, sizeof(*sb));
Expand Down Expand Up @@ -933,7 +967,7 @@ static int dr_matcher_set_ste_builders(struct mlx5dv_dr_matcher *matcher,
}

/* Check that all mask fields were consumed */
if (!dr_matcher_is_mask_consumed(&mask)) {
if (!dr_matcher_is_mask_consumed((uint8_t *)&mask, matcher->match_criteria)) {
dr_dbg(dmn, "Mask contains unsupported parameters\n");
errno = EOPNOTSUPP;
return errno;
Expand Down Expand Up @@ -1196,31 +1230,68 @@ static bool dr_matcher_is_fixed_size(struct mlx5dv_dr_matcher *matcher)
return (matcher->rx.fixed_size || matcher->tx.fixed_size);
}

static int dr_matcher_init(struct mlx5dv_dr_matcher *matcher,
struct mlx5dv_flow_match_parameters *mask)
static int dr_matcher_copy_param(struct mlx5dv_dr_matcher *matcher,
struct mlx5dv_flow_match_parameters *mask)
{
struct mlx5dv_dr_table *tbl = matcher->tbl;
struct mlx5dv_dr_domain *dmn = tbl->dmn;
int ret;

if (dr_is_root_table(matcher->tbl))
return dr_matcher_init_root(matcher, mask);
struct mlx5dv_dr_domain *dmn = matcher->tbl->dmn;
uint8_t match_criteria = matcher->match_criteria;
uint64_t *consumed_mask_buf;
uint32_t max_mask_sz;
int ret = 0;

if (matcher->match_criteria >= DR_MATCHER_CRITERIA_MAX) {
if (match_criteria >= DR_MATCHER_CRITERIA_MAX) {
dr_dbg(dmn, "Invalid match criteria attribute\n");
errno = EINVAL;
return errno;
}

if (mask) {
if (mask->match_sz > DEVX_ST_SZ_BYTES(dr_match_param)) {
max_mask_sz = DEVX_ST_SZ_BYTES(dr_match_param);
if (mask->match_sz > max_mask_sz) {
dr_dbg(dmn, "Invalid match size attribute\n");
errno = EINVAL;
return errno;
}
dr_ste_copy_param(matcher->match_criteria, &matcher->mask, mask);

consumed_mask_buf = calloc(1, max_mask_sz);
if (!consumed_mask_buf) {
errno = ENOMEM;
return errno;
}

memcpy(consumed_mask_buf, mask->match_buf, mask->match_sz);
dr_ste_copy_param(match_criteria, &matcher->mask,
consumed_mask_buf, max_mask_sz, true);


ret = dr_matcher_is_mask_consumed((uint8_t *)consumed_mask_buf,
match_criteria);
if (!ret) {
dr_dbg(dmn, "Match param mask contains unsupported parameters\n");
errno = EOPNOTSUPP;
ret = errno;
}

free(consumed_mask_buf);
}

return 0;
}

static int dr_matcher_init(struct mlx5dv_dr_matcher *matcher,
struct mlx5dv_flow_match_parameters *mask)
{
struct mlx5dv_dr_table *tbl = matcher->tbl;
struct mlx5dv_dr_domain *dmn = tbl->dmn;
int ret;

if (dr_is_root_table(matcher->tbl))
return dr_matcher_init_root(matcher, mask);

ret = dr_matcher_copy_param(matcher, mask);
if (ret)
return ret;

switch (dmn->type) {
case MLX5DV_DR_DOMAIN_TYPE_NIC_RX:
matcher->rx.nic_tbl = &tbl->rx;
Expand Down
3 changes: 2 additions & 1 deletion providers/mlx5/dr_rule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,8 @@ static bool dr_rule_verify(struct mlx5dv_dr_matcher *matcher,
return false;
}

dr_ste_copy_param(matcher->match_criteria, param, value);
dr_ste_copy_param(matcher->match_criteria, param, value->match_buf,
value->match_sz, false);

if (match_criteria & DR_MATCHER_CRITERIA_OUTER) {
s_idx = offsetof(struct dr_match_param, outer);
Expand Down

0 comments on commit 02e6759

Please sign in to comment.