Commit 929a2fad authored by Dima Chumak's avatar Dima Chumak Committed by Saeed Mahameed

net/mlx5e: Consider geneve_opts for encap contexts

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: 7f1a546e ("net/mlx5e: Consider tunnel type for encap contexts")
Signed-off-by: default avatarDima Chumak <dchumak@nvidia.com>
Reviewed-by: default avatarVlad Buslov <vladbu@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent a7b76002
...@@ -21,6 +21,11 @@ enum { ...@@ -21,6 +21,11 @@ enum {
MLX5E_TC_TUNNEL_TYPE_MPLSOUDP, 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 { struct mlx5e_tc_tunnel {
int tunnel_type; int tunnel_type;
enum mlx5_flow_match_level match_level; enum mlx5_flow_match_level match_level;
...@@ -44,6 +49,8 @@ struct mlx5e_tc_tunnel { ...@@ -44,6 +49,8 @@ struct mlx5e_tc_tunnel {
struct flow_cls_offload *f, struct flow_cls_offload *f,
void *headers_c, void *headers_c,
void *headers_v); void *headers_v);
bool (*encap_info_equal)(struct mlx5e_encap_key *a,
struct mlx5e_encap_key *b);
}; };
extern struct mlx5e_tc_tunnel vxlan_tunnel; extern struct mlx5e_tc_tunnel vxlan_tunnel;
...@@ -101,6 +108,9 @@ int mlx5e_tc_tun_parse_udp_ports(struct mlx5e_priv *priv, ...@@ -101,6 +108,9 @@ int mlx5e_tc_tun_parse_udp_ports(struct mlx5e_priv *priv,
void *headers_c, void *headers_c,
void *headers_v); 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 /* CONFIG_MLX5_ESWITCH */
#endif //__MLX5_EN_TC_TUNNEL_H__ #endif //__MLX5_EN_TC_TUNNEL_H__
...@@ -476,16 +476,11 @@ void mlx5e_detach_decap(struct mlx5e_priv *priv, ...@@ -476,16 +476,11 @@ void mlx5e_detach_decap(struct mlx5e_priv *priv,
mlx5e_decap_dealloc(priv, d); mlx5e_decap_dealloc(priv, d);
} }
struct encap_key { bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a,
const struct ip_tunnel_key *ip_tun_key; struct mlx5e_encap_key *b)
struct mlx5e_tc_tunnel *tc_tunnel;
};
static int cmp_encap_info(struct encap_key *a,
struct encap_key *b)
{ {
return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) || 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; a->tc_tunnel->tunnel_type == b->tc_tunnel->tunnel_type;
} }
static int cmp_decap_info(struct mlx5e_decap_key *a, static int cmp_decap_info(struct mlx5e_decap_key *a,
...@@ -494,7 +489,7 @@ static int cmp_decap_info(struct mlx5e_decap_key *a, ...@@ -494,7 +489,7 @@ static int cmp_decap_info(struct mlx5e_decap_key *a,
return memcmp(&a->key, &b->key, sizeof(b->key)); 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), return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key),
key->tc_tunnel->tunnel_type); key->tc_tunnel->tunnel_type);
...@@ -516,18 +511,18 @@ static bool mlx5e_decap_take(struct mlx5e_decap_entry *e) ...@@ -516,18 +511,18 @@ static bool mlx5e_decap_take(struct mlx5e_decap_entry *e)
} }
static struct mlx5e_encap_entry * 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) uintptr_t hash_key)
{ {
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5e_encap_key e_key;
struct mlx5e_encap_entry *e; struct mlx5e_encap_entry *e;
struct encap_key e_key;
hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
encap_hlist, hash_key) { encap_hlist, hash_key) {
e_key.ip_tun_key = &e->tun_info->key; e_key.ip_tun_key = &e->tun_info->key;
e_key.tc_tunnel = e->tunnel; 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)) mlx5e_encap_take(e))
return e; return e;
} }
...@@ -694,8 +689,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, ...@@ -694,8 +689,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
struct mlx5_flow_attr *attr = flow->attr; struct mlx5_flow_attr *attr = flow->attr;
const struct ip_tunnel_info *tun_info; const struct ip_tunnel_info *tun_info;
unsigned long tbl_time_before = 0; unsigned long tbl_time_before = 0;
struct encap_key key;
struct mlx5e_encap_entry *e; struct mlx5e_encap_entry *e;
struct mlx5e_encap_key key;
bool entry_created = false; bool entry_created = false;
unsigned short family; unsigned short family;
uintptr_t hash_key; uintptr_t hash_key;
......
...@@ -329,6 +329,34 @@ static int mlx5e_tc_tun_parse_geneve(struct mlx5e_priv *priv, ...@@ -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); 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 = { struct mlx5e_tc_tunnel geneve_tunnel = {
.tunnel_type = MLX5E_TC_TUNNEL_TYPE_GENEVE, .tunnel_type = MLX5E_TC_TUNNEL_TYPE_GENEVE,
.match_level = MLX5_MATCH_L4, .match_level = MLX5_MATCH_L4,
...@@ -338,4 +366,5 @@ struct mlx5e_tc_tunnel geneve_tunnel = { ...@@ -338,4 +366,5 @@ struct mlx5e_tc_tunnel geneve_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_geneve, .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_geneve,
.parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_geneve, .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_geneve,
.parse_tunnel = mlx5e_tc_tun_parse_geneve, .parse_tunnel = mlx5e_tc_tun_parse_geneve,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_geneve,
}; };
...@@ -94,4 +94,5 @@ struct mlx5e_tc_tunnel gre_tunnel = { ...@@ -94,4 +94,5 @@ struct mlx5e_tc_tunnel gre_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_gretap, .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_gretap,
.parse_udp_ports = NULL, .parse_udp_ports = NULL,
.parse_tunnel = mlx5e_tc_tun_parse_gretap, .parse_tunnel = mlx5e_tc_tun_parse_gretap,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
}; };
...@@ -131,4 +131,5 @@ struct mlx5e_tc_tunnel mplsoudp_tunnel = { ...@@ -131,4 +131,5 @@ struct mlx5e_tc_tunnel mplsoudp_tunnel = {
.generate_ip_tun_hdr = generate_ip_tun_hdr, .generate_ip_tun_hdr = generate_ip_tun_hdr,
.parse_udp_ports = parse_udp_ports, .parse_udp_ports = parse_udp_ports,
.parse_tunnel = parse_tunnel, .parse_tunnel = parse_tunnel,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
}; };
...@@ -150,4 +150,5 @@ struct mlx5e_tc_tunnel vxlan_tunnel = { ...@@ -150,4 +150,5 @@ struct mlx5e_tc_tunnel vxlan_tunnel = {
.generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_vxlan, .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_vxlan,
.parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan, .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan,
.parse_tunnel = mlx5e_tc_tun_parse_vxlan, .parse_tunnel = mlx5e_tc_tun_parse_vxlan,
.encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment