summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/b53/b53_common.c16
-rw-r--r--drivers/net/dsa/b53/b53_priv.h3
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c20
-rw-r--r--drivers/net/dsa/mt7530.c10
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c38
-rw-r--r--drivers/net/dsa/qca8k.c15
-rw-r--r--include/net/dsa.h5
-rw-r--r--include/net/switchdev.h12
-rw-r--r--net/dsa/dsa_priv.h2
-rw-r--r--net/dsa/port.c11
-rw-r--r--net/dsa/slave.c100
-rw-r--r--net/switchdev/switchdev.c84
12 files changed, 112 insertions, 204 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 0176d8087344..274f3679f33d 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1227,8 +1227,7 @@ static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
1227} 1227}
1228 1228
1229static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, 1229static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
1230 struct switchdev_obj_port_fdb *fdb, 1230 dsa_fdb_dump_cb_t *cb, void *data)
1231 switchdev_obj_dump_cb_t *cb)
1232{ 1231{
1233 if (!ent->is_valid) 1232 if (!ent->is_valid)
1234 return 0; 1233 return 0;
@@ -1236,16 +1235,11 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
1236 if (port != ent->port) 1235 if (port != ent->port)
1237 return 0; 1236 return 0;
1238 1237
1239 ether_addr_copy(fdb->addr, ent->mac); 1238 return cb(ent->mac, ent->vid, ent->is_static, data);
1240 fdb->vid = ent->vid;
1241 fdb->ndm_state = ent->is_static ? NUD_NOARP : NUD_REACHABLE;
1242
1243 return cb(&fdb->obj);
1244} 1239}
1245 1240
1246int b53_fdb_dump(struct dsa_switch *ds, int port, 1241int b53_fdb_dump(struct dsa_switch *ds, int port,
1247 struct switchdev_obj_port_fdb *fdb, 1242 dsa_fdb_dump_cb_t *cb, void *data)
1248 switchdev_obj_dump_cb_t *cb)
1249{ 1243{
1250 struct b53_device *priv = ds->priv; 1244 struct b53_device *priv = ds->priv;
1251 struct b53_arl_entry results[2]; 1245 struct b53_arl_entry results[2];
@@ -1263,13 +1257,13 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
1263 return ret; 1257 return ret;
1264 1258
1265 b53_arl_search_rd(priv, 0, &results[0]); 1259 b53_arl_search_rd(priv, 0, &results[0]);
1266 ret = b53_fdb_copy(port, &results[0], fdb, cb); 1260 ret = b53_fdb_copy(port, &results[0], cb, data);
1267 if (ret) 1261 if (ret)
1268 return ret; 1262 return ret;
1269 1263
1270 if (priv->num_arl_entries > 2) { 1264 if (priv->num_arl_entries > 2) {
1271 b53_arl_search_rd(priv, 1, &results[1]); 1265 b53_arl_search_rd(priv, 1, &results[1]);
1272 ret = b53_fdb_copy(port, &results[1], fdb, cb); 1266 ret = b53_fdb_copy(port, &results[1], cb, data);
1273 if (ret) 1267 if (ret)
1274 return ret; 1268 return ret;
1275 1269
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index af5d6c166bff..01bd8cbe9a3f 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -398,8 +398,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
398int b53_fdb_del(struct dsa_switch *ds, int port, 398int b53_fdb_del(struct dsa_switch *ds, int port,
399 const unsigned char *addr, u16 vid); 399 const unsigned char *addr, u16 vid);
400int b53_fdb_dump(struct dsa_switch *ds, int port, 400int b53_fdb_dump(struct dsa_switch *ds, int port,
401 struct switchdev_obj_port_fdb *fdb, 401 dsa_fdb_dump_cb_t *cb, void *data);
402 switchdev_obj_dump_cb_t *cb);
403int b53_mirror_add(struct dsa_switch *ds, int port, 402int b53_mirror_add(struct dsa_switch *ds, int port,
404 struct dsa_mall_mirror_tc_entry *mirror, bool ingress); 403 struct dsa_mall_mirror_tc_entry *mirror, bool ingress);
405void b53_mirror_del(struct dsa_switch *ds, int port, 404void b53_mirror_del(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 4de9d90a4bb3..56cd6d365352 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -805,12 +805,11 @@ static void convert_alu(struct alu_struct *alu, u32 *alu_table)
805} 805}
806 806
807static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, 807static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
808 struct switchdev_obj_port_fdb *fdb, 808 dsa_fdb_dump_cb_t *cb, void *data)
809 switchdev_obj_dump_cb_t *cb)
810{ 809{
811 struct ksz_device *dev = ds->priv; 810 struct ksz_device *dev = ds->priv;
812 int ret = 0; 811 int ret = 0;
813 u32 data; 812 u32 ksz_data;
814 u32 alu_table[4]; 813 u32 alu_table[4];
815 struct alu_struct alu; 814 struct alu_struct alu;
816 int timeout; 815 int timeout;
@@ -823,8 +822,8 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
823 do { 822 do {
824 timeout = 1000; 823 timeout = 1000;
825 do { 824 do {
826 ksz_read32(dev, REG_SW_ALU_CTRL__4, &data); 825 ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data);
827 if ((data & ALU_VALID) || !(data & ALU_START)) 826 if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START))
828 break; 827 break;
829 usleep_range(1, 10); 828 usleep_range(1, 10);
830 } while (timeout-- > 0); 829 } while (timeout-- > 0);
@@ -841,18 +840,11 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
841 convert_alu(&alu, alu_table); 840 convert_alu(&alu, alu_table);
842 841
843 if (alu.port_forward & BIT(port)) { 842 if (alu.port_forward & BIT(port)) {
844 fdb->vid = alu.fid; 843 ret = cb(alu.mac, alu.fid, alu.is_static, data);
845 if (alu.is_static)
846 fdb->ndm_state = NUD_NOARP;
847 else
848 fdb->ndm_state = NUD_REACHABLE;
849 ether_addr_copy(fdb->addr, alu.mac);
850
851 ret = cb(&fdb->obj);
852 if (ret) 844 if (ret)
853 goto exit; 845 goto exit;
854 } 846 }
855 } while (data & ALU_START); 847 } while (ksz_data & ALU_START);
856 848
857exit: 849exit:
858 850
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index f92aae8947e6..12700710f26d 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -834,8 +834,7 @@ mt7530_port_fdb_del(struct dsa_switch *ds, int port,
834 834
835static int 835static int
836mt7530_port_fdb_dump(struct dsa_switch *ds, int port, 836mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
837 struct switchdev_obj_port_fdb *fdb, 837 dsa_fdb_dump_cb_t *cb, void *data)
838 switchdev_obj_dump_cb_t *cb)
839{ 838{
840 struct mt7530_priv *priv = ds->priv; 839 struct mt7530_priv *priv = ds->priv;
841 struct mt7530_fdb _fdb = { 0 }; 840 struct mt7530_fdb _fdb = { 0 };
@@ -853,11 +852,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
853 if (rsp & ATC_SRCH_HIT) { 852 if (rsp & ATC_SRCH_HIT) {
854 mt7530_fdb_read(priv, &_fdb); 853 mt7530_fdb_read(priv, &_fdb);
855 if (_fdb.port_mask & BIT(port)) { 854 if (_fdb.port_mask & BIT(port)) {
856 ether_addr_copy(fdb->addr, _fdb.mac); 855 ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp,
857 fdb->vid = _fdb.vid; 856 data);
858 fdb->ndm_state = _fdb.noarp ?
859 NUD_NOARP : NUD_REACHABLE;
860 ret = cb(&fdb->obj);
861 if (ret < 0) 857 if (ret < 0)
862 break; 858 break;
863 } 859 }
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 1f5c202b974d..918d8f0fe091 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1381,10 +1381,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1381 1381
1382static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, 1382static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
1383 u16 fid, u16 vid, int port, 1383 u16 fid, u16 vid, int port,
1384 struct switchdev_obj *obj, 1384 dsa_fdb_dump_cb_t *cb, void *data)
1385 switchdev_obj_dump_cb_t *cb)
1386{ 1385{
1387 struct mv88e6xxx_atu_entry addr; 1386 struct mv88e6xxx_atu_entry addr;
1387 bool is_static;
1388 int err; 1388 int err;
1389 1389
1390 addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED; 1390 addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
@@ -1401,24 +1401,12 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
1401 if (addr.trunk || (addr.portvec & BIT(port)) == 0) 1401 if (addr.trunk || (addr.portvec & BIT(port)) == 0)
1402 continue; 1402 continue;
1403 1403
1404 if (obj->id == SWITCHDEV_OBJ_ID_PORT_FDB) { 1404 if (!is_unicast_ether_addr(addr.mac))
1405 struct switchdev_obj_port_fdb *fdb; 1405 continue;
1406
1407 if (!is_unicast_ether_addr(addr.mac))
1408 continue;
1409
1410 fdb = SWITCHDEV_OBJ_PORT_FDB(obj);
1411 fdb->vid = vid;
1412 ether_addr_copy(fdb->addr, addr.mac);
1413 if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC)
1414 fdb->ndm_state = NUD_NOARP;
1415 else
1416 fdb->ndm_state = NUD_REACHABLE;
1417 } else {
1418 return -EOPNOTSUPP;
1419 }
1420 1406
1421 err = cb(obj); 1407 is_static = (addr.state ==
1408 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
1409 err = cb(addr.mac, vid, is_static, data);
1422 if (err) 1410 if (err)
1423 return err; 1411 return err;
1424 } while (!is_broadcast_ether_addr(addr.mac)); 1412 } while (!is_broadcast_ether_addr(addr.mac));
@@ -1427,8 +1415,7 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
1427} 1415}
1428 1416
1429static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, 1417static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1430 struct switchdev_obj *obj, 1418 dsa_fdb_dump_cb_t *cb, void *data)
1431 switchdev_obj_dump_cb_t *cb)
1432{ 1419{
1433 struct mv88e6xxx_vtu_entry vlan = { 1420 struct mv88e6xxx_vtu_entry vlan = {
1434 .vid = chip->info->max_vid, 1421 .vid = chip->info->max_vid,
@@ -1441,7 +1428,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1441 if (err) 1428 if (err)
1442 return err; 1429 return err;
1443 1430
1444 err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, obj, cb); 1431 err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data);
1445 if (err) 1432 if (err)
1446 return err; 1433 return err;
1447 1434
@@ -1455,7 +1442,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1455 break; 1442 break;
1456 1443
1457 err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port, 1444 err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
1458 obj, cb); 1445 cb, data);
1459 if (err) 1446 if (err)
1460 return err; 1447 return err;
1461 } while (vlan.vid < chip->info->max_vid); 1448 } while (vlan.vid < chip->info->max_vid);
@@ -1464,14 +1451,13 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1464} 1451}
1465 1452
1466static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, 1453static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1467 struct switchdev_obj_port_fdb *fdb, 1454 dsa_fdb_dump_cb_t *cb, void *data)
1468 switchdev_obj_dump_cb_t *cb)
1469{ 1455{
1470 struct mv88e6xxx_chip *chip = ds->priv; 1456 struct mv88e6xxx_chip *chip = ds->priv;
1471 int err; 1457 int err;
1472 1458
1473 mutex_lock(&chip->reg_lock); 1459 mutex_lock(&chip->reg_lock);
1474 err = mv88e6xxx_port_db_dump(chip, port, &fdb->obj, cb); 1460 err = mv88e6xxx_port_db_dump(chip, port, cb, data);
1475 mutex_unlock(&chip->reg_lock); 1461 mutex_unlock(&chip->reg_lock);
1476 1462
1477 return err; 1463 return err;
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index f8ef823349bc..17977f06cb98 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -801,27 +801,20 @@ qca8k_port_fdb_del(struct dsa_switch *ds, int port,
801 801
802static int 802static int
803qca8k_port_fdb_dump(struct dsa_switch *ds, int port, 803qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
804 struct switchdev_obj_port_fdb *fdb, 804 dsa_fdb_dump_cb_t *cb, void *data)
805 switchdev_obj_dump_cb_t *cb)
806{ 805{
807 struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; 806 struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
808 struct qca8k_fdb _fdb = { 0 }; 807 struct qca8k_fdb _fdb = { 0 };
809 int cnt = QCA8K_NUM_FDB_RECORDS; 808 int cnt = QCA8K_NUM_FDB_RECORDS;
809 bool is_static;
810 int ret = 0; 810 int ret = 0;
811 811
812 mutex_lock(&priv->reg_mutex); 812 mutex_lock(&priv->reg_mutex);
813 while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) { 813 while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
814 if (!_fdb.aging) 814 if (!_fdb.aging)
815 break; 815 break;
816 816 is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
817 ether_addr_copy(fdb->addr, _fdb.mac); 817 ret = cb(_fdb.mac, _fdb.vid, is_static, data);
818 fdb->vid = _fdb.vid;
819 if (_fdb.aging == QCA8K_ATU_STATUS_STATIC)
820 fdb->ndm_state = NUD_NOARP;
821 else
822 fdb->ndm_state = NUD_REACHABLE;
823
824 ret = cb(&fdb->obj);
825 if (ret) 818 if (ret)
826 break; 819 break;
827 } 820 }
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 4ef185997b6f..a4f66dbb4b7c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -272,6 +272,8 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
272 return ds->rtable[dst->cpu_dp->ds->index]; 272 return ds->rtable[dst->cpu_dp->ds->index];
273} 273}
274 274
275typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
276 bool is_static, void *data);
275struct dsa_switch_ops { 277struct dsa_switch_ops {
276 /* 278 /*
277 * Legacy probing. 279 * Legacy probing.
@@ -386,8 +388,7 @@ struct dsa_switch_ops {
386 int (*port_fdb_del)(struct dsa_switch *ds, int port, 388 int (*port_fdb_del)(struct dsa_switch *ds, int port,
387 const unsigned char *addr, u16 vid); 389 const unsigned char *addr, u16 vid);
388 int (*port_fdb_dump)(struct dsa_switch *ds, int port, 390 int (*port_fdb_dump)(struct dsa_switch *ds, int port,
389 struct switchdev_obj_port_fdb *fdb, 391 dsa_fdb_dump_cb_t *cb, void *data);
390 switchdev_obj_dump_cb_t *cb);
391 392
392 /* 393 /*
393 * Multicast database 394 * Multicast database
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 8ae9e3b6392e..d2637a685ca6 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -208,9 +208,6 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
208int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 208int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
209 struct net_device *dev, const unsigned char *addr, 209 struct net_device *dev, const unsigned char *addr,
210 u16 vid); 210 u16 vid);
211int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
212 struct net_device *dev,
213 struct net_device *filter_dev, int *idx);
214void switchdev_port_fwd_mark_set(struct net_device *dev, 211void switchdev_port_fwd_mark_set(struct net_device *dev,
215 struct net_device *group_dev, 212 struct net_device *group_dev,
216 bool joining); 213 bool joining);
@@ -309,15 +306,6 @@ static inline int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
309 return -EOPNOTSUPP; 306 return -EOPNOTSUPP;
310} 307}
311 308
312static inline int switchdev_port_fdb_dump(struct sk_buff *skb,
313 struct netlink_callback *cb,
314 struct net_device *dev,
315 struct net_device *filter_dev,
316 int *idx)
317{
318 return *idx;
319}
320
321static inline bool switchdev_port_same_parent_id(struct net_device *a, 309static inline bool switchdev_port_same_parent_id(struct net_device *a,
322 struct net_device *b) 310 struct net_device *b)
323{ 311{
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 9c890de6e4dd..1debf9c42fc4 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -133,8 +133,6 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
133 u16 vid); 133 u16 vid);
134int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, 134int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
135 u16 vid); 135 u16 vid);
136int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
137 switchdev_obj_dump_cb_t *cb);
138int dsa_port_mdb_add(struct dsa_port *dp, 136int dsa_port_mdb_add(struct dsa_port *dp,
139 const struct switchdev_obj_port_mdb *mdb, 137 const struct switchdev_obj_port_mdb *mdb,
140 struct switchdev_trans *trans); 138 struct switchdev_trans *trans);
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 73787828953a..659676ba3f8b 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -173,17 +173,6 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
173 return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); 173 return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
174} 174}
175 175
176int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
177 switchdev_obj_dump_cb_t *cb)
178{
179 struct dsa_switch *ds = dp->ds;
180
181 if (ds->ops->port_fdb_dump)
182 return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb);
183
184 return -EOPNOTSUPP;
185}
186
187int dsa_port_mdb_add(struct dsa_port *dp, 176int dsa_port_mdb_add(struct dsa_port *dp,
188 const struct switchdev_obj_port_mdb *mdb, 177 const struct switchdev_obj_port_mdb *mdb,
189 struct switchdev_trans *trans) 178 struct switchdev_trans *trans)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 5807c905fd1d..8c79011c5a83 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -199,6 +199,83 @@ out:
199 return 0; 199 return 0;
200} 200}
201 201
202struct dsa_slave_dump_ctx {
203 struct net_device *dev;
204 struct sk_buff *skb;
205 struct netlink_callback *cb;
206 int idx;
207};
208
209static int
210dsa_slave_port_fdb_do_dump(const unsigned char *addr, u16 vid,
211 bool is_static, void *data)
212{
213 struct dsa_slave_dump_ctx *dump = data;
214 u32 portid = NETLINK_CB(dump->cb->skb).portid;
215 u32 seq = dump->cb->nlh->nlmsg_seq;
216 struct nlmsghdr *nlh;
217 struct ndmsg *ndm;
218
219 if (dump->idx < dump->cb->args[2])
220 goto skip;
221
222 nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
223 sizeof(*ndm), NLM_F_MULTI);
224 if (!nlh)
225 return -EMSGSIZE;
226
227 ndm = nlmsg_data(nlh);
228 ndm->ndm_family = AF_BRIDGE;
229 ndm->ndm_pad1 = 0;
230 ndm->ndm_pad2 = 0;
231 ndm->ndm_flags = NTF_SELF;
232 ndm->ndm_type = 0;
233 ndm->ndm_ifindex = dump->dev->ifindex;
234 ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
235
236 if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
237 goto nla_put_failure;
238
239 if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
240 goto nla_put_failure;
241
242 nlmsg_end(dump->skb, nlh);
243
244skip:
245 dump->idx++;
246 return 0;
247
248nla_put_failure:
249 nlmsg_cancel(dump->skb, nlh);
250 return -EMSGSIZE;
251}
252
253static int
254dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
255 struct net_device *dev, struct net_device *filter_dev,
256 int *idx)
257{
258 struct dsa_slave_dump_ctx dump = {
259 .dev = dev,
260 .skb = skb,
261 .cb = cb,
262 .idx = *idx,
263 };
264 struct dsa_slave_priv *p = netdev_priv(dev);
265 struct dsa_port *dp = p->dp;
266 struct dsa_switch *ds = dp->ds;
267 int err;
268
269 if (!ds->ops->port_fdb_dump)
270 return -EOPNOTSUPP;
271
272 err = ds->ops->port_fdb_dump(ds, dp->index,
273 dsa_slave_port_fdb_do_dump,
274 &dump);
275 *idx = dump.idx;
276 return err;
277}
278
202static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 279static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
203{ 280{
204 struct dsa_slave_priv *p = netdev_priv(dev); 281 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -287,26 +364,6 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
287 return err; 364 return err;
288} 365}
289 366
290static int dsa_slave_port_obj_dump(struct net_device *dev,
291 struct switchdev_obj *obj,
292 switchdev_obj_dump_cb_t *cb)
293{
294 struct dsa_slave_priv *p = netdev_priv(dev);
295 struct dsa_port *dp = p->dp;
296 int err;
297
298 switch (obj->id) {
299 case SWITCHDEV_OBJ_ID_PORT_FDB:
300 err = dsa_port_fdb_dump(dp, SWITCHDEV_OBJ_PORT_FDB(obj), cb);
301 break;
302 default:
303 err = -EOPNOTSUPP;
304 break;
305 }
306
307 return err;
308}
309
310static int dsa_slave_port_attr_get(struct net_device *dev, 367static int dsa_slave_port_attr_get(struct net_device *dev,
311 struct switchdev_attr *attr) 368 struct switchdev_attr *attr)
312{ 369{
@@ -974,7 +1031,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
974 .ndo_set_mac_address = dsa_slave_set_mac_address, 1031 .ndo_set_mac_address = dsa_slave_set_mac_address,
975 .ndo_fdb_add = dsa_legacy_fdb_add, 1032 .ndo_fdb_add = dsa_legacy_fdb_add,
976 .ndo_fdb_del = dsa_legacy_fdb_del, 1033 .ndo_fdb_del = dsa_legacy_fdb_del,
977 .ndo_fdb_dump = switchdev_port_fdb_dump, 1034 .ndo_fdb_dump = dsa_slave_fdb_dump,
978 .ndo_do_ioctl = dsa_slave_ioctl, 1035 .ndo_do_ioctl = dsa_slave_ioctl,
979 .ndo_get_iflink = dsa_slave_get_iflink, 1036 .ndo_get_iflink = dsa_slave_get_iflink,
980#ifdef CONFIG_NET_POLL_CONTROLLER 1037#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -992,7 +1049,6 @@ static const struct switchdev_ops dsa_slave_switchdev_ops = {
992 .switchdev_port_attr_set = dsa_slave_port_attr_set, 1049 .switchdev_port_attr_set = dsa_slave_port_attr_set,
993 .switchdev_port_obj_add = dsa_slave_port_obj_add, 1050 .switchdev_port_obj_add = dsa_slave_port_obj_add,
994 .switchdev_port_obj_del = dsa_slave_port_obj_del, 1051 .switchdev_port_obj_del = dsa_slave_port_obj_del,
995 .switchdev_port_obj_dump = dsa_slave_port_obj_dump,
996}; 1052};
997 1053
998static struct device_type dsa_type = { 1054static struct device_type dsa_type = {
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 25dc67ef9d37..3d32981b9aa1 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -1009,90 +1009,6 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
1009} 1009}
1010EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); 1010EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
1011 1011
1012struct switchdev_fdb_dump {
1013 struct switchdev_obj_port_fdb fdb;
1014 struct net_device *dev;
1015 struct sk_buff *skb;
1016 struct netlink_callback *cb;
1017 int idx;
1018};
1019
1020static int switchdev_port_fdb_dump_cb(struct switchdev_obj *obj)
1021{
1022 struct switchdev_obj_port_fdb *fdb = SWITCHDEV_OBJ_PORT_FDB(obj);
1023 struct switchdev_fdb_dump *dump =
1024 container_of(fdb, struct switchdev_fdb_dump, fdb);
1025 u32 portid = NETLINK_CB(dump->cb->skb).portid;
1026 u32 seq = dump->cb->nlh->nlmsg_seq;
1027 struct nlmsghdr *nlh;
1028 struct ndmsg *ndm;
1029
1030 if (dump->idx < dump->cb->args[2])
1031 goto skip;
1032
1033 nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
1034 sizeof(*ndm), NLM_F_MULTI);
1035 if (!nlh)
1036 return -EMSGSIZE;
1037
1038 ndm = nlmsg_data(nlh);
1039 ndm->ndm_family = AF_BRIDGE;
1040 ndm->ndm_pad1 = 0;
1041 ndm->ndm_pad2 = 0;
1042 ndm->ndm_flags = NTF_SELF;
1043 ndm->ndm_type = 0;
1044 ndm->ndm_ifindex = dump->dev->ifindex;
1045 ndm->ndm_state = fdb->ndm_state;
1046
1047 if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, fdb->addr))
1048 goto nla_put_failure;
1049
1050 if (fdb->vid && nla_put_u16(dump->skb, NDA_VLAN, fdb->vid))
1051 goto nla_put_failure;
1052
1053 nlmsg_end(dump->skb, nlh);
1054
1055skip:
1056 dump->idx++;
1057 return 0;
1058
1059nla_put_failure:
1060 nlmsg_cancel(dump->skb, nlh);
1061 return -EMSGSIZE;
1062}
1063
1064/**
1065 * switchdev_port_fdb_dump - Dump port FDB (MAC/VLAN) entries
1066 *
1067 * @skb: netlink skb
1068 * @cb: netlink callback
1069 * @dev: port device
1070 * @filter_dev: filter device
1071 * @idx:
1072 *
1073 * Dump FDB entries from switch device.
1074 */
1075int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
1076 struct net_device *dev,
1077 struct net_device *filter_dev, int *idx)
1078{
1079 struct switchdev_fdb_dump dump = {
1080 .fdb.obj.orig_dev = dev,
1081 .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
1082 .dev = dev,
1083 .skb = skb,
1084 .cb = cb,
1085 .idx = *idx,
1086 };
1087 int err;
1088
1089 err = switchdev_port_obj_dump(dev, &dump.fdb.obj,
1090 switchdev_port_fdb_dump_cb);
1091 *idx = dump.idx;
1092 return err;
1093}
1094EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
1095
1096bool switchdev_port_same_parent_id(struct net_device *a, 1012bool switchdev_port_same_parent_id(struct net_device *a,
1097 struct net_device *b) 1013 struct net_device *b)
1098{ 1014{