Commit 6363651d authored by Or Gerlitz's avatar Or Gerlitz Committed by Saeed Mahameed

net/mlx5e: Properly set steering match levels for offloaded TC decap rules

The match level computed by the driver gets to be wrong for decap
rules with wildcarded inner packet match such as:

tc filter add dev vxlan_sys_4789 protocol all parent ffff: prio 2 flower
       enc_dst_ip 192.168.0.9 enc_key_id 100 enc_dst_port 4789
       action tunnel_key unset
       action mirred egress redirect dev eth1

The FW errs for a missing matching meta-data indicator for the outer
headers (where we do have a match), and a wrong matching meta-data
indicator for the inner headers (where we don't have a match).

Fix that by taking into account the matching on the tunnel info and
relating the match level of the encapsulated packet to the firmware
inner headers indicator in case of decap.

As for vxlan we mandate a match on the tunnel udp dst port, and in general
we practically madndate a match on the source or dest ip for any IP tunnel,
the fix was done in a minimal manner around the tunnel match parsing code.

Fixes: d708f902 ('net/mlx5e: Get the required HW match level while parsing TC flow matches')
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Reported-by: default avatarSlava Ovsiienko <viacheslavo@mellanox.com>
Reviewed-by: default avatarJianbo Liu <jianbol@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 82eaa1fa
...@@ -612,16 +612,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, ...@@ -612,16 +612,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
struct mlx5_flow_spec *spec, struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f, struct tc_cls_flower_offload *f,
void *headers_c, void *headers_c,
void *headers_v) void *headers_v, u8 *match_level)
{ {
int tunnel_type; int tunnel_type;
int err = 0; int err = 0;
tunnel_type = mlx5e_tc_tun_get_type(filter_dev); tunnel_type = mlx5e_tc_tun_get_type(filter_dev);
if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) { if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
*match_level = MLX5_MATCH_L4;
err = mlx5e_tc_tun_parse_vxlan(priv, spec, f, err = mlx5e_tc_tun_parse_vxlan(priv, spec, f,
headers_c, headers_v); headers_c, headers_v);
} else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) { } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) {
*match_level = MLX5_MATCH_L3;
err = mlx5e_tc_tun_parse_gretap(priv, spec, f, err = mlx5e_tc_tun_parse_gretap(priv, spec, f,
headers_c, headers_v); headers_c, headers_v);
} else { } else {
......
...@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, ...@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
struct mlx5_flow_spec *spec, struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f, struct tc_cls_flower_offload *f,
void *headers_c, void *headers_c,
void *headers_v); void *headers_v, u8 *match_level);
#endif //__MLX5_EN_TC_TUNNEL_H__ #endif //__MLX5_EN_TC_TUNNEL_H__
...@@ -1302,7 +1302,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, ...@@ -1302,7 +1302,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
static int parse_tunnel_attr(struct mlx5e_priv *priv, static int parse_tunnel_attr(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec, struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f, struct tc_cls_flower_offload *f,
struct net_device *filter_dev) struct net_device *filter_dev, u8 *match_level)
{ {
struct netlink_ext_ack *extack = f->common.extack; struct netlink_ext_ack *extack = f->common.extack;
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
...@@ -1317,7 +1317,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, ...@@ -1317,7 +1317,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
int err = 0; int err = 0;
err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f, err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
headers_c, headers_v); headers_c, headers_v, match_level);
if (err) { if (err) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"failed to parse tunnel attributes"); "failed to parse tunnel attributes");
...@@ -1426,7 +1426,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, ...@@ -1426,7 +1426,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec, struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f, struct tc_cls_flower_offload *f,
struct net_device *filter_dev, struct net_device *filter_dev,
u8 *match_level) u8 *match_level, u8 *tunnel_match_level)
{ {
struct netlink_ext_ack *extack = f->common.extack; struct netlink_ext_ack *extack = f->common.extack;
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
...@@ -1477,7 +1477,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, ...@@ -1477,7 +1477,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
switch (key->addr_type) { switch (key->addr_type) {
case FLOW_DISSECTOR_KEY_IPV4_ADDRS: case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
case FLOW_DISSECTOR_KEY_IPV6_ADDRS: case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
if (parse_tunnel_attr(priv, spec, f, filter_dev)) if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
return -EOPNOTSUPP; return -EOPNOTSUPP;
break; break;
default: default:
...@@ -1826,11 +1826,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv, ...@@ -1826,11 +1826,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_core_dev *dev = priv->mdev; struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_eswitch *esw = dev->priv.eswitch; struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5e_rep_priv *rpriv = priv->ppriv;
u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
struct mlx5_eswitch_rep *rep; struct mlx5_eswitch_rep *rep;
u8 match_level;
int err; int err;
err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level); err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) { if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
rep = rpriv->rep; rep = rpriv->rep;
...@@ -1846,10 +1846,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv, ...@@ -1846,10 +1846,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
} }
} }
if (flow->flags & MLX5E_TC_FLOW_ESWITCH) if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
flow->esw_attr->match_level = match_level; flow->esw_attr->match_level = match_level;
else flow->esw_attr->tunnel_match_level = tunnel_match_level;
} else {
flow->nic_attr->match_level = match_level; flow->nic_attr->match_level = match_level;
}
return err; return err;
} }
......
...@@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr { ...@@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr {
} dests[MLX5_MAX_FLOW_FWD_VPORTS]; } dests[MLX5_MAX_FLOW_FWD_VPORTS];
u32 mod_hdr_id; u32 mod_hdr_id;
u8 match_level; u8 match_level;
u8 tunnel_match_level;
struct mlx5_fc *counter; struct mlx5_fc *counter;
u32 chain; u32 chain;
u16 prio; u16 prio;
......
...@@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, ...@@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
MLX5_SET_TO_ONES(fte_match_set_misc, misc, MLX5_SET_TO_ONES(fte_match_set_misc, misc,
source_eswitch_owner_vhca_id); source_eswitch_owner_vhca_id);
if (attr->match_level == MLX5_MATCH_NONE)
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | if (attr->tunnel_match_level != MLX5_MATCH_NONE)
MLX5_MATCH_MISC_PARAMETERS; spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
if (attr->match_level != MLX5_MATCH_NONE)
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS; spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
} else if (attr->match_level != MLX5_MATCH_NONE) {
spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
}
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
flow_act.modify_id = attr->mod_hdr_id; flow_act.modify_id = attr->mod_hdr_id;
......
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