Skip to content

Commit f41f3ed

Browse files
ddvladkuba-moo
authored andcommitted
net/mlx5: HWS, Disallow matcher IP version mixing
Signal clearly to the user, via an error, that mixing IPv4 and IPv6 rules in the same matcher is not supported. Previously such cases silently failed by adding a rule that did not work correctly. Rules can specify an IP version by one of two fields: IP version or ethertype. At matcher creation, store whether the template matches on any of these two fields. If yes, inspect each rule for its corresponding match value and store the IP version inside the matcher to guard against inconsistencies with subsequent rules. Furthermore, also check rules for internal consistency, i.e. verify that the ethertype and IP version match values do not contradict each other. The logic applies to inner and outer headers independently, to account for tunneling. Rules that do not match on IP addresses are not affected. Signed-off-by: Vlad Dogaru <[email protected]> Reviewed-by: Yevgeny Kliteynik <[email protected]> Signed-off-by: Mark Bloch <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 6991a97 commit f41f3ed

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,30 @@ static int hws_matcher_bind_at(struct mlx5hws_matcher *matcher)
385385
return 0;
386386
}
387387

388+
static void hws_matcher_set_ip_version_match(struct mlx5hws_matcher *matcher)
389+
{
390+
int i;
391+
392+
for (i = 0; i < matcher->mt->fc_sz; i++) {
393+
switch (matcher->mt->fc[i].fname) {
394+
case MLX5HWS_DEFINER_FNAME_ETH_TYPE_O:
395+
matcher->matches_outer_ethertype = 1;
396+
break;
397+
case MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_O:
398+
matcher->matches_outer_ip_version = 1;
399+
break;
400+
case MLX5HWS_DEFINER_FNAME_ETH_TYPE_I:
401+
matcher->matches_inner_ethertype = 1;
402+
break;
403+
case MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_I:
404+
matcher->matches_inner_ip_version = 1;
405+
break;
406+
default:
407+
break;
408+
}
409+
}
410+
}
411+
388412
static int hws_matcher_bind_mt(struct mlx5hws_matcher *matcher)
389413
{
390414
struct mlx5hws_context *ctx = matcher->tbl->ctx;
@@ -401,6 +425,8 @@ static int hws_matcher_bind_mt(struct mlx5hws_matcher *matcher)
401425
}
402426
}
403427

428+
hws_matcher_set_ip_version_match(matcher);
429+
404430
/* Create an STE pool per matcher*/
405431
pool_attr.table_type = matcher->tbl->type;
406432
pool_attr.pool_type = MLX5HWS_POOL_TYPE_STE;

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ struct mlx5hws_matcher_match_ste {
5050
struct mlx5hws_pool *pool;
5151
};
5252

