Skip to content

Commit 9c0ca9b

Browse files
w1ldptrSaeed Mahameed
authored andcommitted
net/mlx5: Bridge, implement QinQ support
Implement support for new 802.1ad VLAN protocol type. Create new flow groups that handle svlan tags. Create FDB flows with svlan tag match when bridge VLAN is set to QinQ. Signed-off-by: Vlad Buslov <[email protected]> Reviewed-by: Roi Dayan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent c5fcac9 commit 9c0ca9b

File tree

2 files changed

+111
-8
lines changed

2 files changed

+111
-8
lines changed

drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
#define CREATE_TRACE_POINTS
1414
#include "diag/bridge_tracepoint.h"
1515

16-
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE 16000
17-
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_UNTAGGED_GRP_SIZE 32000
16+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE 12000
17+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_UNTAGGED_GRP_SIZE 16000
1818
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM 0
1919
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO \
2020
(MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE - 1)
@@ -23,22 +23,37 @@
2323
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_TO \
2424
(MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_FROM + \
2525
MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE - 1)
26-
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM \
26+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_FROM \
2727
(MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_TO + 1)
28+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_TO \
29+
(MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_FROM + \
30+
MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE - 1)
31+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_FROM \
32+
(MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_TO + 1)
33+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_TO \
34+
(MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_FROM + \
35+
MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_SIZE - 1)
36+
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM \
37+
(MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_TO + 1)
2838
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO \
2939
(MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM + \
3040
MLX5_ESW_BRIDGE_INGRESS_TABLE_UNTAGGED_GRP_SIZE - 1)
3141
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE \
3242
(MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO + 1)
3343
static_assert(MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE == 64000);
3444

35-
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_SIZE 32000
45+
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_SIZE 16000
3646
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_SIZE (32000 - 1)
3747
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_FROM 0
3848
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO \
3949
(MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_SIZE - 1)
40-
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM \
50+
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_FROM \
4151
(MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO + 1)
52+
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_TO \
53+
(MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_FROM + \
54+
MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_SIZE - 1)
55+
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM \
56+
(MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_TO + 1)
4257
#define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO \
4358
(MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM + \
4459
MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_SIZE - 1)
@@ -80,6 +95,7 @@ struct mlx5_esw_bridge {
8095

8196
struct mlx5_flow_table *egress_ft;
8297
struct mlx5_flow_group *egress_vlan_fg;
98+
struct mlx5_flow_group *egress_qinq_fg;
8399
struct mlx5_flow_group *egress_mac_fg;
84100
struct mlx5_flow_group *egress_miss_fg;
85101
struct mlx5_pkt_reformat *egress_miss_pkt_reformat;
@@ -176,6 +192,8 @@ mlx5_esw_bridge_ingress_vlan_proto_fg_create(unsigned int from, unsigned int to,
176192
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
177193
if (vlan_proto == ETH_P_8021Q)
178194
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
195+
else if (vlan_proto == ETH_P_8021AD)
196+
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
179197
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
180198

181199
MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
@@ -204,6 +222,17 @@ mlx5_esw_bridge_ingress_vlan_fg_create(struct mlx5_eswitch *esw,
204222
return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, ingress_ft);
205223
}
206224

225+
static struct mlx5_flow_group *
226+
mlx5_esw_bridge_ingress_qinq_fg_create(struct mlx5_eswitch *esw,
227+
struct mlx5_flow_table *ingress_ft)
228+
{
229+
unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_FROM;
230+
unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_TO;
231+
232+
return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw,
233+
ingress_ft);
234+
}
235+
207236
static struct mlx5_flow_group *
208237
mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(unsigned int from, unsigned int to,
209238
u16 vlan_proto, struct mlx5_eswitch *esw,
@@ -225,6 +254,8 @@ mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(unsigned int from, unsigned
225254
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
226255
if (vlan_proto == ETH_P_8021Q)
227256
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
257+
else if (vlan_proto == ETH_P_8021AD)
258+
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
228259
MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
229260
mlx5_eswitch_get_vport_metadata_mask());
230261

@@ -251,6 +282,17 @@ mlx5_esw_bridge_ingress_vlan_filter_fg_create(struct mlx5_eswitch *esw,
251282
ingress_ft);
252283
}
253284

