Skip to content

Commit 7d92d58

Browse files
Gal PressmanSaeed Mahameed
authored andcommitted
net/mlx5e: Add 802.1ad VLAN filter steering rules
When a user chooses to use 802.1ad VLAN the proper steering rules will be added to the VLAN flow table (matching the specific S-tag VID). Due to current hardware limitation, when using 802.1ad, we must disable C-tag VLAN stripping on the RQs. Signed-off-by: Gal Pressman <[email protected]> Reviewed-by: Maor Gottlieb <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 03eda95 commit 7d92d58

File tree

3 files changed

+112
-13
lines changed

3 files changed

+112
-13
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,9 @@ struct mlx5e_tc_table {
656656
struct mlx5e_vlan_table {
657657
struct mlx5e_flow_table ft;
658658
DECLARE_BITMAP(active_cvlans, VLAN_N_VID);
659+
DECLARE_BITMAP(active_svlans, VLAN_N_VID);
659660
struct mlx5_flow_handle *active_cvlans_rule[VLAN_N_VID];
661+
struct mlx5_flow_handle *active_svlans_rule[VLAN_N_VID];
660662
struct mlx5_flow_handle *untagged_rule;
661663
struct mlx5_flow_handle *any_cvlan_rule;
662664
struct mlx5_flow_handle *any_svlan_rule;

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

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ enum mlx5e_vlan_rule_type {
155155
MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID,
156156
MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID,
157157
MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID,
158+
MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID,
158159
};
159160

160161
static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
@@ -174,6 +175,10 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
174175

175176
switch (rule_type) {
176177
case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
178+
/* cvlan_tag enabled in match criteria and
179+
* disabled in match value means both S & C tags
180+
* don't exist (untagged of both)
181+
*/
177182
rule_p = &priv->fs.vlan.untagged_rule;
178183
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
179184
outer_headers.cvlan_tag);
@@ -190,6 +195,16 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
190195
outer_headers.svlan_tag);
191196
MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
192197
break;
198+
case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
199+
rule_p = &priv->fs.vlan.active_svlans_rule[vid];
200+
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
201+
outer_headers.svlan_tag);
202+
MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
203+
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
204+
outer_headers.first_vid);
205+
MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,
206+
vid);
207+
break;
193208
default: /* MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID */
194209
rule_p = &priv->fs.vlan.active_cvlans_rule[vid];
195210
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
@@ -255,6 +270,12 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
255270
priv->fs.vlan.any_svlan_rule = NULL;
256271
}
257272
break;
273+
case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
274+
if (priv->fs.vlan.active_svlans_rule[vid]) {
275+
mlx5_del_flow_rules(priv->fs.vlan.active_svlans_rule[vid]);
276+
priv->fs.vlan.active_svlans_rule[vid] = NULL;
277+
}
278+
break;
258279
case MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID:
259280
mlx5e_vport_context_update_vlans(priv);
260281
if (priv->fs.vlan.active_cvlans_rule[vid]) {
@@ -305,10 +326,8 @@ void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv)
305326
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
306327
}
307328

308-
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
309-
u16 vid)
329+
static int mlx5e_vlan_rx_add_cvid(struct mlx5e_priv *priv, u16 vid)
310330
{
311-
struct mlx5e_priv *priv = netdev_priv(dev);
312331
int err;
313332

314333
set_bit(vid, priv->fs.vlan.active_cvlans);
@@ -320,14 +339,48 @@ int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
320339
return err;
321340
}
322341

323-
int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
324-
u16 vid)
342+
static int mlx5e_vlan_rx_add_svid(struct mlx5e_priv *priv, u16 vid)
343+
{
344+
struct net_device *netdev = priv->netdev;
345+
int err;
346+
347+
set_bit(vid, priv->fs.vlan.active_svlans);
348+
349+
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
350+
if (err) {
351+
clear_bit(vid, priv->fs.vlan.active_svlans);
352+
return err;
353+
}
354+
355+
/* Need to fix some features.. */
356+
netdev_update_features(netdev);
357+
return err;
358+
}
359+
360+
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
325361
{
326362
struct mlx5e_priv *priv = netdev_priv(dev);
327363

328-
clear_bit(vid, priv->fs.vlan.active_cvlans);
364+
if (be16_to_cpu(proto) == ETH_P_8021Q)
365+
return mlx5e_vlan_rx_add_cvid(priv, vid);
366+
else if (be16_to_cpu(proto) == ETH_P_8021AD)
367+
return mlx5e_vlan_rx_add_svid(priv, vid);
329368

330-
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
369+
return -EOPNOTSUPP;
370+
}
371+
372+
int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
373+
{
374+
struct mlx5e_priv *priv = netdev_priv(dev);
375+
376+
if (be16_to_cpu(proto) == ETH_P_8021Q) {
377+
clear_bit(vid, priv->fs.vlan.active_cvlans);
378+
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
379+
} else if (be16_to_cpu(proto) == ETH_P_8021AD) {
380+
clear_bit(vid, priv->fs.vlan.active_svlans);
381+
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
382+
netdev_update_features(dev);
383+
}
331384

332385
return 0;
333386
}
@@ -342,6 +395,9 @@ static void mlx5e_add_vlan_rules(struct mlx5e_priv *priv)
342395
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
343396
}
344397

398+
for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
399+
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
400+
345401
if (priv->fs.vlan.cvlan_filter_disabled &&
346402
!(priv->netdev->flags & IFF_PROMISC))
347403
mlx5e_add_any_vid_rules(priv);
@@ -357,6 +413,9 @@ static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
357413
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
358414
}
359415

