History

net: dsa: Move FDB dump implementation inside DSA

>From all switchdev devices only DSA requires special FDB dump. This is due to lack of ability for syncing the hardware learned FDBs with the bridge. Due to this it is removed from switchdev and moved inside DSA.

Arkadi Sharshevsky committed 9 years ago

Commit 2bedde11 parent dc0cbff12 files · +112 −204Browse files

Unified · Split

12 files
  1. drivers/net/dsa/b53/b53_common.c +5 −11
  2. drivers/net/dsa/b53/b53_priv.h +1 −2
  3. drivers/net/dsa/microchip/ksz_common.c +6 −14
  4. drivers/net/dsa/mt7530.c +3 −7
  5. drivers/net/dsa/mv88e6xxx/chip.c +12 −26
  6. drivers/net/dsa/qca8k.c +4 −11
  7. include/net/dsa.h +3 −2
  8. include/net/switchdev.h +0 −12
  9. net/dsa/dsa_priv.h +0 −2
  10. net/dsa/port.c +0 −11
  11. net/dsa/slave.c +78 −22
  12. net/switchdev/switchdev.c +0 −84
drivers/net/dsa/b53/b53_common.c+5−11
@@ -1227,8 +1227,7 @@ static void b53_arl_search_rd(struct b53_device *dev, u8 idx, · 1226 unmodified lines
12271227 }
12281228
12291229 static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
1230− struct switchdev_obj_port_fdb *fdb,
1231− switchdev_obj_dump_cb_t *cb)
1230+ dsa_fdb_dump_cb_t *cb, void *data)
12321231 {
12331232 if (!ent->is_valid)
12341233 return 0;
@@ -1236,16 +1235,11 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, · 1 unmodified line
12361235 if (port != ent->port)
12371236 return 0;
12381237
1239− ether_addr_copy(fdb->addr, ent->mac);
1240− fdb->vid = ent->vid;
1241− fdb->ndm_state = ent->is_static ? NUD_NOARP : NUD_REACHABLE;
1242−
1243− return cb(&fdb->obj);
1238+ return cb(ent->mac, ent->vid, ent->is_static, data);
12441239 }
12451240
12461241 int b53_fdb_dump(struct dsa_switch *ds, int port,
1247− struct switchdev_obj_port_fdb *fdb,
1248− switchdev_obj_dump_cb_t *cb)
1242+ dsa_fdb_dump_cb_t *cb, void *data)
12491243 {
12501244 struct b53_device *priv = ds->priv;
12511245 struct b53_arl_entry results[2];
@@ -1263,13 +1257,13 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, · 11 unmodified lines
12631257 return ret;
12641258
12651259 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);
12671261 if (ret)
12681262 return ret;
12691263
12701264 if (priv->num_arl_entries > 2) {
12711265 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);
12731267 if (ret)
12741268 return ret;
12751269
drivers/net/dsa/b53/b53_priv.h+1−2
@@ -398,8 +398,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port, · 397 unmodified lines
398398 int b53_fdb_del(struct dsa_switch *ds, int port,
399399 const unsigned char *addr, u16 vid);
400400 int b53_fdb_dump(struct dsa_switch *ds, int port,
401− struct switchdev_obj_port_fdb *fdb,
402− switchdev_obj_dump_cb_t *cb);
401+ dsa_fdb_dump_cb_t *cb, void *data);
403402 int b53_mirror_add(struct dsa_switch *ds, int port,
404403 struct dsa_mall_mirror_tc_entry *mirror, bool ingress);
405404 void b53_mirror_del(struct dsa_switch *ds, int port,
drivers/net/dsa/microchip/ksz_common.c+6−14
@@ -805,12 +805,11 @@ static void convert_alu(struct alu_struct *alu, u32 *alu_table) · 804 unmodified lines
805805 }
806806
807807 static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
808− struct switchdev_obj_port_fdb *fdb,
809− switchdev_obj_dump_cb_t *cb)
808+ dsa_fdb_dump_cb_t *cb, void *data)
810809 {
811810 struct ksz_device *dev = ds->priv;
812811 int ret = 0;
813− u32 data;
812+ u32 ksz_data;
814813 u32 alu_table[4];
815814 struct alu_struct alu;
816815 int timeout;
@@ -823,8 +822,8 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, · 6 unmodified lines
823822 do {
824823 timeout = 1000;
825824 do {
826− ksz_read32(dev, REG_SW_ALU_CTRL__4, &data);
827− if ((data & ALU_VALID) || !(data & ALU_START))
825+ ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data);
826+ if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START))
828827 break;
829828 usleep_range(1, 10);
830829 } while (timeout-- > 0);
@@ -841,18 +840,11 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, · 10 unmodified lines
841840 convert_alu(&alu, alu_table);
842841
843842 if (alu.port_forward & BIT(port)) {
844− fdb->vid = alu.fid;
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);
843+ ret = cb(alu.mac, alu.fid, alu.is_static, data);
852844 if (ret)
853845 goto exit;
854846 }
855− } while (data & ALU_START);
847+ } while (ksz_data & ALU_START);
856848
857849 exit:
858850
drivers/net/dsa/mt7530.c+3−7
@@ -834,8 +834,7 @@ mt7530_port_fdb_del(struct dsa_switch *ds, int port, · 833 unmodified lines
834834
835835 static int
836836 mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
837− struct switchdev_obj_port_fdb *fdb,
838− switchdev_obj_dump_cb_t *cb)
837+ dsa_fdb_dump_cb_t *cb, void *data)
839838 {
840839 struct mt7530_priv *priv = ds->priv;
841840 struct mt7530_fdb _fdb = { 0 };
@@ -853,11 +852,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port, · 11 unmodified lines
853852 if (rsp & ATC_SRCH_HIT) {
854853 mt7530_fdb_read(priv, &_fdb);
855854 if (_fdb.port_mask & BIT(port)) {
856− ether_addr_copy(fdb->addr, _fdb.mac);
857− fdb->vid = _fdb.vid;
858− fdb->ndm_state = _fdb.noarp ?
859− NUD_NOARP : NUD_REACHABLE;
860− ret = cb(&fdb->obj);
855+ ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp,
856+ data);
861857 if (ret < 0)
862858 break;
863859 }
drivers/net/dsa/mv88e6xxx/chip.c+12−26
@@ -1381,10 +1381,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, · 1380 unmodified lines
13811381
13821382 static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
13831383 u16 fid, u16 vid, int port,
1384− struct switchdev_obj *obj,
1385− switchdev_obj_dump_cb_t *cb)
1384+ dsa_fdb_dump_cb_t *cb, void *data)
13861385 {
13871386 struct mv88e6xxx_atu_entry addr;
1387+ bool is_static;
13881388 int err;
13891389
13901390 addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
@@ -1401,24 +1401,12 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, · 10 unmodified lines
14011401 if (addr.trunk || (addr.portvec & BIT(port)) == 0)
14021402 continue;
14031403
1404− if (obj->id == SWITCHDEV_OBJ_ID_PORT_FDB) {
1405− struct switchdev_obj_port_fdb *fdb;
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− }
1404+ if (!is_unicast_ether_addr(addr.mac))
1405+ continue;
14201406
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);
14221410 if (err)
14231411 return err;
14241412 } while (!is_broadcast_ether_addr(addr.mac));
@@ -1427,8 +1415,7 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, · 2 unmodified lines
14271415 }
14281416
14291417 static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
1430− struct switchdev_obj *obj,
1431− switchdev_obj_dump_cb_t *cb)
1418+ dsa_fdb_dump_cb_t *cb, void *data)
14321419 {
14331420 struct mv88e6xxx_vtu_entry vlan = {
14341421 .vid = chip->info->max_vid,
@@ -1441,7 +1428,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, · 6 unmodified lines
14411428 if (err)
14421429 return err;
14431430
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);
14451432 if (err)
14461433 return err;
14471434
@@ -1455,7 +1442,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, · 7 unmodified lines
14551442 break;
14561443
14571444 err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
1458− obj, cb);
1445+ cb, data);
14591446 if (err)
14601447 return err;
14611448 } while (vlan.vid < chip->info->max_vid);
@@ -1464,14 +1451,13 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, · 2 unmodified lines
14641451 }
14651452
14661453 static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1467− struct switchdev_obj_port_fdb *fdb,
1468− switchdev_obj_dump_cb_t *cb)
1454+ dsa_fdb_dump_cb_t *cb, void *data)
14691455 {
14701456 struct mv88e6xxx_chip *chip = ds->priv;
14711457 int err;
14721458
14731459 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);
14751461 mutex_unlock(&chip->reg_lock);
14761462
14771463 return err;
drivers/net/dsa/qca8k.c+4−11
@@ -801,27 +801,20 @@ qca8k_port_fdb_del(struct dsa_switch *ds, int port, · 800 unmodified lines
801801
802802 static int
803803 qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
804− struct switchdev_obj_port_fdb *fdb,
805− switchdev_obj_dump_cb_t *cb)
804+ dsa_fdb_dump_cb_t *cb, void *data)
806805 {
807806 struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
808807 struct qca8k_fdb _fdb = { 0 };
809808 int cnt = QCA8K_NUM_FDB_RECORDS;
809+ bool is_static;
810810 int ret = 0;
811811
812812 mutex_lock(&priv->reg_mutex);
813813 while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
814814 if (!_fdb.aging)
815815 break;
816−
817− ether_addr_copy(fdb->addr, _fdb.mac);
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);
816+ is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
817+ ret = cb(_fdb.mac, _fdb.vid, is_static, data);
825818 if (ret)
826819 break;
827820 }
include/net/dsa.h+3−2
@@ -272,6 +272,8 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds) · 271 unmodified lines
272272 return ds->rtable[dst->cpu_dp->ds->index];
273273 }
274274
275+typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
276+ bool is_static, void *data);
275277 struct dsa_switch_ops {
276278 /*
277279 * Legacy probing.
@@ -386,8 +388,7 @@ struct dsa_switch_ops { · 108 unmodified lines
386388 int (*port_fdb_del)(struct dsa_switch *ds, int port,
387389 const unsigned char *addr, u16 vid);
388390 int (*port_fdb_dump)(struct dsa_switch *ds, int port,
389− struct switchdev_obj_port_fdb *fdb,
390− switchdev_obj_dump_cb_t *cb);
391+ dsa_fdb_dump_cb_t *cb, void *data);
391392
392393 /*
393394 * Multicast database
include/net/switchdev.h+0−12
@@ -208,9 +208,6 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], · 207 unmodified lines
208208 int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
209209 struct net_device *dev, const unsigned char *addr,
210210 u16 vid);
211−int 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);
214211 void switchdev_port_fwd_mark_set(struct net_device *dev,
215212 struct net_device *group_dev,
216213 bool joining);
@@ -309,15 +306,6 @@ static inline int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], · 92 unmodified lines
309306 return -EOPNOTSUPP;
310307 }
311308
312−static 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−
321309 static inline bool switchdev_port_same_parent_id(struct net_device *a,
322310 struct net_device *b)
323311 {
net/dsa/dsa_priv.h+0−2
@@ -133,8 +133,6 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, · 132 unmodified lines
133133 u16 vid);
134134 int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
135135 u16 vid);
136−int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
137− switchdev_obj_dump_cb_t *cb);
138136 int dsa_port_mdb_add(struct dsa_port *dp,
139137 const struct switchdev_obj_port_mdb *mdb,
140138 struct switchdev_trans *trans);
net/dsa/port.c+0−11
@@ -173,17 +173,6 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, · 172 unmodified lines
173173 return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
174174 }
175175
176−int 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−
187176 int dsa_port_mdb_add(struct dsa_port *dp,
188177 const struct switchdev_obj_port_mdb *mdb,
189178 struct switchdev_trans *trans)
net/dsa/slave.c+78−22
@@ -199,6 +199,83 @@ out: · 198 unmodified lines
199199 return 0;
200200 }
201201
202+struct dsa_slave_dump_ctx {
203+ struct net_device *dev;
204+ struct sk_buff *skb;
205+ struct netlink_callback *cb;
206+ int idx;
207+};
208+
209+static int
210+dsa_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+
244+skip:
245+ dump->idx++;
246+ return 0;
247+
248+nla_put_failure:
249+ nlmsg_cancel(dump->skb, nlh);
250+ return -EMSGSIZE;
251+}
252+
253+static int
254+dsa_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+
202279 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
203280 {
204281 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -287,26 +364,6 @@ static int dsa_slave_port_obj_del(struct net_device *dev, · 82 unmodified lines
287364 return err;
288365 }
289366
290−static 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−
310367 static int dsa_slave_port_attr_get(struct net_device *dev,
311368 struct switchdev_attr *attr)
312369 {
@@ -974,7 +1031,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = { · 661 unmodified lines
9741031 .ndo_set_mac_address = dsa_slave_set_mac_address,
9751032 .ndo_fdb_add = dsa_legacy_fdb_add,
9761033 .ndo_fdb_del = dsa_legacy_fdb_del,
977− .ndo_fdb_dump = switchdev_port_fdb_dump,
1034+ .ndo_fdb_dump = dsa_slave_fdb_dump,
9781035 .ndo_do_ioctl = dsa_slave_ioctl,
9791036 .ndo_get_iflink = dsa_slave_get_iflink,
9801037 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -992,7 +1049,6 @@ static const struct switchdev_ops dsa_slave_switchdev_ops = { · 11 unmodified lines
9921049 .switchdev_port_attr_set = dsa_slave_port_attr_set,
9931050 .switchdev_port_obj_add = dsa_slave_port_obj_add,
9941051 .switchdev_port_obj_del = dsa_slave_port_obj_del,
995− .switchdev_port_obj_dump = dsa_slave_port_obj_dump,
9961052 };
9971053
9981054 static struct device_type dsa_type = {
net/switchdev/switchdev.c+0−84
@@ -1009,90 +1009,6 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], · 1008 unmodified lines
10091009 }
10101010 EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
10111011
1012−struct 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−
1020−static 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−
1055−skip:
1056− dump->idx++;
1057− return 0;
1058−
1059−nla_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− */
1075−int 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−}
1094−EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
1095−
10961012 bool switchdev_port_same_parent_id(struct net_device *a,
10971013 struct net_device *b)
10981014 {