@@ -41,46 +41,88 @@ static bool mlx5_esw_bridge_dev_same_hw(struct net_device *dev, struct mlx5_eswi
41
41
return system_guid == esw_system_guid ;
42
42
}
43
43
44
- static int mlx5_esw_bridge_vport_num_vhca_id_get (struct net_device * dev , struct mlx5_eswitch * esw ,
45
- u16 * vport_num , u16 * esw_owner_vhca_id )
44
+ static struct net_device *
45
+ mlx5_esw_bridge_lag_rep_get (struct net_device * dev , struct mlx5_eswitch * esw )
46
+ {
47
+ struct net_device * lower ;
48
+ struct list_head * iter ;
49
+
50
+ netdev_for_each_lower_dev (dev , lower , iter ) {
51
+ struct mlx5_core_dev * mdev ;
52
+ struct mlx5e_priv * priv ;
53
+
54
+ if (!mlx5e_eswitch_rep (lower ))
55
+ continue ;
56
+
57
+ priv = netdev_priv (lower );
58
+ mdev = priv -> mdev ;
59
+ if (mlx5_lag_is_shared_fdb (mdev ) && mlx5_esw_bridge_dev_same_esw (lower , esw ))
60
+ return lower ;
61
+ }
62
+
63
+ return NULL ;
64
+ }
65
+
66
+ static struct net_device *
67
+ mlx5_esw_bridge_rep_vport_num_vhca_id_get (struct net_device * dev , struct mlx5_eswitch * esw ,
68
+ u16 * vport_num , u16 * esw_owner_vhca_id )
46
69
{
47
70
struct mlx5e_rep_priv * rpriv ;
48
71
struct mlx5e_priv * priv ;
49
72
50
- if (!mlx5e_eswitch_rep (dev ) || !mlx5_esw_bridge_dev_same_hw (dev , esw ))
51
- return - ENODEV ;
73
+ if (netif_is_lag_master (dev ))
74
+ dev = mlx5_esw_bridge_lag_rep_get (dev , esw );
75
+
76
+ if (!dev || !mlx5e_eswitch_rep (dev ) || !mlx5_esw_bridge_dev_same_hw (dev , esw ))
77
+ return NULL ;
52
78
53
79
priv = netdev_priv (dev );
54
80
rpriv = priv -> ppriv ;
55
81
* vport_num = rpriv -> rep -> vport ;
56
82
* esw_owner_vhca_id = MLX5_CAP_GEN (priv -> mdev , vhca_id );
57
- return 0 ;
83
+ return dev ;
58
84
}
59
85
60
- static int
86
+ static struct net_device *
61
87
mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get (struct net_device * dev , struct mlx5_eswitch * esw ,
62
88
u16 * vport_num , u16 * esw_owner_vhca_id )
63
89
{
64
90
struct net_device * lower_dev ;
65
91
struct list_head * iter ;
66
92
67
- if (mlx5e_eswitch_rep (dev ))
68
- return mlx5_esw_bridge_vport_num_vhca_id_get (dev , esw , vport_num ,
69
- esw_owner_vhca_id );
93
+ if (netif_is_lag_master ( dev ) || mlx5e_eswitch_rep (dev ))
94
+ return mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , esw , vport_num ,
95
+ esw_owner_vhca_id );
70
96
71
97
netdev_for_each_lower_dev (dev , lower_dev , iter ) {
72
- int err ;
98
+ struct net_device * rep ;
73
99
74
100
if (netif_is_bridge_master (lower_dev ))
75
101
continue ;
76
102
77
- err = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get (lower_dev , esw , vport_num ,
103
+ rep = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get (lower_dev , esw , vport_num ,
78
104
esw_owner_vhca_id );
79
- if (! err )
80
- return 0 ;
105
+ if (rep )
106
+ return rep ;
81
107
}
82
108
83
- return - ENODEV ;
109
+ return NULL ;
110
+ }
111
+
112
+ static bool mlx5_esw_bridge_is_local (struct net_device * dev , struct net_device * rep ,
113
+ struct mlx5_eswitch * esw )
114
+ {
115
+ struct mlx5_core_dev * mdev ;
116
+ struct mlx5e_priv * priv ;
117
+
118
+ if (!mlx5_esw_bridge_dev_same_esw (rep , esw ))
119
+ return false;
120
+
121
+ priv = netdev_priv (rep );
122
+ mdev = priv -> mdev ;
123
+ if (netif_is_lag_master (dev ))
124
+ return mlx5_lag_is_shared_fdb (mdev ) && mlx5_lag_is_master (mdev );
125
+ return true;
84
126
}
85
127
86
128
static int mlx5_esw_bridge_port_changeupper (struct notifier_block * nb , void * ptr )
@@ -90,8 +132,8 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
90
132
netdev_nb );
91
133
struct net_device * dev = netdev_notifier_info_to_dev (ptr );
92
134
struct netdev_notifier_changeupper_info * info = ptr ;
135
+ struct net_device * upper = info -> upper_dev , * rep ;
93
136
struct mlx5_eswitch * esw = br_offloads -> esw ;
94
- struct net_device * upper = info -> upper_dev ;
95
137
u16 vport_num , esw_owner_vhca_id ;
96
138
struct netlink_ext_ack * extack ;
97
139
int ifindex = upper -> ifindex ;
@@ -100,20 +142,19 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
100
142
if (!netif_is_bridge_master (upper ))
101
143
return 0 ;
102
144
103
- err = mlx5_esw_bridge_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
104
- & esw_owner_vhca_id );
105
- if (err )
145
+ rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , esw , & vport_num , & esw_owner_vhca_id );
146
+ if (!rep )
106
147
return 0 ;
107
148
108
149
extack = netdev_notifier_info_to_extack (& info -> info );
109
150
110
- if (mlx5_esw_bridge_dev_same_esw (dev , esw ))
151
+ if (mlx5_esw_bridge_is_local (dev , rep , esw ))
111
152
err = info -> linking ?
112
153
mlx5_esw_bridge_vport_link (ifindex , vport_num , esw_owner_vhca_id ,
113
154
br_offloads , extack ) :
114
155
mlx5_esw_bridge_vport_unlink (ifindex , vport_num , esw_owner_vhca_id ,
115
156
br_offloads , extack );
116
- else if (mlx5_esw_bridge_dev_same_hw (dev , esw ))
157
+ else if (mlx5_esw_bridge_dev_same_hw (rep , esw ))
117
158
err = info -> linking ?
118
159
mlx5_esw_bridge_vport_peer_link (ifindex , vport_num , esw_owner_vhca_id ,
119
160
br_offloads , extack ) :
@@ -151,9 +192,8 @@ mlx5_esw_bridge_port_obj_add(struct net_device *dev,
151
192
u16 vport_num , esw_owner_vhca_id ;
152
193
int err ;
153
194
154
- err = mlx5_esw_bridge_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
155
- & esw_owner_vhca_id );
156
- if (err )
195
+ if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
196
+ & esw_owner_vhca_id ))
157
197
return 0 ;
158
198
159
199
port_obj_info -> handled = true;
@@ -178,11 +218,9 @@ mlx5_esw_bridge_port_obj_del(struct net_device *dev,
178
218
const struct switchdev_obj * obj = port_obj_info -> obj ;
179
219
const struct switchdev_obj_port_vlan * vlan ;
180
220
u16 vport_num , esw_owner_vhca_id ;
181
- int err ;
182
221
183
- err = mlx5_esw_bridge_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
184
- & esw_owner_vhca_id );
185
- if (err )
222
+ if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
223
+ & esw_owner_vhca_id ))
186
224
return 0 ;
187
225
188
226
port_obj_info -> handled = true;
@@ -208,9 +246,8 @@ mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
208
246
u16 vport_num , esw_owner_vhca_id ;
209
247
int err ;
210
248
211
- err = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
212
- & esw_owner_vhca_id );
213
- if (err )
249
+ if (!mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
250
+ & esw_owner_vhca_id ))
214
251
return 0 ;
215
252
216
253
port_attr_info -> handled = true;
@@ -283,13 +320,11 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
283
320
fdb_work -> br_offloads ;
284
321
struct net_device * dev = fdb_work -> dev ;
285
322
u16 vport_num , esw_owner_vhca_id ;
286
- int err ;
287
323
288
324
rtnl_lock ();
289
325
290
- err = mlx5_esw_bridge_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
291
- & esw_owner_vhca_id );
292
- if (err )
326
+ if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , br_offloads -> esw , & vport_num ,
327
+ & esw_owner_vhca_id ))
293
328
goto out ;
294
329
295
330
if (fdb_work -> add )
@@ -343,8 +378,10 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
343
378
struct net_device * dev = switchdev_notifier_info_to_dev (ptr );
344
379
struct switchdev_notifier_fdb_info * fdb_info ;
345
380
struct mlx5_bridge_switchdev_fdb_work * work ;
381
+ struct mlx5_eswitch * esw = br_offloads -> esw ;
346
382
struct switchdev_notifier_info * info = ptr ;
347
- struct net_device * upper ;
383
+ u16 vport_num , esw_owner_vhca_id ;
384
+ struct net_device * upper , * rep ;
348
385
349
386
if (event == SWITCHDEV_PORT_ATTR_SET ) {
350
387
int err = mlx5_esw_bridge_port_obj_attr_set (dev , ptr , br_offloads );
@@ -358,13 +395,25 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
358
395
if (!netif_is_bridge_master (upper ))
359
396
return NOTIFY_DONE ;
360
397
361
- if (!mlx5e_eswitch_rep (dev ))
398
+ rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get (dev , esw , & vport_num , & esw_owner_vhca_id );
399
+ if (!rep )
362
400
return NOTIFY_DONE ;
363
401
364
402
switch (event ) {
403
+ case SWITCHDEV_FDB_ADD_TO_BRIDGE :
404
+ /* only handle the event on native eswtich of representor */
405
+ if (!mlx5_esw_bridge_is_local (dev , rep , esw ))
406
+ break ;
407
+
408
+ fdb_info = container_of (info ,
409
+ struct switchdev_notifier_fdb_info ,
410
+ info );
411
+ mlx5_esw_bridge_fdb_update_used (dev , vport_num , esw_owner_vhca_id , br_offloads ,
412
+ fdb_info );
413
+ break ;
365
414
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 ))
415
+ /* only handle the event on peers */
416
+ if (mlx5_esw_bridge_is_local (dev , rep , esw ))
368
417
break ;
369
418
fallthrough ;
370
419
case SWITCHDEV_FDB_ADD_TO_DEVICE :
0 commit comments