Skip to content

Commit 605fcce

Browse files
Tariq ToukanSaeed Mahameed
authored andcommitted
net/mlx5: SD, Implement steering for primary and secondaries
Implement the needed SD steering adjustments for the primary and secondaries. While the SD multiple devices are used to avoid cross-numa memory, when it comes to chip level all traffic goes only through the primary device. The secondaries are forced to silent mode, to guarantee they are not involved in any unexpected ingress/egress traffic. In RX, secondary devices will not have steering objects. Traffic will be steered from the primary device to the RQs of a secondary device using advanced cross-vhca RX steering capabilities. In TX, the primary creates a new TX flow table, which is aliased by the secondaries. Signed-off-by: Tariq Toukan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent a45af9a commit 605fcce

File tree

1 file changed

+184
-1
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/lib

1 file changed

+184
-1
lines changed

drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "lib/sd.h"
55
#include "mlx5_core.h"
66
#include "lib/mlx5.h"
7+
#include "fs_cmd.h"
78
#include <linux/mlx5/vport.h>
89

910
#define sd_info(__dev, format, ...) \
@@ -19,9 +20,11 @@ struct mlx5_sd {
1920
union {
2021
struct { /* primary */
2122
struct mlx5_core_dev *secondaries[MLX5_SD_MAX_GROUP_SZ - 1];
23+
struct mlx5_flow_table *tx_ft;
2224
};
2325
struct { /* secondary */
2426
struct mlx5_core_dev *primary_dev;
27+
u32 alias_obj_id;
2528
};
2629
};
2730
};
@@ -78,6 +81,21 @@ struct mlx5_core_dev *mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev *primary, int c
7881
return mlx5_sd_primary_get_peer(primary, mdev_idx);
7982
}
8083

84+
static bool ft_create_alias_supported(struct mlx5_core_dev *dev)
85+
{
86+
u64 obj_allowed = MLX5_CAP_GEN_2_64(dev, allowed_object_for_other_vhca_access);
87+
u32 obj_supp = MLX5_CAP_GEN_2(dev, cross_vhca_object_to_object_supported);
88+
89+
if (!(obj_supp &
90+
MLX5_CROSS_VHCA_OBJ_TO_OBJ_SUPPORTED_LOCAL_FLOW_TABLE_ROOT_TO_REMOTE_FLOW_TABLE))
91+
return false;
92+
93+
if (!(obj_allowed & MLX5_ALLOWED_OBJ_FOR_OTHER_VHCA_ACCESS_FLOW_TABLE))
94+
return false;
95+
96+
return true;
97+
}
98+
8199
static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses)
82100
{
83101
/* Feature is currently implemented for PFs only */
@@ -88,6 +106,24 @@ static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses)
88106
if (host_buses > MLX5_SD_MAX_GROUP_SZ)
89107
return false;
90108

109+
/* Disconnect secondaries from the network */
110+
if (!MLX5_CAP_GEN(dev, eswitch_manager))
111+
return false;
112+
if (!MLX5_CAP_GEN(dev, silent_mode))
113+
return false;
114+
115+
/* RX steering from primary to secondaries */
116+
if (!MLX5_CAP_GEN(dev, cross_vhca_rqt))
117+
return false;
118+
if (host_buses > MLX5_CAP_GEN_2(dev, max_rqt_vhca_id))
119+
return false;
120+
121+
/* TX steering from secondaries to primary */
122+
if (!ft_create_alias_supported(dev))
123+
return false;
124+
if (!MLX5_CAP_FLOWTABLE_NIC_TX(dev, reset_root_to_default))
125+
return false;
126+
91127
return true;
92128
}
93129

@@ -227,10 +263,122 @@ static void sd_unregister(struct mlx5_core_dev *dev)
227263
mlx5_devcom_unregister_component(sd->devcom);
228264
}
229265

