Skip to content

Commit c358ea1

Browse files
w1ldptrSaeed Mahameed
authored andcommitted
net/mlx5: Bridge, allow merged eswitch connectivity
Allow connectivity between representors of different eswitch instances that are attached to same bridge when merged_eswitch capability is enabled. Add ports of peer eswitch to bridge instance and mark them with MLX5_ESW_BRIDGE_PORT_FLAG_PEER. Mark FDBs offloaded on peer ports with MLX5_ESW_BRIDGE_FLAG_PEER flag. Such FDBs can only be aged out on their local eswitch instance, which then sends SWITCHDEV_FDB_DEL_TO_BRIDGE event. Listen to the event on mlx5 bridge implementation and delete peer FDBs in event handler. Signed-off-by: Vlad Buslov <[email protected]> Reviewed-by: Roi Dayan <[email protected]> Reviewed-by: Mark Bloch <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent bf3d56d commit c358ea1

File tree

5 files changed

+112
-28
lines changed

5 files changed

+112
-28
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct mlx5_bridge_switchdev_fdb_work {
1515
struct work_struct work;
1616
struct switchdev_notifier_fdb_info fdb_info;
1717
struct net_device *dev;
18+
struct mlx5_esw_bridge_offloads *br_offloads;
1819
bool add;
1920
};
2021

@@ -25,13 +26,28 @@ static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_esw
2526
return esw == priv->mdev->priv.eswitch;
2627
}
2728

29+
static bool mlx5_esw_bridge_dev_same_hw(struct net_device *dev, struct mlx5_eswitch *esw)
30+
{
31+
struct mlx5e_priv *priv = netdev_priv(dev);
32+
struct mlx5_core_dev *mdev, *esw_mdev;
33+
u64 system_guid, esw_system_guid;
34+
35+
mdev = priv->mdev;
36+
esw_mdev = esw->dev;
37+
38+
system_guid = mlx5_query_nic_system_image_guid(mdev);
39+
esw_system_guid = mlx5_query_nic_system_image_guid(esw_mdev);
40+
41+
return system_guid == esw_system_guid;
42+
}
43+
2844
static int mlx5_esw_bridge_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw,
2945
u16 *vport_num, u16 *esw_owner_vhca_id)
3046
{
3147
struct mlx5e_rep_priv *rpriv;
3248
struct mlx5e_priv *priv;
3349

34-
if (!mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_esw(dev, esw))
50+
if (!mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_hw(dev, esw))
3551
return -ENODEV;
3652

3753
priv = netdev_priv(dev);
@@ -48,7 +64,7 @@ mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct m
4864
struct net_device *lower_dev;
4965
struct list_head *iter;
5066

51-
if (mlx5e_eswitch_rep(dev) && mlx5_esw_bridge_dev_same_esw(dev, esw))
67+
if (mlx5e_eswitch_rep(dev))
5268
return mlx5_esw_bridge_vport_num_vhca_id_get(dev, esw, vport_num,
5369
esw_owner_vhca_id);
5470

@@ -74,6 +90,7 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
7490
netdev_nb);
7591
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
7692
struct netdev_notifier_changeupper_info *info = ptr;
93+
struct mlx5_eswitch *esw = br_offloads->esw;
7794
struct net_device *upper = info->upper_dev;
7895
u16 vport_num, esw_owner_vhca_id;
7996
struct netlink_ext_ack *extack;
@@ -90,11 +107,20 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
90107

91108
extack = netdev_notifier_info_to_extack(&info->info);
92109

93-
return info->linking ?
94-
mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
95-
extack) :
96-
mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
97-
extack);
110+
if (mlx5_esw_bridge_dev_same_esw(dev, esw))
111+
err = info->linking ?
112+
mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id,
113+
br_offloads, extack) :
114+
mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id,
115+
br_offloads, extack);
116+
else if (mlx5_esw_bridge_dev_same_hw(dev, esw))
117+
err = info->linking ?
118+
mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id,
119+
br_offloads, extack) :
120+
mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id,
121+
br_offloads, extack);
122+
123+
return err;
98124
}
99125

100126
static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
@@ -253,16 +279,14 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
253279
container_of(work, struct mlx5_bridge_switchdev_fdb_work, work);
254280
struct switchdev_notifier_fdb_info *fdb_info =
255281
&fdb_work->fdb_info;
256-
struct mlx5_esw_bridge_offloads *br_offloads;
282+
struct mlx5_esw_bridge_offloads *br_offloads =
283+
fdb_work->br_offloads;
257284
struct net_device *dev = fdb_work->dev;
258285
u16 vport_num, esw_owner_vhca_id;
259-
struct mlx5e_priv *priv;
260286
int err;
261287

262288
rtnl_lock();
263289

264-
priv = netdev_priv(dev);
265-
br_offloads = priv->mdev->priv.eswitch->br_offloads;
266290
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
267291
&esw_owner_vhca_id);
268292
if (err)
@@ -282,7 +306,8 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
282306