416+
for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
417+
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
418+
360419
if (priv->fs.vlan.cvlan_filter_disabled &&
361420
!(priv->netdev->flags & IFF_PROMISC))
362421
mlx5e_del_any_vid_rules(priv);
@@ -550,6 +609,9 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
550609
bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
551610

552611
if (enable_promisc) {
612+
if (!priv->channels.params.vlan_strip_disable)
613+
netdev_warn_once(ndev,
614+
"S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
553615
mlx5e_add_l2_flow_rule(priv, &ea->promisc, MLX5E_PROMISC);
554616
if (!priv->fs.vlan.cvlan_filter_disabled)
555617
mlx5e_add_any_vid_rules(priv);
@@ -1270,13 +1332,15 @@ static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
12701332
return err;
12711333
}
12721334

1273-
#define MLX5E_NUM_VLAN_GROUPS 3
1335+
#define MLX5E_NUM_VLAN_GROUPS 4
12741336
#define MLX5E_VLAN_GROUP0_SIZE BIT(12)
1275-
#define MLX5E_VLAN_GROUP1_SIZE BIT(1)
1276-
#define MLX5E_VLAN_GROUP2_SIZE BIT(0)
1337+
#define MLX5E_VLAN_GROUP1_SIZE BIT(12)
1338+
#define MLX5E_VLAN_GROUP2_SIZE BIT(1)
1339+
#define MLX5E_VLAN_GROUP3_SIZE BIT(0)
12771340
#define MLX5E_VLAN_TABLE_SIZE (MLX5E_VLAN_GROUP0_SIZE +\
12781341
MLX5E_VLAN_GROUP1_SIZE +\
1279-
MLX5E_VLAN_GROUP2_SIZE)
1342+
MLX5E_VLAN_GROUP2_SIZE +\
1343+
MLX5E_VLAN_GROUP3_SIZE)
12801344

12811345
static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in,
12821346
int inlen)
@@ -1299,7 +1363,8 @@ static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in
12991363

13001364
memset(in, 0, inlen);
13011365
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1302-
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
1366+
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1367+
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
13031368
MLX5_SET_CFG(in, start_flow_index, ix);
13041369
ix += MLX5E_VLAN_GROUP1_SIZE;
13051370
MLX5_SET_CFG(in, end_flow_index, ix - 1);
@@ -1310,7 +1375,7 @@ static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in
13101375

13111376
memset(in, 0, inlen);
13121377
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1313-
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1378+
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
13141379
MLX5_SET_CFG(in, start_flow_index, ix);
13151380
ix += MLX5E_VLAN_GROUP2_SIZE;
13161381
MLX5_SET_CFG(in, end_flow_index, ix - 1);
@@ -1319,6 +1384,17 @@ static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in
13191384
goto err_destroy_groups;
13201385
ft->num_groups++;
13211386

1387+
memset(in, 0, inlen);
1388+
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1389+
MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1390+
MLX5_SET_CFG(in, start_flow_index, ix);
1391+
ix += MLX5E_VLAN_GROUP3_SIZE;
1392+
MLX5_SET_CFG(in, end_flow_index, ix - 1);
1393+
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1394+
if (IS_ERR(ft->g[ft->num_groups]))
1395+
goto err_destroy_groups;
1396+
ft->num_groups++;
1397+
13221398
return 0;
13231399

13241400
err_destroy_groups:

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,6 +3395,25 @@ static int mlx5e_set_features(struct net_device *netdev,
33953395
return err ? -EINVAL : 0;
33963396
}
33973397

3398+
static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
3399+
netdev_features_t features)
3400+
{
3401+
struct mlx5e_priv *priv = netdev_priv(netdev);
3402+
3403+
mutex_lock(&priv->state_lock);
3404+
if (!bitmap_empty(priv->fs.vlan.active_svlans, VLAN_N_VID)) {
3405+
/* HW strips the outer C-tag header, this is a problem
3406+
* for S-tag traffic.
3407+
*/
3408+
features &= ~NETIF_F_HW_VLAN_CTAG_RX;
3409+
if (!priv->channels.params.vlan_strip_disable)
3410+
netdev_warn(netdev, "Dropping C-tag vlan stripping offload due to S-tag vlan\n");
3411+
}
3412+
mutex_unlock(&priv->state_lock);
3413+
3414+
return features;
3415+
}
3416+
33983417
static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
33993418
{
34003419
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -3872,6 +3891,7 @@ static const struct net_device_ops mlx5e_netdev_ops = {
38723891
.ndo_vlan_rx_add_vid = mlx5e_vlan_rx_add_vid,
38733892
.ndo_vlan_rx_kill_vid = mlx5e_vlan_rx_kill_vid,
38743893
.ndo_set_features = mlx5e_set_features,
3894+
.ndo_fix_features = mlx5e_fix_features,
38753895
.ndo_change_mtu = mlx5e_change_mtu,
38763896
.ndo_do_ioctl = mlx5e_ioctl,
38773897
.ndo_set_tx_maxrate = mlx5e_set_tx_maxrate,
@@ -4231,6 +4251,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
42314251
}
42324252

42334253
netdev->features |= NETIF_F_HIGHDMA;
4254+
netdev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
42344255

42354256
netdev->priv_flags |= IFF_UNICAST_FLT;
42364257

0 commit comments

Comments
 (0)