266+
static int sd_cmd_set_primary(struct mlx5_core_dev *primary, u8 *alias_key)
267+
{
268+
struct mlx5_cmd_allow_other_vhca_access_attr allow_attr = {};
269+
struct mlx5_sd *sd = mlx5_get_sd(primary);
270+
struct mlx5_flow_table_attr ft_attr = {};
271+
struct mlx5_flow_namespace *nic_ns;
272+
struct mlx5_flow_table *ft;
273+
int err;
274+
275+
nic_ns = mlx5_get_flow_namespace(primary, MLX5_FLOW_NAMESPACE_EGRESS);
276+
if (!nic_ns)
277+
return -EOPNOTSUPP;
278+
279+
ft = mlx5_create_flow_table(nic_ns, &ft_attr);
280+
if (IS_ERR(ft)) {
281+
err = PTR_ERR(ft);
282+
return err;
283+
}
284+
sd->tx_ft = ft;
285+
memcpy(allow_attr.access_key, alias_key, ACCESS_KEY_LEN);
286+
allow_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS;
287+
allow_attr.obj_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id;
288+
289+
err = mlx5_cmd_allow_other_vhca_access(primary, &allow_attr);
290+
if (err) {
291+
mlx5_core_err(primary, "Failed to allow other vhca access err=%d\n",
292+
err);
293+
mlx5_destroy_flow_table(ft);
294+
return err;
295+
}
296+
297+
return 0;
298+
}
299+
300+
static void sd_cmd_unset_primary(struct mlx5_core_dev *primary)
301+
{
302+
struct mlx5_sd *sd = mlx5_get_sd(primary);
303+
304+
mlx5_destroy_flow_table(sd->tx_ft);
305+
}
306+
307+
static int sd_secondary_create_alias_ft(struct mlx5_core_dev *secondary,
308+
struct mlx5_core_dev *primary,
309+
struct mlx5_flow_table *ft,
310+
u32 *obj_id, u8 *alias_key)
311+
{
312+
u32 aliased_object_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id;
313+
u16 vhca_id_to_be_accessed = MLX5_CAP_GEN(primary, vhca_id);
314+
struct mlx5_cmd_alias_obj_create_attr alias_attr = {};
315+
int ret;
316+
317+
memcpy(alias_attr.access_key, alias_key, ACCESS_KEY_LEN);
318+
alias_attr.obj_id = aliased_object_id;
319+
alias_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS;
320+
alias_attr.vhca_id = vhca_id_to_be_accessed;
321+
ret = mlx5_cmd_alias_obj_create(secondary, &alias_attr, obj_id);
322+
if (ret) {
323+
mlx5_core_err(secondary, "Failed to create alias object err=%d\n",
324+
ret);
325+
return ret;
326+
}
327+
328+
return 0;
329+
}
330+
331+
static void sd_secondary_destroy_alias_ft(struct mlx5_core_dev *secondary)
332+
{
333+
struct mlx5_sd *sd = mlx5_get_sd(secondary);
334+
335+
mlx5_cmd_alias_obj_destroy(secondary, sd->alias_obj_id,
336+
MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS);
337+
}
338+
339+
static int sd_cmd_set_secondary(struct mlx5_core_dev *secondary,
340+
struct mlx5_core_dev *primary,
341+
u8 *alias_key)
342+
{
343+
struct mlx5_sd *primary_sd = mlx5_get_sd(primary);
344+
struct mlx5_sd *sd = mlx5_get_sd(secondary);
345+
int err;
346+
347+
err = mlx5_fs_cmd_set_l2table_entry_silent(secondary, 1);
348+
if (err)
349+
return err;
350+
351+
err = sd_secondary_create_alias_ft(secondary, primary, primary_sd->tx_ft,
352+
&sd->alias_obj_id, alias_key);
353+
if (err)
354+
goto err_unset_silent;
355+
356+
err = mlx5_fs_cmd_set_tx_flow_table_root(secondary, sd->alias_obj_id, false);
357+
if (err)
358+
goto err_destroy_alias_ft;
359+
360+
return 0;
361+
362+
err_destroy_alias_ft:
363+
sd_secondary_destroy_alias_ft(secondary);
364+
err_unset_silent:
365+
mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0);
366+
return err;
367+
}
368+
369+
static void sd_cmd_unset_secondary(struct mlx5_core_dev *secondary)
370+
{
371+
mlx5_fs_cmd_set_tx_flow_table_root(secondary, 0, true);
372+
sd_secondary_destroy_alias_ft(secondary);
373+
mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0);
374+
}
375+
230376
int mlx5_sd_init(struct mlx5_core_dev *dev)
231377
{
378+
struct mlx5_core_dev *primary, *pos, *to;
232379
struct mlx5_sd *sd = mlx5_get_sd(dev);
233-
int err;
380+
u8 alias_key[ACCESS_KEY_LEN];
381+
int err, i;
234382

235383
err = sd_init(dev);
236384
if (err)
@@ -244,8 +392,33 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
244392
if (err)
245393
goto err_sd_cleanup;
246394

395+
if (!mlx5_devcom_comp_is_ready(sd->devcom))
396+
return 0;
397+
398+
primary = mlx5_sd_get_primary(dev);
399+
400+
for (i = 0; i < ACCESS_KEY_LEN; i++)
401+
alias_key[i] = get_random_u8();
402+
403+
err = sd_cmd_set_primary(primary, alias_key);
404+
if (err)
405+
goto err_sd_unregister;
406+
407+
mlx5_sd_for_each_secondary(i, primary, pos) {
408+
err = sd_cmd_set_secondary(pos, primary, alias_key);
409+
if (err)
410+
goto err_unset_secondaries;
411+
}
412+
247413
return 0;
248414

415+
err_unset_secondaries:
416+
to = pos;
417+
mlx5_sd_for_each_secondary_to(i, primary, to, pos)
418+
sd_cmd_unset_secondary(pos);
419+
sd_cmd_unset_primary(primary);
420+
err_sd_unregister:
421+
sd_unregister(dev);
249422
err_sd_cleanup:
250423
sd_cleanup(dev);
251424
return err;
@@ -254,10 +427,20 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
254427
void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
255428
{
256429
struct mlx5_sd *sd = mlx5_get_sd(dev);
430+
struct mlx5_core_dev *primary, *pos;
431+
int i;
257432

258433
if (!sd)
259434
return;
260435

436+
if (!mlx5_devcom_comp_is_ready(sd->devcom))
437+
goto out;
438+
439+
primary = mlx5_sd_get_primary(dev);
440+
mlx5_sd_for_each_secondary(i, primary, pos)
441+
sd_cmd_unset_secondary(pos);
442+
sd_cmd_unset_primary(primary);
443+
out:
261444
sd_unregister(dev);
262445
sd_cleanup(dev);
263446
}

0 commit comments

Comments
 (0)