285+
static struct mlx5_flow_group *
286+
mlx5_esw_bridge_ingress_qinq_filter_fg_create(struct mlx5_eswitch *esw,
287+
struct mlx5_flow_table *ingress_ft)
288+
{
289+
unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_FROM;
290+
unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_TO;
291+
292+
return mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(from, to, ETH_P_8021AD, esw,
293+
ingress_ft);
294+
}
295+
254296
static struct mlx5_flow_group *
255297
mlx5_esw_bridge_ingress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *ingress_ft)
256298
{
@@ -307,6 +349,8 @@ mlx5_esw_bridge_egress_vlan_proto_fg_create(unsigned int from, unsigned int to,
307349
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0);
308350
if (vlan_proto == ETH_P_8021Q)
309351
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
352+
else if (vlan_proto == ETH_P_8021AD)
353+
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
310354
MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
311355

312356
MLX5_SET(create_flow_group_in, in, start_flow_index, from);
@@ -330,6 +374,16 @@ mlx5_esw_bridge_egress_vlan_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow
330374
return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, egress_ft);
331375
}
332376

377+
static struct mlx5_flow_group *
378+
mlx5_esw_bridge_egress_qinq_fg_create(struct mlx5_eswitch *esw,
379+
struct mlx5_flow_table *egress_ft)
380+
{
381+
unsigned int from = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_FROM;
382+
unsigned int to = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_TO;
383+
384+
return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw, egress_ft);
385+
}
386+
333387
static struct mlx5_flow_group *
334388
mlx5_esw_bridge_egress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
335389
{
@@ -394,7 +448,7 @@ mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow
394448
static int
395449
mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads)
396450
{
397-
struct mlx5_flow_group *mac_fg, *vlan_filter_fg, *vlan_fg;
451+
struct mlx5_flow_group *mac_fg, *qinq_filter_fg, *qinq_fg, *vlan_filter_fg, *vlan_fg;
398452
struct mlx5_flow_table *ingress_ft, *skip_ft;
399453
struct mlx5_eswitch *esw = br_offloads->esw;
400454
int err;
@@ -428,6 +482,18 @@ mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads)
428482
goto err_vlan_filter_fg;
429483
}
430484

485+
qinq_fg = mlx5_esw_bridge_ingress_qinq_fg_create(esw, ingress_ft);
486+
if (IS_ERR(qinq_fg)) {
487+
err = PTR_ERR(qinq_fg);
488+
goto err_qinq_fg;
489+
}
490+
491+
qinq_filter_fg = mlx5_esw_bridge_ingress_qinq_filter_fg_create(esw, ingress_ft);
492+
if (IS_ERR(qinq_filter_fg)) {
493+
err = PTR_ERR(qinq_filter_fg);
494+
goto err_qinq_filter_fg;
495+
}
496+
431497
mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(esw, ingress_ft);
432498
if (IS_ERR(mac_fg)) {
433499
err = PTR_ERR(mac_fg);
@@ -438,10 +504,16 @@ mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads)
438504
br_offloads->skip_ft = skip_ft;
439505
br_offloads->ingress_vlan_fg = vlan_fg;
440506
br_offloads->ingress_vlan_filter_fg = vlan_filter_fg;
507+
br_offloads->ingress_qinq_fg = qinq_fg;
508+
br_offloads->ingress_qinq_filter_fg = qinq_filter_fg;
441509
br_offloads->ingress_mac_fg = mac_fg;
442510
return 0;
443511

