]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
net/mlx5e: Fix hairpin RSS table size
[mirror_ubuntu-focal-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_tc.c
index c4c59d2e676e6affa279a251f5ba125dc9fa8111..947122c6849301116f85479c63356d844f9f47dc 100644 (file)
@@ -586,7 +586,7 @@ static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp,
        for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
                ttc_params->indir_tirn[tt] = hp->indir_tirn[tt];
 
-       ft_attr->max_fte = MLX5E_NUM_TT;
+       ft_attr->max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
        ft_attr->prio = MLX5E_TC_PRIO;
 }
@@ -1278,8 +1278,10 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
        mlx5_eswitch_del_vlan_action(esw, attr);
 
        for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
-               if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+               if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) {
                        mlx5e_detach_encap(priv, flow, out_index);
+                       kfree(attr->parse_attr->tun_info[out_index]);
+               }
        kvfree(attr->parse_attr);
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
@@ -1559,6 +1561,7 @@ static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entr
                        mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat);
        }
 
+       kfree(e->tun_info);
        kfree(e->encap_header);
        kfree_rcu(e, rcu);
 }
@@ -1613,7 +1616,7 @@ static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
        flow_flag_clear(flow, DUP);
 
        mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
-       kvfree(flow->peer_flow);
+       kfree(flow->peer_flow);
        flow->peer_flow = NULL;
 }
 
@@ -2972,6 +2975,13 @@ mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key,
        return NULL;
 }
 
+static struct ip_tunnel_info *dup_tun_info(const struct ip_tunnel_info *tun_info)
+{
+       size_t tun_size = sizeof(*tun_info) + tun_info->options_len;
+
+       return kmemdup(tun_info, tun_size, GFP_KERNEL);
+}
+
 static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow,
                              struct net_device *mirred_dev,
@@ -3028,13 +3038,15 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
        refcount_set(&e->refcnt, 1);
        init_completion(&e->res_ready);
 
+       tun_info = dup_tun_info(tun_info);
+       if (!tun_info) {
+               err = -ENOMEM;
+               goto out_err_init;
+       }
        e->tun_info = tun_info;
        err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack);
-       if (err) {
-               kfree(e);
-               e = NULL;
-               goto out_err;
-       }
+       if (err)
+               goto out_err_init;
 
        INIT_LIST_HEAD(&e->flows);
        hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
@@ -3075,6 +3087,12 @@ out_err:
        if (e)
                mlx5e_encap_put(priv, e);
        return err;
+
+out_err_init:
+       mutex_unlock(&esw->offloads.encap_tbl_lock);
+       kfree(tun_info);
+       kfree(e);
+       return err;
 }
 
 static int parse_tc_vlan_action(struct mlx5e_priv *priv,
@@ -3250,7 +3268,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
 
                        action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
                                  MLX5_FLOW_CONTEXT_ACTION_COUNT;
-                       if (netdev_port_same_parent_id(priv->netdev, out_dev)) {
+                       if (encap) {
+                               parse_attr->mirred_ifindex[attr->out_count] =
+                                       out_dev->ifindex;
+                               parse_attr->tun_info[attr->out_count] = dup_tun_info(info);
+                               if (!parse_attr->tun_info[attr->out_count])
+                                       return -ENOMEM;
+                               encap = false;
+                               attr->dests[attr->out_count].flags |=
+                                       MLX5_ESW_DEST_ENCAP;
+                               attr->out_count++;
+                               /* attr->dests[].rep is resolved when we
+                                * handle encap
+                                */
+                       } else if (netdev_port_same_parent_id(priv->netdev, out_dev)) {
                                struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
                                struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
                                struct net_device *uplink_upper;
@@ -3292,17 +3323,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                attr->dests[attr->out_count].rep = rpriv->rep;
                                attr->dests[attr->out_count].mdev = out_priv->mdev;
                                attr->out_count++;
-                       } else if (encap) {
-                               parse_attr->mirred_ifindex[attr->out_count] =
-                                       out_dev->ifindex;
-                               parse_attr->tun_info[attr->out_count] = info;
-                               encap = false;
-                               attr->dests[attr->out_count].flags |=
-                                       MLX5_ESW_DEST_ENCAP;
-                               attr->out_count++;
-                               /* attr->dests[].rep is resolved when we
-                                * handle encap
-                                */
                        } else if (parse_attr->filter_dev != priv->netdev) {
                                /* All mlx5 devices are called to configure
                                 * high level device filters. Therefore, the
@@ -3423,6 +3443,12 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
        }
 
+       if (!(attr->action &
+             (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
+               NL_SET_ERR_MSG(extack, "Rule must have at least one forward/drop action");
+               return -EOPNOTSUPP;
+       }
+
        if (attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "current firmware doesn't support split rule for port mirroring");
@@ -3980,9 +4006,8 @@ int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
                                struct tc_cls_matchall_offload *ma)
 {
        struct netlink_ext_ack *extack = ma->common.extack;
-       int prio = TC_H_MAJ(ma->common.prio) >> 16;
 
-       if (prio != 1) {
+       if (ma->common.prio != 1) {
                NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported");
                return -EINVAL;
        }