Skip to content

Commit 1c46d74

Browse files
ayalevinkuba-moo
authored andcommitted
net/mlx5e: Optimize promiscuous mode
Change steering flow to optimize traffic in promiscuous mode. On demand, add a high priority table containing a catch-all rule. All incoming packets are caught by this rule and steered directly to the TTC table. Prior to this change, packets in promiscuous mode may suffer from up to 4 steering hops before reaching TTC table. In addition, this patch will allow us adding a catch-all rule at the end of MAC table to serve MAC trap, with no impact on promiscuous mode performance. Signed-off-by: Aya Levin <[email protected]> Reviewed-by: Moshe Shemesh <[email protected]> Reviewed-by: Maor Gottlieb <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 241dc15 commit 1c46d74

File tree

3 files changed

+100
-34
lines changed

3 files changed

+100
-34
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/fs.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ struct mlx5e_l2_rule {
4444

4545
#define MLX5E_L2_ADDR_HASH_SIZE BIT(BITS_PER_BYTE)
4646

47+
struct mlx5e_promisc_table {
48+
struct mlx5e_flow_table ft;
49+
struct mlx5_flow_handle *rule;
50+
};
51+
4752
struct mlx5e_vlan_table {
4853
struct mlx5e_flow_table ft;
4954
DECLARE_BITMAP(active_cvlans, VLAN_N_VID);
@@ -62,7 +67,6 @@ struct mlx5e_l2_table {
6267
struct hlist_head netdev_mc[MLX5E_L2_ADDR_HASH_SIZE];
6368
struct mlx5e_l2_rule broadcast;
6469
struct mlx5e_l2_rule allmulti;
65-
struct mlx5e_l2_rule promisc;
6670
bool broadcast_enabled;
6771
bool allmulti_enabled;
6872
bool promisc_enabled;
@@ -126,7 +130,8 @@ struct mlx5e_ttc_table {
126130

127131
/* NIC prio FTS */
128132
enum {
129-
MLX5E_VLAN_FT_LEVEL = 0,
133+
MLX5E_PROMISC_FT_LEVEL,
134+
MLX5E_VLAN_FT_LEVEL,
130135
MLX5E_L2_FT_LEVEL,
131136
MLX5E_TTC_FT_LEVEL,
132137
MLX5E_INNER_TTC_FT_LEVEL,
@@ -241,6 +246,7 @@ struct mlx5e_flow_steering {
241246
struct mlx5e_ethtool_steering ethtool;
242247
#endif
243248
struct mlx5e_tc_table tc;
249+
struct mlx5e_promisc_table promisc;
244250
struct mlx5e_vlan_table vlan;
245251
struct mlx5e_l2_table l2;
246252
struct mlx5e_ttc_table ttc;

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

Lines changed: 90 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
4646
enum {
4747
MLX5E_FULLMATCH = 0,
4848
MLX5E_ALLMULTI = 1,
49-
MLX5E_PROMISC = 2,
5049
};
5150

5251
enum {
@@ -596,6 +595,83 @@ static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv)
596595
mlx5e_apply_netdev_addr(priv);
597596
}
598597

598+
#define MLX5E_PROMISC_GROUP0_SIZE BIT(0)
599+
#define MLX5E_PROMISC_TABLE_SIZE MLX5E_PROMISC_GROUP0_SIZE
600+
601+
static int mlx5e_add_promisc_rule(struct mlx5e_priv *priv)
602+
{
603+
struct mlx5_flow_table *ft = priv->fs.promisc.ft.t;
604+
struct mlx5_flow_destination dest = {};
605+
struct mlx5_flow_handle **rule_p;
606+
MLX5_DECLARE_FLOW_ACT(flow_act);
607+
struct mlx5_flow_spec *spec;
608+
int err = 0;
609+
610+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
611+
if (!spec)
612+
return -ENOMEM;
613+
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
614+
dest.ft = priv->fs.ttc.ft.t;
615+
616+
rule_p = &priv->fs.promisc.rule;
617+
*rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
618+
if (IS_ERR(*rule_p)) {
619+
err = PTR_ERR(*rule_p);
620+
*rule_p = NULL;
621+
netdev_err(priv->netdev, "%s: add promiscuous rule failed\n", __func__);
622+
}
623+
kvfree(spec);
624+
return err;
625+
}
626+
627+
static int mlx5e_create_promisc_table(struct mlx5e_priv *priv)
628+
{
629+
struct mlx5e_flow_table *ft = &priv->fs.promisc.ft;
630+
struct mlx5_flow_table_attr ft_attr = {};
631+
int err;
632+
633+
ft_attr.max_fte = MLX5E_PROMISC_TABLE_SIZE;
634+
ft_attr.autogroup.max_num_groups = 1;
635+
ft_attr.level = MLX5E_PROMISC_FT_LEVEL;
636+
ft_attr.prio = MLX5E_NIC_PRIO;
637+
638+
ft->t = mlx5_create_auto_grouped_flow_table(priv->fs.ns, &ft_attr);
639+
if (IS_ERR(ft->t)) {
640+
err = PTR_ERR(ft->t);
641+
netdev_err(priv->netdev, "fail to create promisc table err=%d\n", err);
642+
return err;
643+
}
644+
645+
err = mlx5e_add_promisc_rule(priv);
646+
if (err)
647+
goto err_destroy_promisc_table;
648+
649+
return 0;
650+
651+
err_destroy_promisc_table:
652+
mlx5_destroy_flow_table(ft->t);
653+
ft->t = NULL;
654+
655+
return err;
656+
}
657+
658+
static void mlx5e_del_promisc_rule(struct mlx5e_priv *priv)
659+
{
660+
if (WARN(!priv->fs.promisc.rule, "Trying to remove non-existing promiscuous rule"))
661+
return;
662+
mlx5_del_flow_rules(priv->fs.promisc.rule);
663+
priv->fs.promisc.rule = NULL;
664+
}
665+
666+
static void mlx5e_destroy_promisc_table(struct mlx5e_priv *priv)
667+
{
668+
if (WARN(!priv->fs.promisc.ft.t, "Trying to remove non-existing promiscuous table"))
669+
return;
670+
mlx5e_del_promisc_rule(priv);
671+
mlx5_destroy_flow_table(priv->fs.promisc.ft.t);
672+
priv->fs.promisc.ft.t = NULL;
673+
}
674+
599675
void mlx5e_set_rx_mode_work(struct work_struct *work)
600676
{
601677
struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
@@ -615,14 +691,15 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
615691
bool disable_allmulti = ea->allmulti_enabled && !allmulti_enabled;
616692
bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled;
617693
bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
694+
int err;
618695

619696
if (enable_promisc) {
620-
if (!priv->channels.params.vlan_strip_disable)
697+
err = mlx5e_create_promisc_table(priv);
698+
if (err)
699+
enable_promisc = false;
700+
if (!priv->channels.params.vlan_strip_disable && !err)
621701
netdev_warn_once(ndev,
622702
"S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
623-
mlx5e_add_l2_flow_rule(priv, &ea->promisc, MLX5E_PROMISC);
624-
if (!priv->fs.vlan.cvlan_filter_disabled)
625-
mlx5e_add_any_vid_rules(priv);
626703
}
627704
if (enable_allmulti)
628705
mlx5e_add_l2_flow_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
@@ -635,11 +712,8 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
635712
mlx5e_del_l2_flow_rule(priv, &ea->broadcast);
636713
if (disable_allmulti)
637714
mlx5e_del_l2_flow_rule(priv, &ea->allmulti);
638-
if (disable_promisc) {
639-
if (!priv->fs.vlan.cvlan_filter_disabled)
640-
mlx5e_del_any_vid_rules(priv);
641-
mlx5e_del_l2_flow_rule(priv, &ea->promisc);
642-
}
715+
if (disable_promisc)
716+
mlx5e_destroy_promisc_table(priv);
643717

644718
ea->promisc_enabled = promisc_enabled;
645719
ea->allmulti_enabled = allmulti_enabled;
@@ -1306,9 +1380,6 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
13061380
mc_dmac[0] = 0x01;
13071381
mv_dmac[0] = 0x01;
13081382
break;
1309-
1310-
case MLX5E_PROMISC:
1311-
break;
13121383
}
13131384

13141385
ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
@@ -1324,13 +1395,11 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
13241395
return err;
13251396
}
13261397

1327-
#define MLX5E_NUM_L2_GROUPS 3
1328-
#define MLX5E_L2_GROUP1_SIZE BIT(0)
1329-
#define MLX5E_L2_GROUP2_SIZE BIT(15)
1330-
#define MLX5E_L2_GROUP3_SIZE BIT(0)
1398+
#define MLX5E_NUM_L2_GROUPS 2
1399+
#define MLX5E_L2_GROUP1_SIZE BIT(15)
1400+
#define MLX5E_L2_GROUP2_SIZE BIT(0)
13311401
#define MLX5E_L2_TABLE_SIZE (MLX5E_L2_GROUP1_SIZE +\
1332-
MLX5E_L2_GROUP2_SIZE +\
1333-
MLX5E_L2_GROUP3_SIZE)
1402+
MLX5E_L2_GROUP2_SIZE)
13341403
static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
13351404
{
13361405
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
@@ -1353,20 +1422,11 @@ static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
13531422
mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
13541423
mc_dmac = MLX5_ADDR_OF(fte_match_param, mc,
13551424
outer_headers.dmac_47_16);
1356-
/* Flow Group for promiscuous */
1357-
MLX5_SET_CFG(in, start_flow_index, ix);
1358-
ix += MLX5E_L2_GROUP1_SIZE;
1359-
MLX5_SET_CFG(in, end_flow_index, ix - 1);
1360-
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1361-
if (IS_ERR(ft->g[ft->num_groups]))
1362-
goto err_destroy_groups;
1363-
ft->num_groups++;
1364-
13651425
/* Flow Group for full match */
13661426
eth_broadcast_addr(mc_dmac);
13671427
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13681428
MLX5_SET_CFG(in, start_flow_index, ix);
1369-
ix += MLX5E_L2_GROUP2_SIZE;
1429+
ix += MLX5E_L2_GROUP1_SIZE;
13701430
MLX5_SET_CFG(in, end_flow_index, ix - 1);
13711431
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13721432
if (IS_ERR(ft->g[ft->num_groups]))
@@ -1377,7 +1437,7 @@ static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
13771437
eth_zero_addr(mc_dmac);
13781438
mc_dmac[0] = 0x01;
13791439
MLX5_SET_CFG(in, start_flow_index, ix);
1380-
ix += MLX5E_L2_GROUP3_SIZE;
1440+
ix += MLX5E_L2_GROUP2_SIZE;
13811441
MLX5_SET_CFG(in, end_flow_index, ix - 1);
13821442
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13831443
if (IS_ERR(ft->g[ft->num_groups]))

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@
105105
#define ETHTOOL_PRIO_NUM_LEVELS 1
106106
#define ETHTOOL_NUM_PRIOS 11
107107
#define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
108-
/* Vlan, mac, ttc, inner ttc, {aRFS/accel and esp/esp_err} */
109-
#define KERNEL_NIC_PRIO_NUM_LEVELS 6
108+
/* Promiscuous, Vlan, mac, ttc, inner ttc, {aRFS/accel and esp/esp_err} */
109+
#define KERNEL_NIC_PRIO_NUM_LEVELS 7
110110
#define KERNEL_NIC_NUM_PRIOS 1
111111
/* One more level for tc */
112112
#define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)

0 commit comments

Comments
 (0)