283307
static struct mlx5_bridge_switchdev_fdb_work *
284308
mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,
285-
struct switchdev_notifier_fdb_info *fdb_info)
309+
struct switchdev_notifier_fdb_info *fdb_info,
310+
struct mlx5_esw_bridge_offloads *br_offloads)
286311
{
287312
struct mlx5_bridge_switchdev_fdb_work *work;
288313
u8 *addr;
@@ -304,6 +329,7 @@ mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,
304329

305330
dev_hold(dev);
306331
work->dev = dev;
332+
work->br_offloads = br_offloads;
307333
work->add = add;
308334
return work;
309335
}
@@ -334,10 +360,13 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
334360

335361
if (!mlx5e_eswitch_rep(dev))
336362
return NOTIFY_DONE;
337-
if (!mlx5_esw_bridge_dev_same_esw(dev, br_offloads->esw))
338-
return NOTIFY_DONE;
339363

340364
switch (event) {
365+
case SWITCHDEV_FDB_DEL_TO_BRIDGE:
366+
/* only handle the event when source is on another eswitch */
367+
if (mlx5_esw_bridge_dev_same_esw(dev, br_offloads->esw))
368+
break;
369+
fallthrough;
341370
case SWITCHDEV_FDB_ADD_TO_DEVICE:
342371
case SWITCHDEV_FDB_DEL_TO_DEVICE:
343372
fdb_info = container_of(info,
@@ -346,7 +375,8 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
346375

347376
work = mlx5_esw_bridge_init_switchdev_fdb_work(dev,
348377
event == SWITCHDEV_FDB_ADD_TO_DEVICE,
349-
fdb_info);
378+
fdb_info,
379+
br_offloads);
350380
if (IS_ERR(work)) {
351381
WARN_ONCE(1, "Failed to init switchdev work, err=%ld",
352382
PTR_ERR(work));

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

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *
7979
static void
8080
mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry)
8181
{
82-
if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER))
82+
if (!(entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | MLX5_ESW_BRIDGE_FLAG_PEER)))
8383
mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
8484
entry->key.vid,
8585
SWITCHDEV_FDB_DEL_TO_BRIDGE);
@@ -513,7 +513,7 @@ mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *a
513513
}
514514

515515
static struct mlx5_flow_handle *
516-
mlx5_esw_bridge_egress_flow_create(u16 vport_num, const unsigned char *addr,
516+
mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr,
517517
struct mlx5_esw_bridge_vlan *vlan,
518518
struct mlx5_esw_bridge *bridge)
519519
{
@@ -558,6 +558,10 @@ mlx5_esw_bridge_egress_flow_create(u16 vport_num, const unsigned char *addr,
558558
vlan->vid);
559559
}
560560

561+
if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) {
562+
dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
563+
dest.vport.vhca_id = esw_owner_vhca_id;
564+
}
561565
handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1);
562566

563567
kvfree(rule_spec);
@@ -917,7 +921,7 @@ mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id,
917921

918922
static struct mlx5_esw_bridge_fdb_entry *
919923
mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
920-
const unsigned char *addr, u16 vid, bool added_by_user,
924+
const unsigned char *addr, u16 vid, bool added_by_user, bool peer,
921925
struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge)
922926
{
923927
struct mlx5_esw_bridge_vlan *vlan = NULL;
@@ -945,6 +949,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
945949
entry->lastuse = jiffies;
946950
if (added_by_user)
947951
entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER;
952+
if (peer)
953+
entry->flags |= MLX5_ESW_BRIDGE_FLAG_PEER;
948954

949955
counter = mlx5_fc_create(esw->dev, true);
950956
if (IS_ERR(counter)) {
@@ -974,7 +980,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
974980
entry->filter_handle = handle;
975981
}
976982

977-
handle = mlx5_esw_bridge_egress_flow_create(vport_num, addr, vlan, bridge);
983+
handle = mlx5_esw_bridge_egress_flow_create(vport_num, esw_owner_vhca_id, addr, vlan,
984+
bridge);
978985
if (IS_ERR(handle)) {
979986
err = PTR_ERR(handle);
980987
esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n",
@@ -1050,7 +1057,7 @@ int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, boo
10501057
return 0;
10511058
}
10521059

1053-
static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id,
1060+
static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, u16 flags,
10541061
struct mlx5_esw_bridge_offloads *br_offloads,
10551062
struct mlx5_esw_bridge *bridge)
10561063
{
@@ -1065,6 +1072,7 @@ static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id,
10651072
port->vport_num = vport_num;
10661073
port->esw_owner_vhca_id = esw_owner_vhca_id;
10671074
port->bridge = bridge;
1075+
port->flags |= flags;
10681076
xa_init(&port->vlans);
10691077
err = mlx5_esw_bridge_port_insert(port, br_offloads);
10701078
if (err) {
@@ -1101,9 +1109,10 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off
11011109
return 0;
11021110
}
11031111

1104-
int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1105-
struct mlx5_esw_bridge_offloads *br_offloads,
1106-
struct netlink_ext_ack *extack)
1112+
static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1113+
u16 flags,
1114+
struct mlx5_esw_bridge_offloads *br_offloads,
1115+
struct netlink_ext_ack *extack)
11071116
{
11081117
struct mlx5_esw_bridge *bridge;
11091118
int err;
@@ -1114,7 +1123,7 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
11141123
return PTR_ERR(bridge);
11151124
}
11161125