53+
enum {
54+
MLX5HWS_MATCHER_IPV_UNSET = 0,
55+
MLX5HWS_MATCHER_IPV_4 = 1,
56+
MLX5HWS_MATCHER_IPV_6 = 2,
57+
};
58+
5359
struct mlx5hws_matcher {
5460
struct mlx5hws_table *tbl;
5561
struct mlx5hws_matcher_attr attr;
@@ -61,6 +67,12 @@ struct mlx5hws_matcher {
6167
u8 num_of_action_stes;
6268
/* enum mlx5hws_matcher_flags */
6369
u8 flags;
70+
u8 matches_outer_ethertype:1;
71+
u8 matches_outer_ip_version:1;
72+
u8 matches_inner_ethertype:1;
73+
u8 matches_inner_ip_version:1;
74+
u8 outer_ip_version:2;
75+
u8 inner_ip_version:2;
6476
u32 end_ft_id;
6577
struct mlx5hws_matcher *col_matcher;
6678
struct mlx5hws_matcher *resize_dst;

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,124 @@ int mlx5hws_rule_move_hws_add(struct mlx5hws_rule *rule,
655655
return 0;
656656
}
657657

658+
static u8 hws_rule_ethertype_to_matcher_ipv(u32 ethertype)
659+
{
660+
switch (ethertype) {
661+
case ETH_P_IP:
662+
return MLX5HWS_MATCHER_IPV_4;
663+
case ETH_P_IPV6:
664+
return MLX5HWS_MATCHER_IPV_6;
665+
default:
666+
return MLX5HWS_MATCHER_IPV_UNSET;
667+
}
668+
}
669+
670+
static u8 hws_rule_ip_version_to_matcher_ipv(u32 ip_version)
671+
{
672+
switch (ip_version) {
673+
case 4:
674+
return MLX5HWS_MATCHER_IPV_4;
675+
case 6:
676+
return MLX5HWS_MATCHER_IPV_6;
677+
default:
678+
return MLX5HWS_MATCHER_IPV_UNSET;
679+
}
680+
}
681+
682+
static int hws_rule_check_outer_ip_version(struct mlx5hws_matcher *matcher,
683+
u32 *match_param)
684+
{
685+
struct mlx5hws_context *ctx = matcher->tbl->ctx;
686+
u8 outer_ipv_ether = MLX5HWS_MATCHER_IPV_UNSET;
687+
u8 outer_ipv_ip = MLX5HWS_MATCHER_IPV_UNSET;
688+
u8 outer_ipv, ver;
689+
690+
if (matcher->matches_outer_ethertype) {
691+
ver = MLX5_GET(fte_match_param, match_param,
692+
outer_headers.ethertype);
693+
outer_ipv_ether = hws_rule_ethertype_to_matcher_ipv(ver);
694+
}
695+
if (matcher->matches_outer_ip_version) {
696+
ver = MLX5_GET(fte_match_param, match_param,
697+
outer_headers.ip_version);
698+
outer_ipv_ip = hws_rule_ip_version_to_matcher_ipv(ver);
699+
}
700+
701+
if (outer_ipv_ether != MLX5HWS_MATCHER_IPV_UNSET &&
702+
outer_ipv_ip != MLX5HWS_MATCHER_IPV_UNSET &&
703+
outer_ipv_ether != outer_ipv_ip) {
704+
mlx5hws_err(ctx, "Rule matches on inconsistent outer ethertype and ip version\n");
705+
return -EINVAL;
706+
}
707+
708+
outer_ipv = outer_ipv_ether != MLX5HWS_MATCHER_IPV_UNSET ?
709+
outer_ipv_ether : outer_ipv_ip;
710+
if (outer_ipv != MLX5HWS_MATCHER_IPV_UNSET &&
711+
matcher->outer_ip_version != MLX5HWS_MATCHER_IPV_UNSET &&
712+
outer_ipv != matcher->outer_ip_version) {
713+
mlx5hws_err(ctx, "Matcher and rule disagree on outer IP version\n");
714+
return -EINVAL;
715+
}
716+
matcher->outer_ip_version = outer_ipv;
717+
718+
return 0;
719+
}
720+
721+
static int hws_rule_check_inner_ip_version(struct mlx5hws_matcher *matcher,
722+
u32 *match_param)
723+
{
724+
struct mlx5hws_context *ctx = matcher->tbl->ctx;
725+
u8 inner_ipv_ether = MLX5HWS_MATCHER_IPV_UNSET;
726+
u8 inner_ipv_ip = MLX5HWS_MATCHER_IPV_UNSET;
727+
u8 inner_ipv, ver;
728+
729+
if (matcher->matches_inner_ethertype) {
730+
ver = MLX5_GET(fte_match_param, match_param,
731+
inner_headers.ethertype);
732+
inner_ipv_ether = hws_rule_ethertype_to_matcher_ipv(ver);
733+
}
734+
if (matcher->matches_inner_ip_version) {
735+
ver = MLX5_GET(fte_match_param, match_param,
736+
inner_headers.ip_version);
737+
inner_ipv_ip = hws_rule_ip_version_to_matcher_ipv(ver);
738+
}
739+
740+
if (inner_ipv_ether != MLX5HWS_MATCHER_IPV_UNSET &&
741+
inner_ipv_ip != MLX5HWS_MATCHER_IPV_UNSET &&
742+
inner_ipv_ether != inner_ipv_ip) {
743+
mlx5hws_err(ctx, "Rule matches on inconsistent inner ethertype and ip version\n");
744+
return -EINVAL;
745+
}
746+
747+
inner_ipv = inner_ipv_ether != MLX5HWS_MATCHER_IPV_UNSET ?
748+
inner_ipv_ether : inner_ipv_ip;
749+
if (inner_ipv != MLX5HWS_MATCHER_IPV_UNSET &&
750+
matcher->inner_ip_version != MLX5HWS_MATCHER_IPV_UNSET &&
751+
inner_ipv != matcher->inner_ip_version) {
752+
mlx5hws_err(ctx, "Matcher and rule disagree on inner IP version\n");
753+
return -EINVAL;
754+
}
755+
matcher->inner_ip_version = inner_ipv;
756+
757+
return 0;
758+
}
759+
760+
static int hws_rule_check_ip_version(struct mlx5hws_matcher *matcher,
761+
u32 *match_param)
762+
{
763+
int ret;
764+
765+
ret = hws_rule_check_outer_ip_version(matcher, match_param);
766+
if (unlikely(ret))
767+
return ret;
768+
769+
ret = hws_rule_check_inner_ip_version(matcher, match_param);
770+
if (unlikely(ret))
771+
return ret;
772+
773+
return 0;
774+
}
775+
658776
int mlx5hws_rule_create(struct mlx5hws_matcher *matcher,
659777
u8 mt_idx,
660778
u32 *match_param,
@@ -665,6 +783,10 @@ int mlx5hws_rule_create(struct mlx5hws_matcher *matcher,
665783
{
666784
int ret;
667785

786+
ret = hws_rule_check_ip_version(matcher, match_param);
787+
if (unlikely(ret))
788+
return ret;
789+
668790
rule_handle->matcher = matcher;
669791

670792
ret = hws_rule_enqueue_precheck_create(rule_handle, attr);

0 commit comments

Comments
 (0)