Skip to content

Commit

Permalink
net/mlx5e: Consider geneve_opts for encap contexts
Browse files Browse the repository at this point in the history
Current algorithm for encap keys is legacy from initial vxlan
implementation and doesn't take into account all possible fields of a
tunnel. For example, for a Geneve tunnel, which may have additional TLV
options, they are ignored when comparing encap keys and a rule can be
attached to an incorrect encap entry.

Fix that by introducing encap_info_equal() operation in
struct mlx5e_tc_tunnel. Geneve tunnel type uses custom implementation,
which extends generic algorithm and considers options if they are set.

Fixes: 7f1a546 ("net/mlx5e: Consider tunnel type for encap contexts")
Signed-off-by: Dima Chumak <dchumak@nvidia.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
  • Loading branch information
Dima Chumak authored and Saeed Mahameed committed Mar 31, 2021
1 parent a7b7600 commit 929a2fa
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 14 deletions.
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ enum {
MLX5E_TC_TUNNEL_TYPE_MPLSOUDP,
};

struct mlx5e_encap_key {
const struct ip_tunnel_key *ip_tun_key;
struct mlx5e_tc_tunnel *tc_tunnel;
};

struct mlx5e_tc_tunnel {
int tunnel_type;
enum mlx5_flow_match_level match_level;
Expand All @@ -44,6 +49,8 @@ struct mlx5e_tc_tunnel {
struct flow_cls_offload *f,
void *headers_c,
void *headers_v);
bool (*encap_info_equal)(struct mlx5e_encap_key *a,
struct mlx5e_encap_key *b);
};

extern struct mlx5e_tc_tunnel vxlan_tunnel;
Expand Down Expand Up @@ -101,6 +108,9 @@ int mlx5e_tc_tun_parse_udp_ports(struct mlx5e_priv *priv,
void *headers_c,
void *headers_v);

bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a,
struct mlx5e_encap_key *b);

#endif /* CONFIG_MLX5_ESWITCH */

#endif //__MLX5_EN_TC_TUNNEL_H__
23 changes: 9 additions & 14 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,16 +476,11 @@ void mlx5e_detach_decap(struct mlx5e_priv *priv,
mlx5e_decap_dealloc(priv, d);
}

struct encap_key {
const struct ip_tunnel_key *ip_tun_key;
struct mlx5e_tc_tunnel *tc_tunnel;
};

static int cmp_encap_info(struct encap_key *a,
struct encap_key *b)
bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a,
struct mlx5e_encap_key *b)
{
return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) ||
a->tc_tunnel->tunnel_type != b->tc_tunnel->tunnel_type;
return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) == 0 &&
a->tc_tunnel->tunnel_type == b->tc_tunnel->tunnel_type;
}

static int cmp_decap_info(struct mlx5e_decap_key *a,
Expand All @@ -494,7 +489,7 @@ static int cmp_decap_info(struct mlx5e_decap_key *a,
return memcmp(&a->key, &b->key, sizeof(b->key));
}

static int hash_encap_info(struct encap_key *key)
static int hash_encap_info(struct mlx5e_encap_key *key)
{
return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key),
key->tc_tunnel->tunnel_type);
Expand All @@ -516,18 +511,18 @@ static bool mlx5e_decap_take(struct mlx5e_decap_entry *e)
}

static struct mlx5e_encap_entry *
mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key,
mlx5e_encap_get(struct mlx5e_priv *priv, struct mlx5e_encap_key *key,
uintptr_t hash_key)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5e_encap_key e_key;
struct mlx5e_encap_entry *e;
struct encap_key e_key;

hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
encap_hlist, hash_key) {
e_key.ip_tun_key = &e->tun_info->key;
e_key.tc_tunnel = e->tunnel;
if (!cmp_encap_info(&e_key, key) &&
if (e->tunnel->encap_info_equal(&e_key, key) &&
mlx5e_encap_take(e))
return e;
}
Expand Down Expand Up @@ -694,8 +689,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
struct mlx5_flow_attr *attr = flow->attr;
const struct ip_tunnel_info *tun_info;
unsigned long tbl_time_before = 0;
struct encap_key key;
struct mlx5e_encap_entry *e;
struct mlx5e_encap_key key;
bool entry_created = false;
unsigned short family;
uintptr_t hash_key;
Expand Down
29 changes: 29 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,34 @@ static int mlx5e_tc_tun_parse_geneve(struct mlx5e_priv *priv,
return mlx5e_tc_tun_parse_geneve_options(priv, spec, f);
}

static bool mlx5e_tc_tun_encap_info_equal_geneve(struct mlx5e_encap_key *a,
struct mlx5e_encap_key *b)
{
struct ip_tunnel_info *a_info;
struct ip_tunnel_info *b_info;
bool a_has_opts, b_has_opts;

if (!mlx5e_tc_tun_encap_info_equal_generic(a, b))
return false;

a_has_opts = !!(a->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT);
b_has_opts = !!(b->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT);

/* keys are equal when both don't have any options attached */
if (!a_has_opts && !b_has_opts)
return true;

if (a_has_opts != b_has_opts)
return false;

/* geneve options stored in memory next to ip_tunnel_info struct */
a_info = container_of(a->ip_tun_key, struct ip_tunnel_info, key);
b_info = container_of(b->ip_tun_key, struct ip_tunnel_info, key);

return a_info->options_len == b_info->options_len &&
memcmp(a_info + 1, b_info + 1, a_info->options_len) == 0;
}

struct mlx5e_tc_tunnel geneve_tunnel = {
.tunnel_type = MLX5E_TC_TUNNEL_TYPE_GENEVE,
.match_level = MLX5_MATCH_L4,
Expand All @@ -338,4 +366,5 @@ struct mlx5e_tc_tunnel geneve_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_geneve,
.parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_geneve,
.parse_tunnel = mlx5e_tc_tun_parse_geneve,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_geneve,
};
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,5 @@ struct mlx5e_tc_tunnel gre_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_gretap,
.parse_udp_ports = NULL,
.parse_tunnel = mlx5e_tc_tun_parse_gretap,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
};
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,5 @@ struct mlx5e_tc_tunnel mplsoudp_tunnel = {
.generate_ip_tun_hdr = generate_ip_tun_hdr,
.parse_udp_ports = parse_udp_ports,
.parse_tunnel = parse_tunnel,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
};
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,5 @@ struct mlx5e_tc_tunnel vxlan_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_vxlan,
.parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan,
.parse_tunnel = mlx5e_tc_tun_parse_vxlan,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
};

0 comments on commit 929a2fa

Please sign in to comment.