File Index
Files and directories
Sign in
FILE

vporttbl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/vporttbl.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2// Copyright (c) 2021 Mellanox Technologies.
  3
  4#include "eswitch.h"
  5
  6/* This struct is used as a key to the hash table and we need it to be packed
  7 * so hash result is consistent
  8 */
  9struct mlx5_vport_key {
 10	u32 chain;
 11	u16 prio;
 12	u16 vport;
 13	u16 vhca_id;
 14	struct esw_vport_tbl_namespace *vport_ns;
 15} __packed;
 16
 17struct mlx5_vport_table {
 18	struct hlist_node hlist;
 19	struct mlx5_flow_table *fdb;
 20	u32 num_rules;
 21	struct mlx5_vport_key key;
 22};
 23
 24static void
 25esw_vport_tbl_init(struct mlx5_eswitch *esw, struct esw_vport_tbl_namespace *ns)
 26{
 27	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
 28		ns->flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
 29			      MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 30}
 31
 32static struct mlx5_flow_table *
 33esw_vport_tbl_create(struct mlx5_eswitch *esw, struct mlx5_flow_namespace *ns,
 34		     const struct esw_vport_tbl_namespace *vport_ns)
 35{
 36	struct mlx5_flow_table_attr ft_attr = {};
 37	struct mlx5_flow_table *fdb;
 38
 39	if (vport_ns->max_num_groups)
 40		ft_attr.autogroup.max_num_groups = vport_ns->max_num_groups;
 41	else
 42		ft_attr.autogroup.max_num_groups = esw->params.large_group_num;
 43	ft_attr.max_fte = vport_ns->max_fte;
 44	ft_attr.prio = FDB_PER_VPORT;
 45	ft_attr.flags = vport_ns->flags;
 46	fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
 47	if (IS_ERR(fdb)) {
 48		esw_warn(esw->dev, "Failed to create per vport FDB Table err %pe\n",
 49			 fdb);
 50	}
 51
 52	return fdb;
 53}
 54
 55static u32 flow_attr_to_vport_key(struct mlx5_eswitch *esw,
 56				  struct mlx5_vport_tbl_attr *attr,
 57				  struct mlx5_vport_key *key)
 58{
 59	key->vport = attr->vport;
 60	key->chain = attr->chain;
 61	key->prio = attr->prio;
 62	key->vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
 63	key->vport_ns  = attr->vport_ns;
 64	return jhash(key, sizeof(*key), 0);
 65}
 66
 67/* caller must hold vports.lock */
 68static struct mlx5_vport_table *
 69esw_vport_tbl_lookup(struct mlx5_eswitch *esw, struct mlx5_vport_key *skey, u32 key)
 70{
 71	struct mlx5_vport_table *e;
 72
 73	hash_for_each_possible(esw->fdb_table.offloads.vports.table, e, hlist, key)
 74		if (!memcmp(&e->key, skey, sizeof(*skey)))
 75			return e;
 76
 77	return NULL;
 78}
 79
 80struct mlx5_flow_table *
 81mlx5_esw_vporttbl_get(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr)
 82{
 83	struct mlx5_core_dev *dev = esw->dev;
 84	struct mlx5_flow_namespace *ns;
 85	struct mlx5_flow_table *fdb;
 86	struct mlx5_vport_table *e;
 87	struct mlx5_vport_key skey;
 88	u32 hkey;
 89
 90	mutex_lock(&esw->fdb_table.offloads.vports.lock);
 91	esw_vport_tbl_init(esw, attr->vport_ns);
 92	hkey = flow_attr_to_vport_key(esw, attr, &skey);
 93	e = esw_vport_tbl_lookup(esw, &skey, hkey);
 94	if (e) {
 95		e->num_rules++;
 96		goto out;
 97	}
 98
 99	e = kzalloc(sizeof(*e), GFP_KERNEL);
100	if (!e) {
101		fdb = ERR_PTR(-ENOMEM);
102		goto err_alloc;
103	}
104
105	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
106	if (!ns) {
107		esw_warn(dev, "Failed to get FDB namespace\n");
108		fdb = ERR_PTR(-ENOENT);
109		goto err_ns;
110	}
111
112	fdb = esw_vport_tbl_create(esw, ns, attr->vport_ns);
113	if (IS_ERR(fdb))
114		goto err_ns;
115
116	e->fdb = fdb;
117	e->num_rules = 1;
118	e->key = skey;
119	hash_add(esw->fdb_table.offloads.vports.table, &e->hlist, hkey);
120out:
121	mutex_unlock(&esw->fdb_table.offloads.vports.lock);
122	return e->fdb;
123
124err_ns:
125	kfree(e);
126err_alloc:
127	mutex_unlock(&esw->fdb_table.offloads.vports.lock);
128	return fdb;
129}
130
131void
132mlx5_esw_vporttbl_put(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr)
133{
134	struct mlx5_vport_table *e;
135	struct mlx5_vport_key key;
136	u32 hkey;
137
138	mutex_lock(&esw->fdb_table.offloads.vports.lock);
139	esw_vport_tbl_init(esw, attr->vport_ns);
140	hkey = flow_attr_to_vport_key(esw, attr, &key);
141	e = esw_vport_tbl_lookup(esw, &key, hkey);
142	if (!e || --e->num_rules)
143		goto out;
144
145	hash_del(&e->hlist);
146	mlx5_destroy_flow_table(e->fdb);
147	kfree(e);
148out:
149	mutex_unlock(&esw->fdb_table.offloads.vports.lock);
150}
~/ Read-only file preview.