444512
err_mac_fg:
513+
mlx5_destroy_flow_group(qinq_filter_fg);
514+
err_qinq_filter_fg:
515+
mlx5_destroy_flow_group(qinq_fg);
516+
err_qinq_fg:
445517
mlx5_destroy_flow_group(vlan_filter_fg);
446518
err_vlan_filter_fg:
447519
mlx5_destroy_flow_group(vlan_fg);
@@ -457,6 +529,10 @@ mlx5_esw_bridge_ingress_table_cleanup(struct mlx5_esw_bridge_offloads *br_offloa
457529
{
458530
mlx5_destroy_flow_group(br_offloads->ingress_mac_fg);
459531
br_offloads->ingress_mac_fg = NULL;
532+
mlx5_destroy_flow_group(br_offloads->ingress_qinq_filter_fg);
533+
br_offloads->ingress_qinq_filter_fg = NULL;
534+
mlx5_destroy_flow_group(br_offloads->ingress_qinq_fg);
535+
br_offloads->ingress_qinq_fg = NULL;
460536
mlx5_destroy_flow_group(br_offloads->ingress_vlan_filter_fg);
461537
br_offloads->ingress_vlan_filter_fg = NULL;
462538
mlx5_destroy_flow_group(br_offloads->ingress_vlan_fg);
@@ -476,7 +552,7 @@ static int
476552
mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads,
477553
struct mlx5_esw_bridge *bridge)
478554
{
479-
struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg;
555+
struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg, *qinq_fg;
480556
struct mlx5_pkt_reformat *miss_pkt_reformat = NULL;
481557
struct mlx5_flow_handle *miss_handle = NULL;
482558
struct mlx5_eswitch *esw = br_offloads->esw;
@@ -495,6 +571,12 @@ mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads,
495571
goto err_vlan_fg;
496572
}
497573

574+
qinq_fg = mlx5_esw_bridge_egress_qinq_fg_create(esw, egress_ft);
575+
if (IS_ERR(qinq_fg)) {
576+
err = PTR_ERR(qinq_fg);
577+
goto err_qinq_fg;
578+
}
579+
498580
mac_fg = mlx5_esw_bridge_egress_mac_fg_create(esw, egress_ft);
499581
if (IS_ERR(mac_fg)) {
500582
err = PTR_ERR(mac_fg);
@@ -539,13 +621,16 @@ mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads,
539621

540622
bridge->egress_ft = egress_ft;
541623
bridge->egress_vlan_fg = vlan_fg;
624+
bridge->egress_qinq_fg = qinq_fg;
542625
bridge->egress_mac_fg = mac_fg;
543626
bridge->egress_miss_fg = miss_fg;
544627
bridge->egress_miss_pkt_reformat = miss_pkt_reformat;
545628
bridge->egress_miss_handle = miss_handle;
546629
return 0;
547630

548631
err_mac_fg:
632+
mlx5_destroy_flow_group(qinq_fg);
633+
err_qinq_fg:
549634
mlx5_destroy_flow_group(vlan_fg);
550635
err_vlan_fg:
551636
mlx5_destroy_flow_table(egress_ft);
@@ -563,6 +648,7 @@ mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge)
563648
if (bridge->egress_miss_fg)
564649
mlx5_destroy_flow_group(bridge->egress_miss_fg);
565650
mlx5_destroy_flow_group(bridge->egress_mac_fg);
651+
mlx5_destroy_flow_group(bridge->egress_qinq_fg);
566652
mlx5_destroy_flow_group(bridge->egress_vlan_fg);
567653
mlx5_destroy_flow_table(bridge->egress_ft);
568654
}
@@ -612,6 +698,11 @@ mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char
612698
outer_headers.cvlan_tag);
613699
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
614700
outer_headers.cvlan_tag);
701+
} else if (bridge->vlan_proto == ETH_P_8021AD) {
702+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
703+
outer_headers.svlan_tag);
704+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
705+
outer_headers.svlan_tag);
615706
}
616707
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
617708
outer_headers.first_vid);
@@ -700,6 +791,11 @@ mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *a
700791
outer_headers.cvlan_tag);
701792
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
702793
outer_headers.cvlan_tag);
794+
} else if (bridge->vlan_proto == ETH_P_8021AD) {
795+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
796+
outer_headers.svlan_tag);
797+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
798+
outer_headers.svlan_tag);
703799
}
704800

705801
handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, &dest, 1);
@@ -753,6 +849,11 @@ mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const u
753849
outer_headers.cvlan_tag);
754850
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
755851
outer_headers.cvlan_tag);
852+
} else if (bridge->vlan_proto == ETH_P_8021AD) {
853+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
854+
outer_headers.svlan_tag);
855+
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
856+
outer_headers.svlan_tag);
756857
}
757858
MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
758859
outer_headers.first_vid);
@@ -1421,7 +1522,7 @@ int mlx5_esw_bridge_vlan_proto_set(u16 vport_num, u16 esw_owner_vhca_id, u16 pro
14211522
bridge = port->bridge;
14221523
if (bridge->vlan_proto == proto)
14231524
return 0;
1424-
if (proto != ETH_P_8021Q) {
1525+
if (proto != ETH_P_8021Q && proto != ETH_P_8021AD) {
14251526
esw_warn(br_offloads->esw->dev, "Can't set unsupported VLAN protocol %x", proto);
14261527
return -EOPNOTSUPP;
14271528
}

drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct mlx5_esw_bridge_offloads {
2727
struct mlx5_flow_table *ingress_ft;
2828
struct mlx5_flow_group *ingress_vlan_fg;
2929
struct mlx5_flow_group *ingress_vlan_filter_fg;
30+
struct mlx5_flow_group *ingress_qinq_fg;
31+
struct mlx5_flow_group *ingress_qinq_filter_fg;
3032
struct mlx5_flow_group *ingress_mac_fg;
3133

3234
struct mlx5_flow_table *skip_ft;

0 commit comments

Comments
 (0)