Skip to content

Commit 898b078

Browse files
mark-blochSaeed Mahameed
authored andcommitted
net/mlx5: Add send to vport rules on paired device
When two mlx5 devices are paired in switchdev mode, always offload the send-to-vport rule to the peer E-Switch. This allows to abstract the logic when this is really necessary (single FDB) and combine the logic of both cases into one. Signed-off-by: Mark Bloch <mbloch@nvidia.com> Reviewed-by: Mark Zhang <markzhang@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
1 parent c8e6a9e commit 898b078

File tree

3 files changed

+101
-3
lines changed

3 files changed

+101
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_rep.c

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "en/devlink.h"
5050
#include "fs_core.h"
5151
#include "lib/mlx5.h"
52+
#include "lib/devcom.h"
5253
#define CREATE_TRACE_POINTS
5354
#include "diag/en_rep_tracepoint.h"
5455
#include "en_accel/ipsec.h"
@@ -310,6 +311,8 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
310311
rpriv = mlx5e_rep_to_rep_priv(rep);
311312
list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
312313
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
314+
if (rep_sq->send_to_vport_rule_peer)
315+
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
313316
list_del(&rep_sq->list);
314317
kfree(rep_sq);
315318
}
@@ -319,6 +322,7 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
319322
struct mlx5_eswitch_rep *rep,
320323
u32 *sqns_array, int sqns_num)
321324
{
325+
struct mlx5_eswitch *peer_esw = NULL;
322326
struct mlx5_flow_handle *flow_rule;
323327
struct mlx5e_rep_priv *rpriv;
324328
struct mlx5e_rep_sq *rep_sq;
@@ -329,6 +333,10 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
329333
return 0;
330334

331335
rpriv = mlx5e_rep_to_rep_priv(rep);
336+
if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS))
337+
peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom,
338+
MLX5_DEVCOM_ESW_OFFLOADS);
339+
332340
for (i = 0; i < sqns_num; i++) {
333341
rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
334342
if (!rep_sq) {
@@ -345,12 +353,34 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
345353
goto out_err;
346354
}
347355
rep_sq->send_to_vport_rule = flow_rule;
356+
rep_sq->sqn = sqns_array[i];
357+
358+
if (peer_esw) {
359+
flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
360+
rep, sqns_array[i]);
361+
if (IS_ERR(flow_rule)) {
362+
err = PTR_ERR(flow_rule);
363+
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
364+
kfree(rep_sq);
365+
goto out_err;
366+
}
367+
rep_sq->send_to_vport_rule_peer = flow_rule;
368+
}
369+
348370
list_add(&rep_sq->list, &rpriv->vport_sqs_list);
349371
}
372+
373+
if (peer_esw)
374+
mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
375+
350376
return 0;
351377

352378
out_err:
353379
mlx5e_sqs2vport_stop(esw, rep);
380+
381+
if (peer_esw)
382+
mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
383+
354384
return err;
355385
}
356386

@@ -1264,10 +1294,64 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
12641294
return rpriv->netdev;
12651295
}
12661296

1297+
static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep)
1298+
{
1299+
struct mlx5e_rep_priv *rpriv;
1300+
struct mlx5e_rep_sq *rep_sq;
1301+
1302+
rpriv = mlx5e_rep_to_rep_priv(rep);
1303+
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1304+
if (!rep_sq->send_to_vport_rule_peer)
1305+
continue;
1306+
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
1307+
rep_sq->send_to_vport_rule_peer = NULL;
1308+
}
1309+
}
1310+
1311+
static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw,
1312+
struct mlx5_eswitch_rep *rep,
1313+
struct mlx5_eswitch *peer_esw)
1314+
{
1315+
struct mlx5_flow_handle *flow_rule;
1316+
struct mlx5e_rep_priv *rpriv;
1317+
struct mlx5e_rep_sq *rep_sq;
1318+
1319+
rpriv = mlx5e_rep_to_rep_priv(rep);
1320+
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1321+
if (rep_sq->send_to_vport_rule_peer)
1322+
continue;
1323+
flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn);
1324+
if (IS_ERR(flow_rule))
1325+
goto err_out;
1326+
rep_sq->send_to_vport_rule_peer = flow_rule;
1327+
}
1328+
1329+
return 0;
1330+
err_out:
1331+
mlx5e_vport_rep_event_unpair(rep);
1332+
return PTR_ERR(flow_rule);
1333+
}
1334+
1335+
static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
1336+
struct mlx5_eswitch_rep *rep,
1337+
enum mlx5_switchdev_event event,
1338+
void *data)
1339+
{
1340+
int err = 0;
1341+
1342+
if (event == MLX5_SWITCHDEV_EVENT_PAIR)
1343+
err = mlx5e_vport_rep_event_pair(esw, rep, data);
1344+
else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR)
1345+
mlx5e_vport_rep_event_unpair(rep);
1346+
1347+
return err;
1348+
}
1349+
12671350
static const struct mlx5_eswitch_rep_ops rep_ops = {
12681351
.load = mlx5e_vport_rep_load,
12691352
.unload = mlx5e_vport_rep_unload,
1270-
.get_proto_dev = mlx5e_vport_rep_get_proto_dev
1353+
.get_proto_dev = mlx5e_vport_rep_get_proto_dev,
1354+
.event = mlx5e_vport_rep_event,
12711355
};
12721356

12731357
static int mlx5e_rep_probe(struct auxiliary_device *adev,

drivers/net/ethernet/mellanox/mlx5/core/en_rep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ struct mlx5e_encap_entry {
207207

208208
struct mlx5e_rep_sq {
209209
struct mlx5_flow_handle *send_to_vport_rule;
210+
struct mlx5_flow_handle *send_to_vport_rule_peer;
211+
u32 sqn;
210212
struct list_head list;
211213
};
212214

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,18 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
16161616
goto ns_err;
16171617
}
16181618

1619-
table_size = esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1619+
/* To be strictly correct:
1620+
* MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ)
1621+
* should be:
1622+
* esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1623+
* peer_esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ
1624+
* but as the peer device might not be in switchdev mode it's not
1625+
* possible. We use the fact that by default FW sets max vfs and max sfs
1626+
* to the same value on both devices. If it needs to be changed in the future note
1627+
* the peer miss group should also be created based on the number of
1628+
* total vports of the peer (currently is also uses esw->total_vports).
1629+
*/
1630+
table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) +
16201631
MLX5_ESW_MISS_FLOWS + esw->total_vports + esw->esw_funcs.num_vfs;
16211632

16221633
/* create the slow path fdb with encap set, so further table instances
@@ -1673,7 +1684,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
16731684
source_eswitch_owner_vhca_id_valid, 1);
16741685
}
16751686

1676-
ix = esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ;
1687+
/* See comment above table_size calculation */
1688+
ix = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ);
16771689
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
16781690
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix - 1);
16791691

0 commit comments

Comments
 (0)