forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f9004dbfff8a3fbbd7e2a88c8a4327c7f2f8e5b2
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
....@@ -15,9 +15,9 @@
1515 #include <linux/rtnetlink.h>
1616 #include <linux/netlink.h>
1717 #include <net/switchdev.h>
18
+#include <net/vxlan.h>
1819
1920 #include "spectrum_span.h"
20
-#include "spectrum_router.h"
2121 #include "spectrum_switchdev.h"
2222 #include "spectrum.h"
2323 #include "core.h"
....@@ -84,9 +84,17 @@
8484 void (*port_leave)(struct mlxsw_sp_bridge_device *bridge_device,
8585 struct mlxsw_sp_bridge_port *bridge_port,
8686 struct mlxsw_sp_port *mlxsw_sp_port);
87
+ int (*vxlan_join)(struct mlxsw_sp_bridge_device *bridge_device,
88
+ const struct net_device *vxlan_dev, u16 vid,
89
+ struct netlink_ext_ack *extack);
8790 struct mlxsw_sp_fid *
8891 (*fid_get)(struct mlxsw_sp_bridge_device *bridge_device,
89
- u16 vid);
92
+ u16 vid, struct netlink_ext_ack *extack);
93
+ struct mlxsw_sp_fid *
94
+ (*fid_lookup)(struct mlxsw_sp_bridge_device *bridge_device,
95
+ u16 vid);
96
+ u16 (*fid_vid)(struct mlxsw_sp_bridge_device *bridge_device,
97
+ const struct mlxsw_sp_fid *fid);
9098 };
9199
92100 static int
....@@ -128,9 +136,9 @@
128136 }
129137
130138 static int mlxsw_sp_bridge_device_upper_rif_destroy(struct net_device *dev,
131
- void *data)
139
+ struct netdev_nested_priv *priv)
132140 {
133
- struct mlxsw_sp *mlxsw_sp = data;
141
+ struct mlxsw_sp *mlxsw_sp = priv->data;
134142
135143 mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev);
136144 return 0;
....@@ -139,22 +147,74 @@
139147 static void mlxsw_sp_bridge_device_rifs_destroy(struct mlxsw_sp *mlxsw_sp,
140148 struct net_device *dev)
141149 {
150
+ struct netdev_nested_priv priv = {
151
+ .data = (void *)mlxsw_sp,
152
+ };
153
+
142154 mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev);
143155 netdev_walk_all_upper_dev_rcu(dev,
144156 mlxsw_sp_bridge_device_upper_rif_destroy,
145
- mlxsw_sp);
157
+ &priv);
158
+}
159
+
160
+static int mlxsw_sp_bridge_device_vxlan_init(struct mlxsw_sp_bridge *bridge,
161
+ struct net_device *br_dev,
162
+ struct netlink_ext_ack *extack)
163
+{
164
+ struct net_device *dev, *stop_dev;
165
+ struct list_head *iter;
166
+ int err;
167
+
168
+ netdev_for_each_lower_dev(br_dev, dev, iter) {
169
+ if (netif_is_vxlan(dev) && netif_running(dev)) {
170
+ err = mlxsw_sp_bridge_vxlan_join(bridge->mlxsw_sp,
171
+ br_dev, dev, 0,
172
+ extack);
173
+ if (err) {
174
+ stop_dev = dev;
175
+ goto err_vxlan_join;
176
+ }
177
+ }
178
+ }
179
+
180
+ return 0;
181
+
182
+err_vxlan_join:
183
+ netdev_for_each_lower_dev(br_dev, dev, iter) {
184
+ if (netif_is_vxlan(dev) && netif_running(dev)) {
185
+ if (stop_dev == dev)
186
+ break;
187
+ mlxsw_sp_bridge_vxlan_leave(bridge->mlxsw_sp, dev);
188
+ }
189
+ }
190
+ return err;
191
+}
192
+
193
+static void mlxsw_sp_bridge_device_vxlan_fini(struct mlxsw_sp_bridge *bridge,
194
+ struct net_device *br_dev)
195
+{
196
+ struct net_device *dev;
197
+ struct list_head *iter;
198
+
199
+ netdev_for_each_lower_dev(br_dev, dev, iter) {
200
+ if (netif_is_vxlan(dev) && netif_running(dev))
201
+ mlxsw_sp_bridge_vxlan_leave(bridge->mlxsw_sp, dev);
202
+ }
146203 }
147204
148205 static struct mlxsw_sp_bridge_device *
149206 mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
150
- struct net_device *br_dev)
207
+ struct net_device *br_dev,
208
+ struct netlink_ext_ack *extack)
151209 {
152210 struct device *dev = bridge->mlxsw_sp->bus_info->dev;
153211 struct mlxsw_sp_bridge_device *bridge_device;
154212 bool vlan_enabled = br_vlan_enabled(br_dev);
213
+ int err;
155214
156215 if (vlan_enabled && bridge->vlan_enabled_exists) {
157216 dev_err(dev, "Only one VLAN-aware bridge is supported\n");
217
+ NL_SET_ERR_MSG_MOD(extack, "Only one VLAN-aware bridge is supported");
158218 return ERR_PTR(-EINVAL);
159219 }
160220
....@@ -176,13 +236,29 @@
176236 INIT_LIST_HEAD(&bridge_device->mids_list);
177237 list_add(&bridge_device->list, &bridge->bridges_list);
178238
239
+ /* It is possible we already have VXLAN devices enslaved to the bridge.
240
+ * In which case, we need to replay their configuration as if they were
241
+ * just now enslaved to the bridge.
242
+ */
243
+ err = mlxsw_sp_bridge_device_vxlan_init(bridge, br_dev, extack);
244
+ if (err)
245
+ goto err_vxlan_init;
246
+
179247 return bridge_device;
248
+
249
+err_vxlan_init:
250
+ list_del(&bridge_device->list);
251
+ if (bridge_device->vlan_enabled)
252
+ bridge->vlan_enabled_exists = false;
253
+ kfree(bridge_device);
254
+ return ERR_PTR(err);
180255 }
181256
182257 static void
183258 mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
184259 struct mlxsw_sp_bridge_device *bridge_device)
185260 {
261
+ mlxsw_sp_bridge_device_vxlan_fini(bridge, bridge_device->dev);
186262 mlxsw_sp_bridge_device_rifs_destroy(bridge->mlxsw_sp,
187263 bridge_device->dev);
188264 list_del(&bridge_device->list);
....@@ -195,7 +271,8 @@
195271
196272 static struct mlxsw_sp_bridge_device *
197273 mlxsw_sp_bridge_device_get(struct mlxsw_sp_bridge *bridge,
198
- struct net_device *br_dev)
274
+ struct net_device *br_dev,
275
+ struct netlink_ext_ack *extack)
199276 {
200277 struct mlxsw_sp_bridge_device *bridge_device;
201278
....@@ -203,7 +280,7 @@
203280 if (bridge_device)
204281 return bridge_device;
205282
206
- return mlxsw_sp_bridge_device_create(bridge, br_dev);
283
+ return mlxsw_sp_bridge_device_create(bridge, br_dev, extack);
207284 }
208285
209286 static void
....@@ -284,7 +361,8 @@
284361
285362 static struct mlxsw_sp_bridge_port *
286363 mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge,
287
- struct net_device *brport_dev)
364
+ struct net_device *brport_dev,
365
+ struct netlink_ext_ack *extack)
288366 {
289367 struct net_device *br_dev = netdev_master_upper_dev_get(brport_dev);
290368 struct mlxsw_sp_bridge_device *bridge_device;
....@@ -297,7 +375,7 @@
297375 return bridge_port;
298376 }
299377
300
- bridge_device = mlxsw_sp_bridge_device_get(bridge, br_dev);
378
+ bridge_device = mlxsw_sp_bridge_device_get(bridge, br_dev, extack);
301379 if (IS_ERR(bridge_device))
302380 return ERR_CAST(bridge_device);
303381
....@@ -421,46 +499,6 @@
421499 {
422500 if (list_empty(&bridge_vlan->port_vlan_list))
423501 mlxsw_sp_bridge_vlan_destroy(bridge_vlan);
424
-}
425
-
426
-static void mlxsw_sp_port_bridge_flags_get(struct mlxsw_sp_bridge *bridge,
427
- struct net_device *dev,
428
- unsigned long *brport_flags)
429
-{
430
- struct mlxsw_sp_bridge_port *bridge_port;
431
-
432
- bridge_port = mlxsw_sp_bridge_port_find(bridge, dev);
433
- if (WARN_ON(!bridge_port))
434
- return;
435
-
436
- memcpy(brport_flags, &bridge_port->flags, sizeof(*brport_flags));
437
-}
438
-
439
-static int mlxsw_sp_port_attr_get(struct net_device *dev,
440
- struct switchdev_attr *attr)
441
-{
442
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
443
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
444
-
445
- switch (attr->id) {
446
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
447
- attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac);
448
- memcpy(&attr->u.ppid.id, &mlxsw_sp->base_mac,
449
- attr->u.ppid.id_len);
450
- break;
451
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
452
- mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev,
453
- &attr->u.brport_flags);
454
- break;
455
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
456
- attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD |
457
- BR_MCAST_FLOOD;
458
- break;
459
- default:
460
- return -EOPNOTSUPP;
461
- }
462
-
463
- return 0;
464502 }
465503
466504 static int
....@@ -610,6 +648,17 @@
610648 mlxsw_sp_port_bridge_vlan_learning_set(mlxsw_sp_port,
611649 bridge_vlan, !set);
612650 return err;
651
+}
652
+
653
+static int mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port
654
+ *mlxsw_sp_port,
655
+ struct switchdev_trans *trans,
656
+ unsigned long brport_flags)
657
+{
658
+ if (brport_flags & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD))
659
+ return -EINVAL;
660
+
661
+ return 0;
613662 }
614663
615664 static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
....@@ -858,6 +907,11 @@
858907 attr->orig_dev,
859908 attr->u.stp_state);
860909 break;
910
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
911
+ err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port,
912
+ trans,
913
+ attr->u.brport_flags);
914
+ break;
861915 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
862916 err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans,
863917 attr->orig_dev,
....@@ -900,7 +954,8 @@
900954
901955 static int
902956 mlxsw_sp_port_vlan_fid_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
903
- struct mlxsw_sp_bridge_port *bridge_port)
957
+ struct mlxsw_sp_bridge_port *bridge_port,
958
+ struct netlink_ext_ack *extack)
904959 {
905960 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
906961 struct mlxsw_sp_bridge_device *bridge_device;
....@@ -910,7 +965,7 @@
910965 int err;
911966
912967 bridge_device = bridge_port->bridge_device;
913
- fid = bridge_device->ops->fid_get(bridge_device, vid);
968
+ fid = bridge_device->ops->fid_get(bridge_device, vid, extack);
914969 if (IS_ERR(fid))
915970 return PTR_ERR(fid);
916971
....@@ -978,7 +1033,8 @@
9781033
9791034 static int
9801035 mlxsw_sp_port_vlan_bridge_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
981
- struct mlxsw_sp_bridge_port *bridge_port)
1036
+ struct mlxsw_sp_bridge_port *bridge_port,
1037
+ struct netlink_ext_ack *extack)
9821038 {
9831039 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
9841040 struct mlxsw_sp_bridge_vlan *bridge_vlan;
....@@ -986,12 +1042,11 @@
9861042 int err;
9871043
9881044 /* No need to continue if only VLAN flags were changed */
989
- if (mlxsw_sp_port_vlan->bridge_port) {
990
- mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1045
+ if (mlxsw_sp_port_vlan->bridge_port)
9911046 return 0;
992
- }
9931047
994
- err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port);
1048
+ err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port,
1049
+ extack);
9951050 if (err)
9961051 return err;
9971052
....@@ -1015,7 +1070,7 @@
10151070 &bridge_vlan->port_vlan_list);
10161071
10171072 mlxsw_sp_bridge_port_get(mlxsw_sp_port->mlxsw_sp->bridge,
1018
- bridge_port->dev);
1073
+ bridge_port->dev, extack);
10191074 mlxsw_sp_port_vlan->bridge_port = bridge_port;
10201075
10211076 return 0;
....@@ -1068,16 +1123,29 @@
10681123 static int
10691124 mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
10701125 struct mlxsw_sp_bridge_port *bridge_port,
1071
- u16 vid, bool is_untagged, bool is_pvid)
1126
+ u16 vid, bool is_untagged, bool is_pvid,
1127
+ struct netlink_ext_ack *extack)
10721128 {
10731129 u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
10741130 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
10751131 u16 old_pvid = mlxsw_sp_port->pvid;
10761132 int err;
10771133
1078
- mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_get(mlxsw_sp_port, vid);
1079
- if (IS_ERR(mlxsw_sp_port_vlan))
1080
- return PTR_ERR(mlxsw_sp_port_vlan);
1134
+ /* The only valid scenario in which a port-vlan already exists, is if
1135
+ * the VLAN flags were changed and the port-vlan is associated with the
1136
+ * correct bridge port
1137
+ */
1138
+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1139
+ if (mlxsw_sp_port_vlan &&
1140
+ mlxsw_sp_port_vlan->bridge_port != bridge_port)
1141
+ return -EEXIST;
1142
+
1143
+ if (!mlxsw_sp_port_vlan) {
1144
+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
1145
+ vid);
1146
+ if (IS_ERR(mlxsw_sp_port_vlan))
1147
+ return PTR_ERR(mlxsw_sp_port_vlan);
1148
+ }
10811149
10821150 err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true,
10831151 is_untagged);
....@@ -1088,7 +1156,8 @@
10881156 if (err)
10891157 goto err_port_pvid_set;
10901158
1091
- err = mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port);
1159
+ err = mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port,
1160
+ extack);
10921161 if (err)
10931162 goto err_port_vlan_bridge_join;
10941163
....@@ -1099,7 +1168,7 @@
10991168 err_port_pvid_set:
11001169 mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
11011170 err_port_vlan_set:
1102
- mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1171
+ mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
11031172 return err;
11041173 }
11051174
....@@ -1108,16 +1177,12 @@
11081177 const struct net_device *br_dev,
11091178 const struct switchdev_obj_port_vlan *vlan)
11101179 {
1111
- struct mlxsw_sp_rif *rif;
1112
- struct mlxsw_sp_fid *fid;
11131180 u16 pvid;
11141181 u16 vid;
11151182
1116
- rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev);
1117
- if (!rif)
1183
+ pvid = mlxsw_sp_rif_vid(mlxsw_sp, br_dev);
1184
+ if (!pvid)
11181185 return 0;
1119
- fid = mlxsw_sp_rif_fid(rif);
1120
- pvid = mlxsw_sp_fid_8021q_vid(fid);
11211186
11221187 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
11231188 if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
....@@ -1138,7 +1203,8 @@
11381203
11391204 static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
11401205 const struct switchdev_obj_port_vlan *vlan,
1141
- struct switchdev_trans *trans)
1206
+ struct switchdev_trans *trans,
1207
+ struct netlink_ext_ack *extack)
11421208 {
11431209 bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
11441210 bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
....@@ -1160,7 +1226,7 @@
11601226 return err;
11611227 }
11621228
1163
- if (switchdev_trans_ph_prepare(trans))
1229
+ if (switchdev_trans_ph_commit(trans))
11641230 return 0;
11651231
11661232 bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
....@@ -1175,7 +1241,7 @@
11751241
11761242 err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
11771243 vid, flag_untagged,
1178
- flag_pvid);
1244
+ flag_pvid, extack);
11791245 if (err)
11801246 return err;
11811247 }
....@@ -1216,6 +1282,51 @@
12161282 {
12171283 return adding ? MLXSW_REG_SFD_OP_WRITE_EDIT :
12181284 MLXSW_REG_SFD_OP_WRITE_REMOVE;
1285
+}
1286
+
1287
+static int mlxsw_sp_port_fdb_tunnel_uc_op(struct mlxsw_sp *mlxsw_sp,
1288
+ const char *mac, u16 fid,
1289
+ enum mlxsw_sp_l3proto proto,
1290
+ const union mlxsw_sp_l3addr *addr,
1291
+ bool adding, bool dynamic)
1292
+{
1293
+ enum mlxsw_reg_sfd_uc_tunnel_protocol sfd_proto;
1294
+ char *sfd_pl;
1295
+ u8 num_rec;
1296
+ u32 uip;
1297
+ int err;
1298
+
1299
+ switch (proto) {
1300
+ case MLXSW_SP_L3_PROTO_IPV4:
1301
+ uip = be32_to_cpu(addr->addr4);
1302
+ sfd_proto = MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV4;
1303
+ break;
1304
+ case MLXSW_SP_L3_PROTO_IPV6:
1305
+ default:
1306
+ WARN_ON(1);
1307
+ return -EOPNOTSUPP;
1308
+ }
1309
+
1310
+ sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
1311
+ if (!sfd_pl)
1312
+ return -ENOMEM;
1313
+
1314
+ mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
1315
+ mlxsw_reg_sfd_uc_tunnel_pack(sfd_pl, 0,
1316
+ mlxsw_sp_sfd_rec_policy(dynamic), mac, fid,
1317
+ MLXSW_REG_SFD_REC_ACTION_NOP, uip,
1318
+ sfd_proto);
1319
+ num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
1320
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
1321
+ if (err)
1322
+ goto out;
1323
+
1324
+ if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
1325
+ err = -EBUSY;
1326
+
1327
+out:
1328
+ kfree(sfd_pl);
1329
+ return err;
12191330 }
12201331
12211332 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
....@@ -1667,39 +1778,10 @@
16671778 }
16681779 }
16691780
1670
-struct mlxsw_sp_span_respin_work {
1671
- struct work_struct work;
1672
- struct mlxsw_sp *mlxsw_sp;
1673
-};
1674
-
1675
-static void mlxsw_sp_span_respin_work(struct work_struct *work)
1676
-{
1677
- struct mlxsw_sp_span_respin_work *respin_work =
1678
- container_of(work, struct mlxsw_sp_span_respin_work, work);
1679
-
1680
- rtnl_lock();
1681
- mlxsw_sp_span_respin(respin_work->mlxsw_sp);
1682
- rtnl_unlock();
1683
- kfree(respin_work);
1684
-}
1685
-
1686
-static void mlxsw_sp_span_respin_schedule(struct mlxsw_sp *mlxsw_sp)
1687
-{
1688
- struct mlxsw_sp_span_respin_work *respin_work;
1689
-
1690
- respin_work = kzalloc(sizeof(*respin_work), GFP_ATOMIC);
1691
- if (!respin_work)
1692
- return;
1693
-
1694
- INIT_WORK(&respin_work->work, mlxsw_sp_span_respin_work);
1695
- respin_work->mlxsw_sp = mlxsw_sp;
1696
-
1697
- mlxsw_core_schedule_work(&respin_work->work);
1698
-}
1699
-
17001781 static int mlxsw_sp_port_obj_add(struct net_device *dev,
17011782 const struct switchdev_obj *obj,
1702
- struct switchdev_trans *trans)
1783
+ struct switchdev_trans *trans,
1784
+ struct netlink_ext_ack *extack)
17031785 {
17041786 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
17051787 const struct switchdev_obj_port_vlan *vlan;
....@@ -1708,7 +1790,8 @@
17081790 switch (obj->id) {
17091791 case SWITCHDEV_OBJ_ID_PORT_VLAN:
17101792 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
1711
- err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
1793
+ err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans,
1794
+ extack);
17121795
17131796 if (switchdev_trans_ph_prepare(trans)) {
17141797 /* The event is emitted before the changes are actually
....@@ -1716,7 +1799,7 @@
17161799 * call for later, so that the respin logic sees the
17171800 * updated bridge state.
17181801 */
1719
- mlxsw_sp_span_respin_schedule(mlxsw_sp_port->mlxsw_sp);
1802
+ mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);
17201803 }
17211804 break;
17221805 case SWITCHDEV_OBJ_ID_PORT_MDB:
....@@ -1746,7 +1829,7 @@
17461829 mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
17471830 mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid);
17481831 mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
1749
- mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1832
+ mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
17501833 }
17511834
17521835 static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
....@@ -1869,7 +1952,7 @@
18691952 break;
18701953 }
18711954
1872
- mlxsw_sp_span_respin_schedule(mlxsw_sp_port->mlxsw_sp);
1955
+ mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);
18731956
18741957 return err;
18751958 }
....@@ -1891,32 +1974,20 @@
18911974 return NULL;
18921975 }
18931976
1894
-static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
1895
- .switchdev_port_attr_get = mlxsw_sp_port_attr_get,
1896
- .switchdev_port_attr_set = mlxsw_sp_port_attr_set,
1897
- .switchdev_port_obj_add = mlxsw_sp_port_obj_add,
1898
- .switchdev_port_obj_del = mlxsw_sp_port_obj_del,
1899
-};
1900
-
19011977 static int
19021978 mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device,
19031979 struct mlxsw_sp_bridge_port *bridge_port,
19041980 struct mlxsw_sp_port *mlxsw_sp_port,
19051981 struct netlink_ext_ack *extack)
19061982 {
1907
- struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1908
-
19091983 if (is_vlan_dev(bridge_port->dev)) {
19101984 NL_SET_ERR_MSG_MOD(extack, "Can not enslave a VLAN device to a VLAN-aware bridge");
19111985 return -EINVAL;
19121986 }
19131987
1914
- mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, 1);
1915
- if (WARN_ON(!mlxsw_sp_port_vlan))
1916
- return -EINVAL;
1917
-
1918
- /* Let VLAN-aware bridge take care of its own VLANs */
1919
- mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1988
+ /* Port is no longer usable as a router interface */
1989
+ if (mlxsw_sp_port->default_vlan->fid)
1990
+ mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
19201991
19211992 return 0;
19221993 }
....@@ -1926,24 +1997,114 @@
19261997 struct mlxsw_sp_bridge_port *bridge_port,
19271998 struct mlxsw_sp_port *mlxsw_sp_port)
19281999 {
1929
- mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
19302000 /* Make sure untagged frames are allowed to ingress */
1931
- mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
2001
+ mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID);
2002
+}
2003
+
2004
+static int
2005
+mlxsw_sp_bridge_8021q_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device,
2006
+ const struct net_device *vxlan_dev, u16 vid,
2007
+ struct netlink_ext_ack *extack)
2008
+{
2009
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
2010
+ struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
2011
+ struct mlxsw_sp_nve_params params = {
2012
+ .type = MLXSW_SP_NVE_TYPE_VXLAN,
2013
+ .vni = vxlan->cfg.vni,
2014
+ .dev = vxlan_dev,
2015
+ };
2016
+ struct mlxsw_sp_fid *fid;
2017
+ int err;
2018
+
2019
+ /* If the VLAN is 0, we need to find the VLAN that is configured as
2020
+ * PVID and egress untagged on the bridge port of the VxLAN device.
2021
+ * It is possible no such VLAN exists
2022
+ */
2023
+ if (!vid) {
2024
+ err = mlxsw_sp_vxlan_mapped_vid(vxlan_dev, &vid);
2025
+ if (err || !vid)
2026
+ return err;
2027
+ }
2028
+
2029
+ fid = mlxsw_sp_fid_8021q_get(mlxsw_sp, vid);
2030
+ if (IS_ERR(fid)) {
2031
+ NL_SET_ERR_MSG_MOD(extack, "Failed to create 802.1Q FID");
2032
+ return PTR_ERR(fid);
2033
+ }
2034
+
2035
+ if (mlxsw_sp_fid_vni_is_set(fid)) {
2036
+ NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID");
2037
+ err = -EINVAL;
2038
+ goto err_vni_exists;
2039
+ }
2040
+
2041
+ err = mlxsw_sp_nve_fid_enable(mlxsw_sp, fid, &params, extack);
2042
+ if (err)
2043
+ goto err_nve_fid_enable;
2044
+
2045
+ return 0;
2046
+
2047
+err_nve_fid_enable:
2048
+err_vni_exists:
2049
+ mlxsw_sp_fid_put(fid);
2050
+ return err;
2051
+}
2052
+
2053
+static struct net_device *
2054
+mlxsw_sp_bridge_8021q_vxlan_dev_find(struct net_device *br_dev, u16 vid)
2055
+{
2056
+ struct net_device *dev;
2057
+ struct list_head *iter;
2058
+
2059
+ netdev_for_each_lower_dev(br_dev, dev, iter) {
2060
+ u16 pvid;
2061
+ int err;
2062
+
2063
+ if (!netif_is_vxlan(dev))
2064
+ continue;
2065
+
2066
+ err = mlxsw_sp_vxlan_mapped_vid(dev, &pvid);
2067
+ if (err || pvid != vid)
2068
+ continue;
2069
+
2070
+ return dev;
2071
+ }
2072
+
2073
+ return NULL;
19322074 }
19332075
19342076 static struct mlxsw_sp_fid *
19352077 mlxsw_sp_bridge_8021q_fid_get(struct mlxsw_sp_bridge_device *bridge_device,
1936
- u16 vid)
2078
+ u16 vid, struct netlink_ext_ack *extack)
19372079 {
19382080 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
19392081
19402082 return mlxsw_sp_fid_8021q_get(mlxsw_sp, vid);
19412083 }
19422084
2085
+static struct mlxsw_sp_fid *
2086
+mlxsw_sp_bridge_8021q_fid_lookup(struct mlxsw_sp_bridge_device *bridge_device,
2087
+ u16 vid)
2088
+{
2089
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
2090
+
2091
+ return mlxsw_sp_fid_8021q_lookup(mlxsw_sp, vid);
2092
+}
2093
+
2094
+static u16
2095
+mlxsw_sp_bridge_8021q_fid_vid(struct mlxsw_sp_bridge_device *bridge_device,
2096
+ const struct mlxsw_sp_fid *fid)
2097
+{
2098
+ return mlxsw_sp_fid_8021q_vid(fid);
2099
+}
2100
+
19432101 static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021q_ops = {
19442102 .port_join = mlxsw_sp_bridge_8021q_port_join,
19452103 .port_leave = mlxsw_sp_bridge_8021q_port_leave,
2104
+ .vxlan_join = mlxsw_sp_bridge_8021q_vxlan_join,
19462105 .fid_get = mlxsw_sp_bridge_8021q_fid_get,
2106
+ .fid_lookup = mlxsw_sp_bridge_8021q_fid_lookup,
2107
+ .fid_vid = mlxsw_sp_bridge_8021q_fid_vid,
19472108 };
19482109
19492110 static bool
....@@ -1973,7 +2134,7 @@
19732134 struct net_device *dev = bridge_port->dev;
19742135 u16 vid;
19752136
1976
- vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 1;
2137
+ vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : MLXSW_SP_DEFAULT_VID;
19772138 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
19782139 if (WARN_ON(!mlxsw_sp_port_vlan))
19792140 return -EINVAL;
....@@ -1987,7 +2148,8 @@
19872148 if (mlxsw_sp_port_vlan->fid)
19882149 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
19892150
1990
- return mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port);
2151
+ return mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port,
2152
+ extack);
19912153 }
19922154
19932155 static void
....@@ -1999,27 +2161,89 @@
19992161 struct net_device *dev = bridge_port->dev;
20002162 u16 vid;
20012163
2002
- vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 1;
2164
+ vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : MLXSW_SP_DEFAULT_VID;
20032165 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
2004
- if (!mlxsw_sp_port_vlan)
2166
+ if (!mlxsw_sp_port_vlan || !mlxsw_sp_port_vlan->bridge_port)
20052167 return;
20062168
20072169 mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
20082170 }
20092171
2172
+static int
2173
+mlxsw_sp_bridge_8021d_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device,
2174
+ const struct net_device *vxlan_dev, u16 vid,
2175
+ struct netlink_ext_ack *extack)
2176
+{
2177
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
2178
+ struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
2179
+ struct mlxsw_sp_nve_params params = {
2180
+ .type = MLXSW_SP_NVE_TYPE_VXLAN,
2181
+ .vni = vxlan->cfg.vni,
2182
+ .dev = vxlan_dev,
2183
+ };
2184
+ struct mlxsw_sp_fid *fid;
2185
+ int err;
2186
+
2187
+ fid = mlxsw_sp_fid_8021d_get(mlxsw_sp, bridge_device->dev->ifindex);
2188
+ if (IS_ERR(fid)) {
2189
+ NL_SET_ERR_MSG_MOD(extack, "Failed to create 802.1D FID");
2190
+ return -EINVAL;
2191
+ }
2192
+
2193
+ if (mlxsw_sp_fid_vni_is_set(fid)) {
2194
+ NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID");
2195
+ err = -EINVAL;
2196
+ goto err_vni_exists;
2197
+ }
2198
+
2199
+ err = mlxsw_sp_nve_fid_enable(mlxsw_sp, fid, &params, extack);
2200
+ if (err)
2201
+ goto err_nve_fid_enable;
2202
+
2203
+ return 0;
2204
+
2205
+err_nve_fid_enable:
2206
+err_vni_exists:
2207
+ mlxsw_sp_fid_put(fid);
2208
+ return err;
2209
+}
2210
+
20102211 static struct mlxsw_sp_fid *
20112212 mlxsw_sp_bridge_8021d_fid_get(struct mlxsw_sp_bridge_device *bridge_device,
2012
- u16 vid)
2213
+ u16 vid, struct netlink_ext_ack *extack)
20132214 {
20142215 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
20152216
20162217 return mlxsw_sp_fid_8021d_get(mlxsw_sp, bridge_device->dev->ifindex);
20172218 }
20182219
2220
+static struct mlxsw_sp_fid *
2221
+mlxsw_sp_bridge_8021d_fid_lookup(struct mlxsw_sp_bridge_device *bridge_device,
2222
+ u16 vid)
2223
+{
2224
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_device->dev);
2225
+
2226
+ /* The only valid VLAN for a VLAN-unaware bridge is 0 */
2227
+ if (vid)
2228
+ return NULL;
2229
+
2230
+ return mlxsw_sp_fid_8021d_lookup(mlxsw_sp, bridge_device->dev->ifindex);
2231
+}
2232
+
2233
+static u16
2234
+mlxsw_sp_bridge_8021d_fid_vid(struct mlxsw_sp_bridge_device *bridge_device,
2235
+ const struct mlxsw_sp_fid *fid)
2236
+{
2237
+ return 0;
2238
+}
2239
+
20192240 static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021d_ops = {
20202241 .port_join = mlxsw_sp_bridge_8021d_port_join,
20212242 .port_leave = mlxsw_sp_bridge_8021d_port_leave,
2243
+ .vxlan_join = mlxsw_sp_bridge_8021d_vxlan_join,
20222244 .fid_get = mlxsw_sp_bridge_8021d_fid_get,
2245
+ .fid_lookup = mlxsw_sp_bridge_8021d_fid_lookup,
2246
+ .fid_vid = mlxsw_sp_bridge_8021d_fid_vid,
20232247 };
20242248
20252249 int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
....@@ -2032,7 +2256,8 @@
20322256 struct mlxsw_sp_bridge_port *bridge_port;
20332257 int err;
20342258
2035
- bridge_port = mlxsw_sp_bridge_port_get(mlxsw_sp->bridge, brport_dev);
2259
+ bridge_port = mlxsw_sp_bridge_port_get(mlxsw_sp->bridge, brport_dev,
2260
+ extack);
20362261 if (IS_ERR(bridge_port))
20372262 return PTR_ERR(bridge_port);
20382263 bridge_device = bridge_port->bridge_device;
....@@ -2069,22 +2294,123 @@
20692294 mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
20702295 }
20712296
2297
+int mlxsw_sp_bridge_vxlan_join(struct mlxsw_sp *mlxsw_sp,
2298
+ const struct net_device *br_dev,
2299
+ const struct net_device *vxlan_dev, u16 vid,
2300
+ struct netlink_ext_ack *extack)
2301
+{
2302
+ struct mlxsw_sp_bridge_device *bridge_device;
2303
+
2304
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
2305
+ if (WARN_ON(!bridge_device))
2306
+ return -EINVAL;
2307
+
2308
+ return bridge_device->ops->vxlan_join(bridge_device, vxlan_dev, vid,
2309
+ extack);
2310
+}
2311
+
2312
+void mlxsw_sp_bridge_vxlan_leave(struct mlxsw_sp *mlxsw_sp,
2313
+ const struct net_device *vxlan_dev)
2314
+{
2315
+ struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
2316
+ struct mlxsw_sp_fid *fid;
2317
+
2318
+ /* If the VxLAN device is down, then the FID does not have a VNI */
2319
+ fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vxlan->cfg.vni);
2320
+ if (!fid)
2321
+ return;
2322
+
2323
+ mlxsw_sp_nve_fid_disable(mlxsw_sp, fid);
2324
+ /* Drop both the reference we just took during lookup and the reference
2325
+ * the VXLAN device took.
2326
+ */
2327
+ mlxsw_sp_fid_put(fid);
2328
+ mlxsw_sp_fid_put(fid);
2329
+}
2330
+
2331
+static void
2332
+mlxsw_sp_switchdev_vxlan_addr_convert(const union vxlan_addr *vxlan_addr,
2333
+ enum mlxsw_sp_l3proto *proto,
2334
+ union mlxsw_sp_l3addr *addr)
2335
+{
2336
+ if (vxlan_addr->sa.sa_family == AF_INET) {
2337
+ addr->addr4 = vxlan_addr->sin.sin_addr.s_addr;
2338
+ *proto = MLXSW_SP_L3_PROTO_IPV4;
2339
+ } else {
2340
+ addr->addr6 = vxlan_addr->sin6.sin6_addr;
2341
+ *proto = MLXSW_SP_L3_PROTO_IPV6;
2342
+ }
2343
+}
2344
+
2345
+static void
2346
+mlxsw_sp_switchdev_addr_vxlan_convert(enum mlxsw_sp_l3proto proto,
2347
+ const union mlxsw_sp_l3addr *addr,
2348
+ union vxlan_addr *vxlan_addr)
2349
+{
2350
+ switch (proto) {
2351
+ case MLXSW_SP_L3_PROTO_IPV4:
2352
+ vxlan_addr->sa.sa_family = AF_INET;
2353
+ vxlan_addr->sin.sin_addr.s_addr = addr->addr4;
2354
+ break;
2355
+ case MLXSW_SP_L3_PROTO_IPV6:
2356
+ vxlan_addr->sa.sa_family = AF_INET6;
2357
+ vxlan_addr->sin6.sin6_addr = addr->addr6;
2358
+ break;
2359
+ }
2360
+}
2361
+
2362
+static void mlxsw_sp_fdb_vxlan_call_notifiers(struct net_device *dev,
2363
+ const char *mac,
2364
+ enum mlxsw_sp_l3proto proto,
2365
+ union mlxsw_sp_l3addr *addr,
2366
+ __be32 vni, bool adding)
2367
+{
2368
+ struct switchdev_notifier_vxlan_fdb_info info;
2369
+ struct vxlan_dev *vxlan = netdev_priv(dev);
2370
+ enum switchdev_notifier_type type;
2371
+
2372
+ type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE :
2373
+ SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE;
2374
+ mlxsw_sp_switchdev_addr_vxlan_convert(proto, addr, &info.remote_ip);
2375
+ info.remote_port = vxlan->cfg.dst_port;
2376
+ info.remote_vni = vni;
2377
+ info.remote_ifindex = 0;
2378
+ ether_addr_copy(info.eth_addr, mac);
2379
+ info.vni = vni;
2380
+ info.offloaded = adding;
2381
+ call_switchdev_notifiers(type, dev, &info.info, NULL);
2382
+}
2383
+
2384
+static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev,
2385
+ const char *mac,
2386
+ enum mlxsw_sp_l3proto proto,
2387
+ union mlxsw_sp_l3addr *addr,
2388
+ __be32 vni,
2389
+ bool adding)
2390
+{
2391
+ if (netif_is_vxlan(dev))
2392
+ mlxsw_sp_fdb_vxlan_call_notifiers(dev, mac, proto, addr, vni,
2393
+ adding);
2394
+}
2395
+
20722396 static void
20732397 mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
20742398 const char *mac, u16 vid,
2075
- struct net_device *dev)
2399
+ struct net_device *dev, bool offloaded)
20762400 {
20772401 struct switchdev_notifier_fdb_info info;
20782402
20792403 info.addr = mac;
20802404 info.vid = vid;
2081
- call_switchdev_notifiers(type, dev, &info.info);
2405
+ info.offloaded = offloaded;
2406
+ call_switchdev_notifiers(type, dev, &info.info, NULL);
20822407 }
20832408
20842409 static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
20852410 char *sfn_pl, int rec_index,
20862411 bool adding)
20872412 {
2413
+ unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
20882414 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
20892415 struct mlxsw_sp_bridge_device *bridge_device;
20902416 struct mlxsw_sp_bridge_port *bridge_port;
....@@ -2097,11 +2423,17 @@
20972423 int err;
20982424
20992425 mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);
2426
+
2427
+ if (WARN_ON_ONCE(local_port >= max_ports))
2428
+ return;
21002429 mlxsw_sp_port = mlxsw_sp->ports[local_port];
21012430 if (!mlxsw_sp_port) {
21022431 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
21032432 goto just_remove;
21042433 }
2434
+
2435
+ if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid))
2436
+ goto just_remove;
21052437
21062438 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid);
21072439 if (!mlxsw_sp_port_vlan) {
....@@ -2129,7 +2461,7 @@
21292461 if (!do_notification)
21302462 return;
21312463 type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
2132
- mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
2464
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding);
21332465
21342466 return;
21352467
....@@ -2162,6 +2494,9 @@
21622494 goto just_remove;
21632495 }
21642496
2497
+ if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid))
2498
+ goto just_remove;
2499
+
21652500 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid);
21662501 if (!mlxsw_sp_port_vlan) {
21672502 netdev_err(mlxsw_sp_port->dev, "Failed to find a matching {Port, VID} following FDB notification\n");
....@@ -2176,7 +2511,8 @@
21762511
21772512 bridge_device = bridge_port->bridge_device;
21782513 vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
2179
- lag_vid = mlxsw_sp_port_vlan->vid;
2514
+ lag_vid = mlxsw_sp_fid_lag_vid_valid(mlxsw_sp_port_vlan->fid) ?
2515
+ mlxsw_sp_port_vlan->vid : 0;
21802516
21812517 do_fdb_op:
21822518 err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
....@@ -2189,7 +2525,7 @@
21892525 if (!do_notification)
21902526 return;
21912527 type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
2192
- mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
2528
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding);
21932529
21942530 return;
21952531
....@@ -2197,6 +2533,122 @@
21972533 adding = false;
21982534 do_notification = false;
21992535 goto do_fdb_op;
2536
+}
2537
+
2538
+static int
2539
+__mlxsw_sp_fdb_notify_mac_uc_tunnel_process(struct mlxsw_sp *mlxsw_sp,
2540
+ const struct mlxsw_sp_fid *fid,
2541
+ bool adding,
2542
+ struct net_device **nve_dev,
2543
+ u16 *p_vid, __be32 *p_vni)
2544
+{
2545
+ struct mlxsw_sp_bridge_device *bridge_device;
2546
+ struct net_device *br_dev, *dev;
2547
+ int nve_ifindex;
2548
+ int err;
2549
+
2550
+ err = mlxsw_sp_fid_nve_ifindex(fid, &nve_ifindex);
2551
+ if (err)
2552
+ return err;
2553
+
2554
+ err = mlxsw_sp_fid_vni(fid, p_vni);
2555
+ if (err)
2556
+ return err;
2557
+
2558
+ dev = __dev_get_by_index(mlxsw_sp_net(mlxsw_sp), nve_ifindex);
2559
+ if (!dev)
2560
+ return -EINVAL;
2561
+ *nve_dev = dev;
2562
+
2563
+ if (!netif_running(dev))
2564
+ return -EINVAL;
2565
+
2566
+ if (adding && !br_port_flag_is_set(dev, BR_LEARNING))
2567
+ return -EINVAL;
2568
+
2569
+ if (adding && netif_is_vxlan(dev)) {
2570
+ struct vxlan_dev *vxlan = netdev_priv(dev);
2571
+
2572
+ if (!(vxlan->cfg.flags & VXLAN_F_LEARN))
2573
+ return -EINVAL;
2574
+ }
2575
+
2576
+ br_dev = netdev_master_upper_dev_get(dev);
2577
+ if (!br_dev)
2578
+ return -EINVAL;
2579
+
2580
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
2581
+ if (!bridge_device)
2582
+ return -EINVAL;
2583
+
2584
+ *p_vid = bridge_device->ops->fid_vid(bridge_device, fid);
2585
+
2586
+ return 0;
2587
+}
2588
+
2589
+static void mlxsw_sp_fdb_notify_mac_uc_tunnel_process(struct mlxsw_sp *mlxsw_sp,
2590
+ char *sfn_pl,
2591
+ int rec_index,
2592
+ bool adding)
2593
+{
2594
+ enum mlxsw_reg_sfn_uc_tunnel_protocol sfn_proto;
2595
+ enum switchdev_notifier_type type;
2596
+ struct net_device *nve_dev;
2597
+ union mlxsw_sp_l3addr addr;
2598
+ struct mlxsw_sp_fid *fid;
2599
+ char mac[ETH_ALEN];
2600
+ u16 fid_index, vid;
2601
+ __be32 vni;
2602
+ u32 uip;
2603
+ int err;
2604
+
2605
+ mlxsw_reg_sfn_uc_tunnel_unpack(sfn_pl, rec_index, mac, &fid_index,
2606
+ &uip, &sfn_proto);
2607
+
2608
+ fid = mlxsw_sp_fid_lookup_by_index(mlxsw_sp, fid_index);
2609
+ if (!fid)
2610
+ goto err_fid_lookup;
2611
+
2612
+ err = mlxsw_sp_nve_learned_ip_resolve(mlxsw_sp, uip,
2613
+ (enum mlxsw_sp_l3proto) sfn_proto,
2614
+ &addr);
2615
+ if (err)
2616
+ goto err_ip_resolve;
2617
+
2618
+ err = __mlxsw_sp_fdb_notify_mac_uc_tunnel_process(mlxsw_sp, fid, adding,
2619
+ &nve_dev, &vid, &vni);
2620
+ if (err)
2621
+ goto err_fdb_process;
2622
+
2623
+ err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp, mac, fid_index,
2624
+ (enum mlxsw_sp_l3proto) sfn_proto,
2625
+ &addr, adding, true);
2626
+ if (err)
2627
+ goto err_fdb_op;
2628
+
2629
+ mlxsw_sp_fdb_nve_call_notifiers(nve_dev, mac,
2630
+ (enum mlxsw_sp_l3proto) sfn_proto,
2631
+ &addr, vni, adding);
2632
+
2633
+ type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE :
2634
+ SWITCHDEV_FDB_DEL_TO_BRIDGE;
2635
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, nve_dev, adding);
2636
+
2637
+ mlxsw_sp_fid_put(fid);
2638
+
2639
+ return;
2640
+
2641
+err_fdb_op:
2642
+err_fdb_process:
2643
+err_ip_resolve:
2644
+ mlxsw_sp_fid_put(fid);
2645
+err_fid_lookup:
2646
+ /* Remove an FDB entry in case we cannot process it. Otherwise the
2647
+ * device will keep sending the same notification over and over again.
2648
+ */
2649
+ mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp, mac, fid_index,
2650
+ (enum mlxsw_sp_l3proto) sfn_proto, &addr,
2651
+ false, true);
22002652 }
22012653
22022654 static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
....@@ -2219,22 +2671,35 @@
22192671 mlxsw_sp_fdb_notify_mac_lag_process(mlxsw_sp, sfn_pl,
22202672 rec_index, false);
22212673 break;
2674
+ case MLXSW_REG_SFN_REC_TYPE_LEARNED_UNICAST_TUNNEL:
2675
+ mlxsw_sp_fdb_notify_mac_uc_tunnel_process(mlxsw_sp, sfn_pl,
2676
+ rec_index, true);
2677
+ break;
2678
+ case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_UNICAST_TUNNEL:
2679
+ mlxsw_sp_fdb_notify_mac_uc_tunnel_process(mlxsw_sp, sfn_pl,
2680
+ rec_index, false);
2681
+ break;
22222682 }
22232683 }
22242684
2225
-static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
2685
+static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp,
2686
+ bool no_delay)
22262687 {
22272688 struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
2689
+ unsigned int interval = no_delay ? 0 : bridge->fdb_notify.interval;
22282690
22292691 mlxsw_core_schedule_dw(&bridge->fdb_notify.dw,
2230
- msecs_to_jiffies(bridge->fdb_notify.interval));
2692
+ msecs_to_jiffies(interval));
22312693 }
2694
+
2695
+#define MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION 10
22322696
22332697 static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
22342698 {
22352699 struct mlxsw_sp_bridge *bridge;
22362700 struct mlxsw_sp *mlxsw_sp;
22372701 char *sfn_pl;
2702
+ int queries;
22382703 u8 num_rec;
22392704 int i;
22402705 int err;
....@@ -2247,30 +2712,138 @@
22472712 mlxsw_sp = bridge->mlxsw_sp;
22482713
22492714 rtnl_lock();
2250
- mlxsw_reg_sfn_pack(sfn_pl);
2251
- err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
2252
- if (err) {
2253
- dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
2254
- goto out;
2715
+ queries = MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION;
2716
+ while (queries > 0) {
2717
+ mlxsw_reg_sfn_pack(sfn_pl);
2718
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
2719
+ if (err) {
2720
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
2721
+ goto out;
2722
+ }
2723
+ num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
2724
+ for (i = 0; i < num_rec; i++)
2725
+ mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
2726
+ if (num_rec != MLXSW_REG_SFN_REC_MAX_COUNT)
2727
+ goto out;
2728
+ queries--;
22552729 }
2256
- num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
2257
- for (i = 0; i < num_rec; i++)
2258
- mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
22592730
22602731 out:
22612732 rtnl_unlock();
22622733 kfree(sfn_pl);
2263
- mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
2734
+ mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, !queries);
22642735 }
22652736
22662737 struct mlxsw_sp_switchdev_event_work {
22672738 struct work_struct work;
2268
- struct switchdev_notifier_fdb_info fdb_info;
2739
+ union {
2740
+ struct switchdev_notifier_fdb_info fdb_info;
2741
+ struct switchdev_notifier_vxlan_fdb_info vxlan_fdb_info;
2742
+ };
22692743 struct net_device *dev;
22702744 unsigned long event;
22712745 };
22722746
2273
-static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
2747
+static void
2748
+mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp,
2749
+ struct mlxsw_sp_switchdev_event_work *
2750
+ switchdev_work,
2751
+ struct mlxsw_sp_fid *fid, __be32 vni)
2752
+{
2753
+ struct switchdev_notifier_vxlan_fdb_info vxlan_fdb_info;
2754
+ struct switchdev_notifier_fdb_info *fdb_info;
2755
+ struct net_device *dev = switchdev_work->dev;
2756
+ enum mlxsw_sp_l3proto proto;
2757
+ union mlxsw_sp_l3addr addr;
2758
+ int err;
2759
+
2760
+ fdb_info = &switchdev_work->fdb_info;
2761
+ err = vxlan_fdb_find_uc(dev, fdb_info->addr, vni, &vxlan_fdb_info);
2762
+ if (err)
2763
+ return;
2764
+
2765
+ mlxsw_sp_switchdev_vxlan_addr_convert(&vxlan_fdb_info.remote_ip,
2766
+ &proto, &addr);
2767
+
2768
+ switch (switchdev_work->event) {
2769
+ case SWITCHDEV_FDB_ADD_TO_DEVICE:
2770
+ err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp,
2771
+ vxlan_fdb_info.eth_addr,
2772
+ mlxsw_sp_fid_index(fid),
2773
+ proto, &addr, true, false);
2774
+ if (err)
2775
+ return;
2776
+ vxlan_fdb_info.offloaded = true;
2777
+ call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
2778
+ &vxlan_fdb_info.info, NULL);
2779
+ mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
2780
+ vxlan_fdb_info.eth_addr,
2781
+ fdb_info->vid, dev, true);
2782
+ break;
2783
+ case SWITCHDEV_FDB_DEL_TO_DEVICE:
2784
+ err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp,
2785
+ vxlan_fdb_info.eth_addr,
2786
+ mlxsw_sp_fid_index(fid),
2787
+ proto, &addr, false,
2788
+ false);
2789
+ vxlan_fdb_info.offloaded = false;
2790
+ call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
2791
+ &vxlan_fdb_info.info, NULL);
2792
+ break;
2793
+ }
2794
+}
2795
+
2796
+static void
2797
+mlxsw_sp_switchdev_bridge_nve_fdb_event(struct mlxsw_sp_switchdev_event_work *
2798
+ switchdev_work)
2799
+{
2800
+ struct mlxsw_sp_bridge_device *bridge_device;
2801
+ struct net_device *dev = switchdev_work->dev;
2802
+ struct net_device *br_dev;
2803
+ struct mlxsw_sp *mlxsw_sp;
2804
+ struct mlxsw_sp_fid *fid;
2805
+ __be32 vni;
2806
+ int err;
2807
+
2808
+ if (switchdev_work->event != SWITCHDEV_FDB_ADD_TO_DEVICE &&
2809
+ switchdev_work->event != SWITCHDEV_FDB_DEL_TO_DEVICE)
2810
+ return;
2811
+
2812
+ if (switchdev_work->event == SWITCHDEV_FDB_ADD_TO_DEVICE &&
2813
+ !switchdev_work->fdb_info.added_by_user)
2814
+ return;
2815
+
2816
+ if (!netif_running(dev))
2817
+ return;
2818
+ br_dev = netdev_master_upper_dev_get(dev);
2819
+ if (!br_dev)
2820
+ return;
2821
+ if (!netif_is_bridge_master(br_dev))
2822
+ return;
2823
+ mlxsw_sp = mlxsw_sp_lower_get(br_dev);
2824
+ if (!mlxsw_sp)
2825
+ return;
2826
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
2827
+ if (!bridge_device)
2828
+ return;
2829
+
2830
+ fid = bridge_device->ops->fid_lookup(bridge_device,
2831
+ switchdev_work->fdb_info.vid);
2832
+ if (!fid)
2833
+ return;
2834
+
2835
+ err = mlxsw_sp_fid_vni(fid, &vni);
2836
+ if (err)
2837
+ goto out;
2838
+
2839
+ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(mlxsw_sp, switchdev_work, fid,
2840
+ vni);
2841
+
2842
+out:
2843
+ mlxsw_sp_fid_put(fid);
2844
+}
2845
+
2846
+static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
22742847 {
22752848 struct mlxsw_sp_switchdev_event_work *switchdev_work =
22762849 container_of(work, struct mlxsw_sp_switchdev_event_work, work);
....@@ -2280,6 +2853,11 @@
22802853 int err;
22812854
22822855 rtnl_lock();
2856
+ if (netif_is_vxlan(dev)) {
2857
+ mlxsw_sp_switchdev_bridge_nve_fdb_event(switchdev_work);
2858
+ goto out;
2859
+ }
2860
+
22832861 mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
22842862 if (!mlxsw_sp_port)
22852863 goto out;
....@@ -2294,13 +2872,13 @@
22942872 break;
22952873 mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
22962874 fdb_info->addr,
2297
- fdb_info->vid, dev);
2875
+ fdb_info->vid, dev, true);
22982876 break;
22992877 case SWITCHDEV_FDB_DEL_TO_DEVICE:
23002878 fdb_info = &switchdev_work->fdb_info;
23012879 mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
23022880 break;
2303
- case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
2881
+ case SWITCHDEV_FDB_ADD_TO_BRIDGE:
23042882 case SWITCHDEV_FDB_DEL_TO_BRIDGE:
23052883 /* These events are only used to potentially update an existing
23062884 * SPAN mirror.
....@@ -2317,14 +2895,217 @@
23172895 dev_put(dev);
23182896 }
23192897
2898
+static void
2899
+mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp,
2900
+ struct mlxsw_sp_switchdev_event_work *
2901
+ switchdev_work)
2902
+{
2903
+ struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info;
2904
+ struct mlxsw_sp_bridge_device *bridge_device;
2905
+ struct net_device *dev = switchdev_work->dev;
2906
+ u8 all_zeros_mac[ETH_ALEN] = { 0 };
2907
+ enum mlxsw_sp_l3proto proto;
2908
+ union mlxsw_sp_l3addr addr;
2909
+ struct net_device *br_dev;
2910
+ struct mlxsw_sp_fid *fid;
2911
+ u16 vid;
2912
+ int err;
2913
+
2914
+ vxlan_fdb_info = &switchdev_work->vxlan_fdb_info;
2915
+ br_dev = netdev_master_upper_dev_get(dev);
2916
+
2917
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
2918
+ if (!bridge_device)
2919
+ return;
2920
+
2921
+ fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vxlan_fdb_info->vni);
2922
+ if (!fid)
2923
+ return;
2924
+
2925
+ mlxsw_sp_switchdev_vxlan_addr_convert(&vxlan_fdb_info->remote_ip,
2926
+ &proto, &addr);
2927
+
2928
+ if (ether_addr_equal(vxlan_fdb_info->eth_addr, all_zeros_mac)) {
2929
+ err = mlxsw_sp_nve_flood_ip_add(mlxsw_sp, fid, proto, &addr);
2930
+ if (err) {
2931
+ mlxsw_sp_fid_put(fid);
2932
+ return;
2933
+ }
2934
+ vxlan_fdb_info->offloaded = true;
2935
+ call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
2936
+ &vxlan_fdb_info->info, NULL);
2937
+ mlxsw_sp_fid_put(fid);
2938
+ return;
2939
+ }
2940
+
2941
+ /* The device has a single FDB table, whereas Linux has two - one
2942
+ * in the bridge driver and another in the VxLAN driver. We only
2943
+ * program an entry to the device if the MAC points to the VxLAN
2944
+ * device in the bridge's FDB table
2945
+ */
2946
+ vid = bridge_device->ops->fid_vid(bridge_device, fid);
2947
+ if (br_fdb_find_port(br_dev, vxlan_fdb_info->eth_addr, vid) != dev)
2948
+ goto err_br_fdb_find;
2949
+
2950
+ err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp, vxlan_fdb_info->eth_addr,
2951
+ mlxsw_sp_fid_index(fid), proto,
2952
+ &addr, true, false);
2953
+ if (err)
2954
+ goto err_fdb_tunnel_uc_op;
2955
+ vxlan_fdb_info->offloaded = true;
2956
+ call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
2957
+ &vxlan_fdb_info->info, NULL);
2958
+ mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
2959
+ vxlan_fdb_info->eth_addr, vid, dev, true);
2960
+
2961
+ mlxsw_sp_fid_put(fid);
2962
+
2963
+ return;
2964
+
2965
+err_fdb_tunnel_uc_op:
2966
+err_br_fdb_find:
2967
+ mlxsw_sp_fid_put(fid);
2968
+}
2969
+
2970
+static void
2971
+mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp,
2972
+ struct mlxsw_sp_switchdev_event_work *
2973
+ switchdev_work)
2974
+{
2975
+ struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info;
2976
+ struct mlxsw_sp_bridge_device *bridge_device;
2977
+ struct net_device *dev = switchdev_work->dev;
2978
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2979
+ u8 all_zeros_mac[ETH_ALEN] = { 0 };
2980
+ enum mlxsw_sp_l3proto proto;
2981
+ union mlxsw_sp_l3addr addr;
2982
+ struct mlxsw_sp_fid *fid;
2983
+ u16 vid;
2984
+
2985
+ vxlan_fdb_info = &switchdev_work->vxlan_fdb_info;
2986
+
2987
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
2988
+ if (!bridge_device)
2989
+ return;
2990
+
2991
+ fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vxlan_fdb_info->vni);
2992
+ if (!fid)
2993
+ return;
2994
+
2995
+ mlxsw_sp_switchdev_vxlan_addr_convert(&vxlan_fdb_info->remote_ip,
2996
+ &proto, &addr);
2997
+
2998
+ if (ether_addr_equal(vxlan_fdb_info->eth_addr, all_zeros_mac)) {
2999
+ mlxsw_sp_nve_flood_ip_del(mlxsw_sp, fid, proto, &addr);
3000
+ mlxsw_sp_fid_put(fid);
3001
+ return;
3002
+ }
3003
+
3004
+ mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp, vxlan_fdb_info->eth_addr,
3005
+ mlxsw_sp_fid_index(fid), proto, &addr,
3006
+ false, false);
3007
+ vid = bridge_device->ops->fid_vid(bridge_device, fid);
3008
+ mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
3009
+ vxlan_fdb_info->eth_addr, vid, dev, false);
3010
+
3011
+ mlxsw_sp_fid_put(fid);
3012
+}
3013
+
3014
+static void mlxsw_sp_switchdev_vxlan_fdb_event_work(struct work_struct *work)
3015
+{
3016
+ struct mlxsw_sp_switchdev_event_work *switchdev_work =
3017
+ container_of(work, struct mlxsw_sp_switchdev_event_work, work);
3018
+ struct net_device *dev = switchdev_work->dev;
3019
+ struct mlxsw_sp *mlxsw_sp;
3020
+ struct net_device *br_dev;
3021
+
3022
+ rtnl_lock();
3023
+
3024
+ if (!netif_running(dev))
3025
+ goto out;
3026
+ br_dev = netdev_master_upper_dev_get(dev);
3027
+ if (!br_dev)
3028
+ goto out;
3029
+ if (!netif_is_bridge_master(br_dev))
3030
+ goto out;
3031
+ mlxsw_sp = mlxsw_sp_lower_get(br_dev);
3032
+ if (!mlxsw_sp)
3033
+ goto out;
3034
+
3035
+ switch (switchdev_work->event) {
3036
+ case SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE:
3037
+ mlxsw_sp_switchdev_vxlan_fdb_add(mlxsw_sp, switchdev_work);
3038
+ break;
3039
+ case SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE:
3040
+ mlxsw_sp_switchdev_vxlan_fdb_del(mlxsw_sp, switchdev_work);
3041
+ break;
3042
+ }
3043
+
3044
+out:
3045
+ rtnl_unlock();
3046
+ kfree(switchdev_work);
3047
+ dev_put(dev);
3048
+}
3049
+
3050
+static int
3051
+mlxsw_sp_switchdev_vxlan_work_prepare(struct mlxsw_sp_switchdev_event_work *
3052
+ switchdev_work,
3053
+ struct switchdev_notifier_info *info)
3054
+{
3055
+ struct vxlan_dev *vxlan = netdev_priv(switchdev_work->dev);
3056
+ struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info;
3057
+ struct vxlan_config *cfg = &vxlan->cfg;
3058
+ struct netlink_ext_ack *extack;
3059
+
3060
+ extack = switchdev_notifier_info_to_extack(info);
3061
+ vxlan_fdb_info = container_of(info,
3062
+ struct switchdev_notifier_vxlan_fdb_info,
3063
+ info);
3064
+
3065
+ if (vxlan_fdb_info->remote_port != cfg->dst_port) {
3066
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default remote port is not supported");
3067
+ return -EOPNOTSUPP;
3068
+ }
3069
+ if (vxlan_fdb_info->remote_vni != cfg->vni ||
3070
+ vxlan_fdb_info->vni != cfg->vni) {
3071
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default VNI is not supported");
3072
+ return -EOPNOTSUPP;
3073
+ }
3074
+ if (vxlan_fdb_info->remote_ifindex) {
3075
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Local interface is not supported");
3076
+ return -EOPNOTSUPP;
3077
+ }
3078
+ if (is_multicast_ether_addr(vxlan_fdb_info->eth_addr)) {
3079
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast MAC addresses not supported");
3080
+ return -EOPNOTSUPP;
3081
+ }
3082
+ if (vxlan_addr_multicast(&vxlan_fdb_info->remote_ip)) {
3083
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast destination IP is not supported");
3084
+ return -EOPNOTSUPP;
3085
+ }
3086
+
3087
+ switchdev_work->vxlan_fdb_info = *vxlan_fdb_info;
3088
+
3089
+ return 0;
3090
+}
3091
+
23203092 /* Called under rcu_read_lock() */
23213093 static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
23223094 unsigned long event, void *ptr)
23233095 {
23243096 struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
23253097 struct mlxsw_sp_switchdev_event_work *switchdev_work;
2326
- struct switchdev_notifier_fdb_info *fdb_info = ptr;
3098
+ struct switchdev_notifier_fdb_info *fdb_info;
3099
+ struct switchdev_notifier_info *info = ptr;
23273100 struct net_device *br_dev;
3101
+ int err;
3102
+
3103
+ if (event == SWITCHDEV_PORT_ATTR_SET) {
3104
+ err = switchdev_handle_port_attr_set(dev, ptr,
3105
+ mlxsw_sp_port_dev_check,
3106
+ mlxsw_sp_port_attr_set);
3107
+ return notifier_from_errno(err);
3108
+ }
23283109
23293110 /* Tunnel devices are not our uppers, so check their master instead */
23303111 br_dev = netdev_master_upper_dev_get_rcu(dev);
....@@ -2339,15 +3120,19 @@
23393120 if (!switchdev_work)
23403121 return NOTIFY_BAD;
23413122
2342
- INIT_WORK(&switchdev_work->work, mlxsw_sp_switchdev_event_work);
23433123 switchdev_work->dev = dev;
23443124 switchdev_work->event = event;
23453125
23463126 switch (event) {
2347
- case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
2348
- case SWITCHDEV_FDB_DEL_TO_DEVICE: /* fall through */
2349
- case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
3127
+ case SWITCHDEV_FDB_ADD_TO_DEVICE:
3128
+ case SWITCHDEV_FDB_DEL_TO_DEVICE:
3129
+ case SWITCHDEV_FDB_ADD_TO_BRIDGE:
23503130 case SWITCHDEV_FDB_DEL_TO_BRIDGE:
3131
+ fdb_info = container_of(info,
3132
+ struct switchdev_notifier_fdb_info,
3133
+ info);
3134
+ INIT_WORK(&switchdev_work->work,
3135
+ mlxsw_sp_switchdev_bridge_fdb_event_work);
23513136 memcpy(&switchdev_work->fdb_info, ptr,
23523137 sizeof(switchdev_work->fdb_info));
23533138 switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
....@@ -2361,6 +3146,16 @@
23613146 */
23623147 dev_hold(dev);
23633148 break;
3149
+ case SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE:
3150
+ case SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE:
3151
+ INIT_WORK(&switchdev_work->work,
3152
+ mlxsw_sp_switchdev_vxlan_fdb_event_work);
3153
+ err = mlxsw_sp_switchdev_vxlan_work_prepare(switchdev_work,
3154
+ info);
3155
+ if (err)
3156
+ goto err_vxlan_work_prepare;
3157
+ dev_hold(dev);
3158
+ break;
23643159 default:
23653160 kfree(switchdev_work);
23663161 return NOTIFY_DONE;
....@@ -2370,13 +3165,283 @@
23703165
23713166 return NOTIFY_DONE;
23723167
3168
+err_vxlan_work_prepare:
23733169 err_addr_alloc:
23743170 kfree(switchdev_work);
23753171 return NOTIFY_BAD;
23763172 }
23773173
2378
-static struct notifier_block mlxsw_sp_switchdev_notifier = {
3174
+struct notifier_block mlxsw_sp_switchdev_notifier = {
23793175 .notifier_call = mlxsw_sp_switchdev_event,
3176
+};
3177
+
3178
+static int
3179
+mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
3180
+ struct mlxsw_sp_bridge_device *bridge_device,
3181
+ const struct net_device *vxlan_dev, u16 vid,
3182
+ bool flag_untagged, bool flag_pvid,
3183
+ struct netlink_ext_ack *extack)
3184
+{
3185
+ struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
3186
+ __be32 vni = vxlan->cfg.vni;
3187
+ struct mlxsw_sp_fid *fid;
3188
+ u16 old_vid;
3189
+ int err;
3190
+
3191
+ /* We cannot have the same VLAN as PVID and egress untagged on multiple
3192
+ * VxLAN devices. Note that we get this notification before the VLAN is
3193
+ * actually added to the bridge's database, so it is not possible for
3194
+ * the lookup function to return 'vxlan_dev'
3195
+ */
3196
+ if (flag_untagged && flag_pvid &&
3197
+ mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) {
3198
+ NL_SET_ERR_MSG_MOD(extack, "VLAN already mapped to a different VNI");
3199
+ return -EINVAL;
3200
+ }
3201
+
3202
+ if (!netif_running(vxlan_dev))
3203
+ return 0;
3204
+
3205
+ /* First case: FID is not associated with this VNI, but the new VLAN
3206
+ * is both PVID and egress untagged. Need to enable NVE on the FID, if
3207
+ * it exists
3208
+ */
3209
+ fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vni);
3210
+ if (!fid) {
3211
+ if (!flag_untagged || !flag_pvid)
3212
+ return 0;
3213
+ return mlxsw_sp_bridge_8021q_vxlan_join(bridge_device,
3214
+ vxlan_dev, vid, extack);
3215
+ }
3216
+
3217
+ /* Second case: FID is associated with the VNI and the VLAN associated
3218
+ * with the FID is the same as the notified VLAN. This means the flags
3219
+ * (PVID / egress untagged) were toggled and that NVE should be
3220
+ * disabled on the FID
3221
+ */
3222
+ old_vid = mlxsw_sp_fid_8021q_vid(fid);
3223
+ if (vid == old_vid) {
3224
+ if (WARN_ON(flag_untagged && flag_pvid)) {
3225
+ mlxsw_sp_fid_put(fid);
3226
+ return -EINVAL;
3227
+ }
3228
+ mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev);
3229
+ mlxsw_sp_fid_put(fid);
3230
+ return 0;
3231
+ }
3232
+
3233
+ /* Third case: A new VLAN was configured on the VxLAN device, but this
3234
+ * VLAN is not PVID, so there is nothing to do.
3235
+ */
3236
+ if (!flag_pvid) {
3237
+ mlxsw_sp_fid_put(fid);
3238
+ return 0;
3239
+ }
3240
+
3241
+ /* Fourth case: Thew new VLAN is PVID, which means the VLAN currently
3242
+ * mapped to the VNI should be unmapped
3243
+ */
3244
+ mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev);
3245
+ mlxsw_sp_fid_put(fid);
3246
+
3247
+ /* Fifth case: The new VLAN is also egress untagged, which means the
3248
+ * VLAN needs to be mapped to the VNI
3249
+ */
3250
+ if (!flag_untagged)
3251
+ return 0;
3252
+
3253
+ err = mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, vxlan_dev, vid,
3254
+ extack);
3255
+ if (err)
3256
+ goto err_vxlan_join;
3257
+
3258
+ return 0;
3259
+
3260
+err_vxlan_join:
3261
+ mlxsw_sp_bridge_8021q_vxlan_join(bridge_device, vxlan_dev, old_vid,
3262
+ NULL);
3263
+ return err;
3264
+}
3265
+
3266
+static void
3267
+mlxsw_sp_switchdev_vxlan_vlan_del(struct mlxsw_sp *mlxsw_sp,
3268
+ struct mlxsw_sp_bridge_device *bridge_device,
3269
+ const struct net_device *vxlan_dev, u16 vid)
3270
+{
3271
+ struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
3272
+ __be32 vni = vxlan->cfg.vni;
3273
+ struct mlxsw_sp_fid *fid;
3274
+
3275
+ if (!netif_running(vxlan_dev))
3276
+ return;
3277
+
3278
+ fid = mlxsw_sp_fid_lookup_by_vni(mlxsw_sp, vni);
3279
+ if (!fid)
3280
+ return;
3281
+
3282
+ /* A different VLAN than the one mapped to the VNI is deleted */
3283
+ if (mlxsw_sp_fid_8021q_vid(fid) != vid)
3284
+ goto out;
3285
+
3286
+ mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev);
3287
+
3288
+out:
3289
+ mlxsw_sp_fid_put(fid);
3290
+}
3291
+
3292
+static int
3293
+mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
3294
+ struct switchdev_notifier_port_obj_info *
3295
+ port_obj_info)
3296
+{
3297
+ struct switchdev_obj_port_vlan *vlan =
3298
+ SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj);
3299
+ bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
3300
+ bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
3301
+ struct switchdev_trans *trans = port_obj_info->trans;
3302
+ struct mlxsw_sp_bridge_device *bridge_device;
3303
+ struct netlink_ext_ack *extack;
3304
+ struct mlxsw_sp *mlxsw_sp;
3305
+ struct net_device *br_dev;
3306
+ u16 vid;
3307
+
3308
+ extack = switchdev_notifier_info_to_extack(&port_obj_info->info);
3309
+ br_dev = netdev_master_upper_dev_get(vxlan_dev);
3310
+ if (!br_dev)
3311
+ return 0;
3312
+
3313
+ mlxsw_sp = mlxsw_sp_lower_get(br_dev);
3314
+ if (!mlxsw_sp)
3315
+ return 0;
3316
+
3317
+ port_obj_info->handled = true;
3318
+
3319
+ if (switchdev_trans_ph_commit(trans))
3320
+ return 0;
3321
+
3322
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
3323
+ if (!bridge_device)
3324
+ return -EINVAL;
3325
+
3326
+ if (!bridge_device->vlan_enabled)
3327
+ return 0;
3328
+
3329
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
3330
+ int err;
3331
+
3332
+ err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device,
3333
+ vxlan_dev, vid,
3334
+ flag_untagged,
3335
+ flag_pvid, extack);
3336
+ if (err)
3337
+ return err;
3338
+ }
3339
+
3340
+ return 0;
3341
+}
3342
+
3343
+static void
3344
+mlxsw_sp_switchdev_vxlan_vlans_del(struct net_device *vxlan_dev,
3345
+ struct switchdev_notifier_port_obj_info *
3346
+ port_obj_info)
3347
+{
3348
+ struct switchdev_obj_port_vlan *vlan =
3349
+ SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj);
3350
+ struct mlxsw_sp_bridge_device *bridge_device;
3351
+ struct mlxsw_sp *mlxsw_sp;
3352
+ struct net_device *br_dev;
3353
+ u16 vid;
3354
+
3355
+ br_dev = netdev_master_upper_dev_get(vxlan_dev);
3356
+ if (!br_dev)
3357
+ return;
3358
+
3359
+ mlxsw_sp = mlxsw_sp_lower_get(br_dev);
3360
+ if (!mlxsw_sp)
3361
+ return;
3362
+
3363
+ port_obj_info->handled = true;
3364
+
3365
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
3366
+ if (!bridge_device)
3367
+ return;
3368
+
3369
+ if (!bridge_device->vlan_enabled)
3370
+ return;
3371
+
3372
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++)
3373
+ mlxsw_sp_switchdev_vxlan_vlan_del(mlxsw_sp, bridge_device,
3374
+ vxlan_dev, vid);
3375
+}
3376
+
3377
+static int
3378
+mlxsw_sp_switchdev_handle_vxlan_obj_add(struct net_device *vxlan_dev,
3379
+ struct switchdev_notifier_port_obj_info *
3380
+ port_obj_info)
3381
+{
3382
+ int err = 0;
3383
+
3384
+ switch (port_obj_info->obj->id) {
3385
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
3386
+ err = mlxsw_sp_switchdev_vxlan_vlans_add(vxlan_dev,
3387
+ port_obj_info);
3388
+ break;
3389
+ default:
3390
+ break;
3391
+ }
3392
+
3393
+ return err;
3394
+}
3395
+
3396
+static void
3397
+mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev,
3398
+ struct switchdev_notifier_port_obj_info *
3399
+ port_obj_info)
3400
+{
3401
+ switch (port_obj_info->obj->id) {
3402
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
3403
+ mlxsw_sp_switchdev_vxlan_vlans_del(vxlan_dev, port_obj_info);
3404
+ break;
3405
+ default:
3406
+ break;
3407
+ }
3408
+}
3409
+
3410
+static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
3411
+ unsigned long event, void *ptr)
3412
+{
3413
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
3414
+ int err = 0;
3415
+
3416
+ switch (event) {
3417
+ case SWITCHDEV_PORT_OBJ_ADD:
3418
+ if (netif_is_vxlan(dev))
3419
+ err = mlxsw_sp_switchdev_handle_vxlan_obj_add(dev, ptr);
3420
+ else
3421
+ err = switchdev_handle_port_obj_add(dev, ptr,
3422
+ mlxsw_sp_port_dev_check,
3423
+ mlxsw_sp_port_obj_add);
3424
+ return notifier_from_errno(err);
3425
+ case SWITCHDEV_PORT_OBJ_DEL:
3426
+ if (netif_is_vxlan(dev))
3427
+ mlxsw_sp_switchdev_handle_vxlan_obj_del(dev, ptr);
3428
+ else
3429
+ err = switchdev_handle_port_obj_del(dev, ptr,
3430
+ mlxsw_sp_port_dev_check,
3431
+ mlxsw_sp_port_obj_del);
3432
+ return notifier_from_errno(err);
3433
+ case SWITCHDEV_PORT_ATTR_SET:
3434
+ err = switchdev_handle_port_attr_set(dev, ptr,
3435
+ mlxsw_sp_port_dev_check,
3436
+ mlxsw_sp_port_attr_set);
3437
+ return notifier_from_errno(err);
3438
+ }
3439
+
3440
+ return NOTIFY_DONE;
3441
+}
3442
+
3443
+static struct notifier_block mlxsw_sp_switchdev_blocking_notifier = {
3444
+ .notifier_call = mlxsw_sp_switchdev_blocking_event,
23803445 };
23813446
23823447 u8
....@@ -2388,6 +3453,7 @@
23883453 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
23893454 {
23903455 struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
3456
+ struct notifier_block *nb;
23913457 int err;
23923458
23933459 err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
....@@ -2402,17 +3468,33 @@
24023468 return err;
24033469 }
24043470
3471
+ nb = &mlxsw_sp_switchdev_blocking_notifier;
3472
+ err = register_switchdev_blocking_notifier(nb);
3473
+ if (err) {
3474
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to register switchdev blocking notifier\n");
3475
+ goto err_register_switchdev_blocking_notifier;
3476
+ }
3477
+
24053478 INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
24063479 bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
2407
- mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
3480
+ mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, false);
24083481 return 0;
3482
+
3483
+err_register_switchdev_blocking_notifier:
3484
+ unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
3485
+ return err;
24093486 }
24103487
24113488 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
24123489 {
2413
- cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
2414
- unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
3490
+ struct notifier_block *nb;
24153491
3492
+ cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
3493
+
3494
+ nb = &mlxsw_sp_switchdev_blocking_notifier;
3495
+ unregister_switchdev_blocking_notifier(nb);
3496
+
3497
+ unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
24163498 }
24173499
24183500 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
....@@ -2440,11 +3522,3 @@
24403522 kfree(mlxsw_sp->bridge);
24413523 }
24423524
2443
-void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
2444
-{
2445
- mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;
2446
-}
2447
-
2448
-void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port)
2449
-{
2450
-}