Skip to content

Commit 7838e17

Browse files
alexveskerSaeed Mahameed
authored andcommitted
net/mlx5: DR, Expose steering table functionality
Tables are objects which are used for storing matchers, each table belongs to a domain and defined by the domain type. When a packet reaches the table it is being processed by each of its matchers until a successful match. Tables can hold multiple matchers ordered by matcher priority. Each table has a level. Signed-off-by: Alex Vesker <valex@mellanox.com> Reviewed-by: Erez Shitrit <erezsh@mellanox.com> Reviewed-by: Mark Bloch <markb@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
1 parent 4ec9e7b commit 7838e17

File tree

1 file changed

+294
-0
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/steering

1 file changed

+294
-0
lines changed
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2+
/* Copyright (c) 2019 Mellanox Technologies. */
3+
4+
#include "dr_types.h"
5+
6+
int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
7+
struct mlx5dr_action *action)
8+
{
9+
struct mlx5dr_matcher *last_matcher = NULL;
10+
struct mlx5dr_htbl_connect_info info;
11+
struct mlx5dr_ste_htbl *last_htbl;
12+
int ret;
13+
14+
if (action && action->action_type != DR_ACTION_TYP_FT)
15+
return -EOPNOTSUPP;
16+
17+
mutex_lock(&tbl->dmn->mutex);
18+
19+
if (!list_empty(&tbl->matcher_list))
20+
last_matcher = list_last_entry(&tbl->matcher_list,
21+
struct mlx5dr_matcher,
22+
matcher_list);
23+
24+
if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX ||
25+
tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
26+
if (last_matcher)
27+
last_htbl = last_matcher->rx.e_anchor;
28+
else
29+
last_htbl = tbl->rx.s_anchor;
30+
31+
tbl->rx.default_icm_addr = action ?
32+
action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
33+
tbl->rx.nic_dmn->default_icm_addr;
34+
35+
info.type = CONNECT_MISS;
36+
info.miss_icm_addr = tbl->rx.default_icm_addr;
37+
38+
ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
39+
tbl->rx.nic_dmn,
40+
last_htbl,
41+
&info, true);
42+
if (ret) {
43+
mlx5dr_dbg(tbl->dmn, "Failed to set RX miss action, ret %d\n", ret);
44+
goto out;
45+
}
46+
}
47+
48+
if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX ||
49+
tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
50+
if (last_matcher)
51+
last_htbl = last_matcher->tx.e_anchor;
52+
else
53+
last_htbl = tbl->tx.s_anchor;
54+
55+
tbl->tx.default_icm_addr = action ?
56+
action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr :
57+
tbl->tx.nic_dmn->default_icm_addr;
58+
59+
info.type = CONNECT_MISS;
60+
info.miss_icm_addr = tbl->tx.default_icm_addr;
61+
62+
ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
63+
tbl->tx.nic_dmn,
64+
last_htbl, &info, true);
65+
if (ret) {
66+
mlx5dr_dbg(tbl->dmn, "Failed to set TX miss action, ret %d\n", ret);
67+
goto out;
68+
}
69+
}
70+
71+
/* Release old action */
72+
if (tbl->miss_action)
73+
refcount_dec(&tbl->miss_action->refcount);
74+
75+
/* Set new miss action */
76+
tbl->miss_action = action;
77+
if (tbl->miss_action)
78+
refcount_inc(&action->refcount);
79+
80+
out:
81+
mutex_unlock(&tbl->dmn->mutex);
82+
return ret;
83+
}
84+
85+
static void dr_table_uninit_nic(struct mlx5dr_table_rx_tx *nic_tbl)
86+
{
87+
mlx5dr_htbl_put(nic_tbl->s_anchor);
88+
}
89+
90+
static void dr_table_uninit_fdb(struct mlx5dr_table *tbl)
91+
{
92+
dr_table_uninit_nic(&tbl->rx);
93+
dr_table_uninit_nic(&tbl->tx);
94+
}
95+
96+
static void dr_table_uninit(struct mlx5dr_table *tbl)
97+
{
98+
mutex_lock(&tbl->dmn->mutex);
99+
100+
switch (tbl->dmn->type) {
101+
case MLX5DR_DOMAIN_TYPE_NIC_RX:
102+
dr_table_uninit_nic(&tbl->rx);
103+
break;
104+
case MLX5DR_DOMAIN_TYPE_NIC_TX:
105+
dr_table_uninit_nic(&tbl->tx);
106+
break;
107+
case MLX5DR_DOMAIN_TYPE_FDB:
108+
dr_table_uninit_fdb(tbl);
109+
break;
110+
default:
111+
WARN_ON(true);
112+
break;
113+
}
114+
115+
mutex_unlock(&tbl->dmn->mutex);
116+
}
117+
118+
static int dr_table_init_nic(struct mlx5dr_domain *dmn,
119+
struct mlx5dr_table_rx_tx *nic_tbl)
120+
{
121+
struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn;
122+
struct mlx5dr_htbl_connect_info info;
123+
int ret;
124+
125+
nic_tbl->default_icm_addr = nic_dmn->default_icm_addr;
126+
127+
nic_tbl->s_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
128+
DR_CHUNK_SIZE_1,
129+
MLX5DR_STE_LU_TYPE_DONT_CARE,
130+
0);
131+
if (!nic_tbl->s_anchor)
132+
return -ENOMEM;
133+
134+
info.type = CONNECT_MISS;
135+
info.miss_icm_addr = nic_dmn->default_icm_addr;
136+
ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn,
137+
nic_tbl->s_anchor,
138+
&info, true);
139+
if (ret)
140+
goto free_s_anchor;
141+
142+
mlx5dr_htbl_get(nic_tbl->s_anchor);
143+
144+
return 0;
145+
146+
free_s_anchor:
147+
mlx5dr_ste_htbl_free(nic_tbl->s_anchor);
148+
return ret;
149+
}
150+
151+
static int dr_table_init_fdb(struct mlx5dr_table *tbl)
152+
{
153+
int ret;
154+
155+
ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
156+
if (ret)
157+
return ret;
158+
159+
ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
160+
if (ret)
161+
goto destroy_rx;
162+
163+
return 0;
164+
165+
destroy_rx:
166+
dr_table_uninit_nic(&tbl->rx);
167+
return ret;
168+
}
169+
170+
static int dr_table_init(struct mlx5dr_table *tbl)
171+
{
172+
int ret = 0;
173+
174+
INIT_LIST_HEAD(&tbl->matcher_list);
175+
176+
mutex_lock(&tbl->dmn->mutex);
177+
178+
switch (tbl->dmn->type) {
179+
case MLX5DR_DOMAIN_TYPE_NIC_RX:
180+
tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_RX;
181+
tbl->rx.nic_dmn = &tbl->dmn->info.rx;
182+
ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
183+
break;
184+
case MLX5DR_DOMAIN_TYPE_NIC_TX:
185+
tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_TX;
186+
tbl->tx.nic_dmn = &tbl->dmn->info.tx;
187+
ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
188+
break;
189+
case MLX5DR_DOMAIN_TYPE_FDB:
190+
tbl->table_type = MLX5_FLOW_TABLE_TYPE_FDB;
191+
tbl->rx.nic_dmn = &tbl->dmn->info.rx;
192+
tbl->tx.nic_dmn = &tbl->dmn->info.tx;
193+
ret = dr_table_init_fdb(tbl);
194+
break;
195+
default:
196+
WARN_ON(true);
197+
break;
198+
}
199+
200+
mutex_unlock(&tbl->dmn->mutex);
201+
202+
return ret;
203+
}
204+
205+
static int dr_table_destroy_sw_owned_tbl(struct mlx5dr_table *tbl)
206+
{
207+
return mlx5dr_cmd_destroy_flow_table(tbl->dmn->mdev,
208+
tbl->table_id,
209+
tbl->table_type);
210+
}
211+
212+
static int dr_table_create_sw_owned_tbl(struct mlx5dr_table *tbl)
213+
{
214+
u64 icm_addr_rx = 0;
215+
u64 icm_addr_tx = 0;
216+
int ret;
217+
218+
if (tbl->rx.s_anchor)
219+
icm_addr_rx = tbl->rx.s_anchor->chunk->icm_addr;
220+
221+
if (tbl->tx.s_anchor)
222+
icm_addr_tx = tbl->tx.s_anchor->chunk->icm_addr;
223+
224+
ret = mlx5dr_cmd_create_flow_table(tbl->dmn->mdev,
225+
tbl->table_type,
226+
icm_addr_rx,
227+
icm_addr_tx,
228+
tbl->dmn->info.caps.max_ft_level - 1,
229+
true, false, NULL,
230+
&tbl->table_id);
231+
232+
return ret;
233+
}
234+
235+
struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_domain *dmn, u32 level)
236+
{
237+
struct mlx5dr_table *tbl;
238+
int ret;
239+
240+
refcount_inc(&dmn->refcount);
241+
242+
tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
243+
if (!tbl)
244+
goto dec_ref;
245+
246+
tbl->dmn = dmn;
247+
tbl->level = level;
248+
refcount_set(&tbl->refcount, 1);
249+
250+
ret = dr_table_init(tbl);
251+
if (ret)
252+
goto free_tbl;
253+
254+
ret = dr_table_create_sw_owned_tbl(tbl);
255+
if (ret)
256+
goto uninit_tbl;
257+
258+
return tbl;
259+
260+
uninit_tbl:
261+
dr_table_uninit(tbl);
262+
free_tbl:
263+
kfree(tbl);
264+
dec_ref:
265+
refcount_dec(&dmn->refcount);
266+
return NULL;
267+
}
268+
269+
int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
270+
{
271+
int ret;
272+
273+
if (refcount_read(&tbl->refcount) > 1)
274+
return -EBUSY;
275+
276+
ret = dr_table_destroy_sw_owned_tbl(tbl);
277+
if (ret)
278+
return ret;
279+
280+
dr_table_uninit(tbl);
281+
282+
if (tbl->miss_action)
283+
refcount_dec(&tbl->miss_action->refcount);
284+
285+
refcount_dec(&tbl->dmn->refcount);
286+
kfree(tbl);
287+
288+
return ret;
289+
}
290+
291+
u32 mlx5dr_table_get_id(struct mlx5dr_table *tbl)
292+
{
293+
return tbl->table_id;
294+
}

0 commit comments

Comments
 (0)