1117-
err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, br_offloads, bridge);
1126+
err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, flags, br_offloads, bridge);
11181127
if (err) {
11191128
NL_SET_ERR_MSG_MOD(extack, "Error initializing port");
11201129
goto err_vport;
@@ -1126,6 +1135,14 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
11261135
return err;
11271136
}
11281137

1138+
int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1139+
struct mlx5_esw_bridge_offloads *br_offloads,
1140+
struct netlink_ext_ack *extack)
1141+
{
1142+
return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0,
1143+
br_offloads, extack);
1144+
}
1145+
11291146
int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
11301147
struct mlx5_esw_bridge_offloads *br_offloads,
11311148
struct netlink_ext_ack *extack)
@@ -1149,6 +1166,26 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
11491166
return err;
11501167
}
11511168

1169+
int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1170+
struct mlx5_esw_bridge_offloads *br_offloads,
1171+
struct netlink_ext_ack *extack)
1172+
{
1173+
if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
1174+
return 0;
1175+
1176+
return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id,
1177+
MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
1178+
br_offloads, extack);
1179+
}
1180+
1181+
int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1182+
struct mlx5_esw_bridge_offloads *br_offloads,
1183+
struct netlink_ext_ack *extack)
1184+
{
1185+
return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
1186+
extack);
1187+
}
1188+
11521189
int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags,
11531190
struct mlx5_esw_bridge_offloads *br_offloads,
11541191
struct netlink_ext_ack *extack)
@@ -1206,14 +1243,15 @@ void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_o
12061243
bridge = port->bridge;
12071244
entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr,
12081245
fdb_info->vid, fdb_info->added_by_user,
1246+
port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
12091247
br_offloads->esw, bridge);
12101248
if (IS_ERR(entry))
12111249
return;
12121250

12131251
if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
12141252
mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
12151253
SWITCHDEV_FDB_OFFLOADED);
1216-
else
1254+
else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER))
12171255
/* Take over dynamic entries to prevent kernel bridge from aging them out. */
12181256
mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
12191257
SWITCHDEV_FDB_ADD_TO_BRIDGE);
@@ -1263,7 +1301,8 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
12631301

12641302
if (time_after(lastuse, entry->lastuse)) {
12651303
mlx5_esw_bridge_fdb_entry_refresh(lastuse, entry);
1266-
} else if (time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) {
1304+
} else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) &&
1305+
time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) {
12671306
mlx5_esw_bridge_fdb_del_notify(entry);
12681307
mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
12691308
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
4040
int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
4141
struct mlx5_esw_bridge_offloads *br_offloads,
4242
struct netlink_ext_ack *extack);
43+
int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
44+
struct mlx5_esw_bridge_offloads *br_offloads,
45+
struct netlink_ext_ack *extack);
46+
int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
47+
struct mlx5_esw_bridge_offloads *br_offloads,
48+
struct netlink_ext_ack *extack);
4349
void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
4450
struct mlx5_esw_bridge_offloads *br_offloads,
4551
struct switchdev_notifier_fdb_info *fdb_info);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ struct mlx5_esw_bridge_fdb_key {
1919

2020
enum {
2121
MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0),
22+
MLX5_ESW_BRIDGE_FLAG_PEER = BIT(1),
23+
};
24+
25+
enum {
26+
MLX5_ESW_BRIDGE_PORT_FLAG_PEER = BIT(0),
2227
};
2328

2429
struct mlx5_esw_bridge_fdb_entry {
@@ -49,6 +54,7 @@ struct mlx5_esw_bridge_vlan {
4954
struct mlx5_esw_bridge_port {
5055
u16 vport_num;
5156
u16 esw_owner_vhca_id;
57+
u16 flags;
5258
struct mlx5_esw_bridge *bridge;
5359
struct xarray vlans;
5460
};

drivers/net/ethernet/mellanox/mlx5/core/esw/diag/bridge_tracepoint.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,17 @@ DECLARE_EVENT_CLASS(mlx5_esw_bridge_port_template,
8686
TP_STRUCT__entry(
8787
__field(u16, vport_num)
8888
__field(u16, esw_owner_vhca_id)
89+
__field(u16, flags)
8990
),
9091
TP_fast_assign(
9192
__entry->vport_num = port->vport_num;
9293
__entry->esw_owner_vhca_id = port->esw_owner_vhca_id;
94+
__entry->flags = port->flags;
9395
),
94-
TP_printk("vport_num=%hu esw_owner_vhca_id=%hu",
96+
TP_printk("vport_num=%hu esw_owner_vhca_id=%hu flags=%hx",
9597
__entry->vport_num,
96-
__entry->esw_owner_vhca_id)
98+
__entry->esw_owner_vhca_id,
99+
__entry->flags)
97100
);
98101

99102
DEFINE_EVENT(mlx5_esw_bridge_port_template,

0 commit comments

Comments
 (0)