Skip to content

Commit 55045dd

Browse files
viviendavem330
authored andcommitted
net: dsa: add support for switchdev FDB objects
Remove the fdb_{add,del,getnext} function pointer in favor of new port_fdb_{add,del,getnext}. Implement the switchdev_port_obj_{add,del,dump} functions in DSA to support the SWITCHDEV_OBJ_PORT_FDB objects. Signed-off-by: Vivien Didelot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8902482 commit 55045dd

File tree

4 files changed

+126
-114
lines changed

4 files changed

+126
-114
lines changed

drivers/net/dsa/mv88e6171.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
116116
.port_join_bridge = mv88e6xxx_join_bridge,
117117
.port_leave_bridge = mv88e6xxx_leave_bridge,
118118
.port_stp_update = mv88e6xxx_port_stp_update,
119-
.fdb_add = mv88e6xxx_port_fdb_add,
120-
.fdb_del = mv88e6xxx_port_fdb_del,
121-
.fdb_getnext = mv88e6xxx_port_fdb_getnext,
122119
};
123120

124121
MODULE_ALIAS("platform:mv88e6171");

drivers/net/dsa/mv88e6352.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
341341
.port_join_bridge = mv88e6xxx_join_bridge,
342342
.port_leave_bridge = mv88e6xxx_leave_bridge,
343343
.port_stp_update = mv88e6xxx_port_stp_update,
344-
.fdb_add = mv88e6xxx_port_fdb_add,
345-
.fdb_del = mv88e6xxx_port_fdb_del,
346-
.fdb_getnext = mv88e6xxx_port_fdb_getnext,
347344
};
348345

349346
MODULE_ALIAS("platform:mv88e6172");

include/net/dsa.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,16 @@ struct dsa_switch_driver {
296296
u32 br_port_mask);
297297
int (*port_stp_update)(struct dsa_switch *ds, int port,
298298
u8 state);
299-
int (*fdb_add)(struct dsa_switch *ds, int port,
300-
const unsigned char *addr, u16 vid);
301-
int (*fdb_del)(struct dsa_switch *ds, int port,
302-
const unsigned char *addr, u16 vid);
303-
int (*fdb_getnext)(struct dsa_switch *ds, int port,
304-
unsigned char *addr, bool *is_static);
299+
300+
/*
301+
* Forwarding database
302+
*/
303+
int (*port_fdb_add)(struct dsa_switch *ds, int port, u16 vid,
304+
const u8 addr[ETH_ALEN]);
305+
int (*port_fdb_del)(struct dsa_switch *ds, int port, u16 vid,
306+
const u8 addr[ETH_ALEN]);
307+
int (*port_fdb_getnext)(struct dsa_switch *ds, int port, u16 *vid,
308+
u8 addr[ETH_ALEN], bool *is_static);
305309
};
306310

307311
void register_switch_driver(struct dsa_switch_driver *type);

net/dsa/slave.c

Lines changed: 116 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <net/switchdev.h>
2020
#include <linux/if_bridge.h>
2121
#include <linux/netpoll.h>
22+
#include <linux/if_vlan.h>
2223
#include "dsa_priv.h"
2324

2425
/* slave mii_bus handling ***************************************************/
@@ -200,105 +201,6 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
200201
return 0;
201202
}
202203

203-
static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
204-
struct net_device *dev,
205-
const unsigned char *addr, u16 vid, u16 nlm_flags)
206-
{
207-
struct dsa_slave_priv *p = netdev_priv(dev);
208-
struct dsa_switch *ds = p->parent;
209-
int ret = -EOPNOTSUPP;
210-
211-
if (ds->drv->fdb_add)
212-
ret = ds->drv->fdb_add(ds, p->port, addr, vid);
213-
214-
return ret;
215-
}
216-
217-
static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
218-
struct net_device *dev,
219-
const unsigned char *addr, u16 vid)
220-
{
221-
struct dsa_slave_priv *p = netdev_priv(dev);
222-
struct dsa_switch *ds = p->parent;
223-
int ret = -EOPNOTSUPP;
224-
225-
if (ds->drv->fdb_del)
226-
ret = ds->drv->fdb_del(ds, p->port, addr, vid);
227-
228-
return ret;
229-
}
230-
231-
static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb,
232-
const unsigned char *addr, u16 vid,
233-
bool is_static,
234-
u32 portid, u32 seq, int type,
235-
unsigned int flags)
236-
{
237-
struct nlmsghdr *nlh;
238-
struct ndmsg *ndm;
239-
240-
nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
241-
if (!nlh)
242-
return -EMSGSIZE;
243-
244-
ndm = nlmsg_data(nlh);
245-
ndm->ndm_family = AF_BRIDGE;
246-
ndm->ndm_pad1 = 0;
247-
ndm->ndm_pad2 = 0;
248-
ndm->ndm_flags = NTF_EXT_LEARNED;
249-
ndm->ndm_type = 0;
250-
ndm->ndm_ifindex = dev->ifindex;
251-
ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
252-
253-
if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
254-
goto nla_put_failure;
255-
256-
if (vid && nla_put_u16(skb, NDA_VLAN, vid))
257-
goto nla_put_failure;
258-
259-
nlmsg_end(skb, nlh);
260-
return 0;
261-
262-
nla_put_failure:
263-
nlmsg_cancel(skb, nlh);
264-
return -EMSGSIZE;
265-
}
266-
267-
/* Dump information about entries, in response to GETNEIGH */
268-
static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
269-
struct net_device *dev,
270-
struct net_device *filter_dev, int idx)
271-
{
272-
struct dsa_slave_priv *p = netdev_priv(dev);
273-
struct dsa_switch *ds = p->parent;
274-
unsigned char addr[ETH_ALEN] = { 0 };
275-
int ret;
276-
277-
if (!ds->drv->fdb_getnext)
278-
return -EOPNOTSUPP;
279-
280-
for (; ; idx++) {
281-
bool is_static;
282-
283-
ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static);
284-
if (ret < 0)
285-
break;
286-
287-
if (idx < cb->args[0])
288-
continue;
289-
290-
ret = dsa_slave_fill_info(dev, skb, addr, 0,
291-
is_static,
292-
NETLINK_CB(cb->skb).portid,
293-
cb->nlh->nlmsg_seq,
294-
RTM_NEWNEIGH, NLM_F_MULTI);
295-
if (ret < 0)
296-
break;
297-
}
298-
299-
return idx;
300-
}
301-
302204
static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
303205
{
304206
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -364,6 +266,115 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
364266
return ret;
365267
}
366268

269+
static int dsa_slave_port_fdb_add(struct net_device *dev,
270+
struct switchdev_obj *obj)
271+
{
272+
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
273+
struct dsa_slave_priv *p = netdev_priv(dev);
274+
struct dsa_switch *ds = p->parent;
275+
int err;
276+
277+
if (obj->trans == SWITCHDEV_TRANS_PREPARE)
278+
err = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
279+
else if (obj->trans == SWITCHDEV_TRANS_COMMIT)
280+
err = ds->drv->port_fdb_add(ds, p->port, fdb->vid, fdb->addr);
281+
else
282+
err = -EOPNOTSUPP;
283+
284+
return err;
285+
}
286+
287+
static int dsa_slave_port_fdb_del(struct net_device *dev,
288+
struct switchdev_obj *obj)
289+
{
290+
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
291+
struct dsa_slave_priv *p = netdev_priv(dev);
292+
struct dsa_switch *ds = p->parent;
293+
294+
if (!ds->drv->port_fdb_del)
295+
return -EOPNOTSUPP;
296+
297+
return ds->drv->port_fdb_del(ds, p->port, fdb->vid, fdb->addr);
298+
}
299+
300+
static int dsa_slave_port_fdb_dump(struct net_device *dev,
301+
struct switchdev_obj *obj)
302+
{
303+
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
304+
struct dsa_slave_priv *p = netdev_priv(dev);
305+
struct dsa_switch *ds = p->parent;
306+
int err;
307+
308+
if (!ds->drv->port_fdb_getnext)
309+
return -EOPNOTSUPP;
310+
311+
memset(fdb, 0, sizeof(*fdb));
312+
313+
for (;;) {
314+
err = ds->drv->port_fdb_getnext(ds, p->port, &fdb->vid,
315+
fdb->addr, &fdb->is_static);
316+
if (err)
317+
break;
318+
319+
err = obj->cb(dev, obj);
320+
if (err)
321+
break;
322+
}
323+
324+
return err == -ENOENT ? 0 : err;
325+
}
326+
327+
static int dsa_slave_port_obj_add(struct net_device *dev,
328+
struct switchdev_obj *obj)
329+
{
330+
int err;
331+
332+
switch (obj->id) {
333+
case SWITCHDEV_OBJ_PORT_FDB:
334+
err = dsa_slave_port_fdb_add(dev, obj);
335+
break;
336+
default:
337+
err = -EOPNOTSUPP;
338+
break;
339+
}
340+
341+
return err;
342+
}
343+
344+
static int dsa_slave_port_obj_del(struct net_device *dev,
345+
struct switchdev_obj *obj)
346+
{
347+
int err;
348+
349+
switch (obj->id) {
350+
case SWITCHDEV_OBJ_PORT_FDB:
351+
err = dsa_slave_port_fdb_del(dev, obj);
352+
break;
353+
default:
354+
err = -EOPNOTSUPP;
355+
break;
356+
}
357+
358+
return err;
359+
}
360+
361+
static int dsa_slave_port_obj_dump(struct net_device *dev,
362+
struct switchdev_obj *obj)
363+
{
364+
int err;
365+
366+
switch (obj->id) {
367+
case SWITCHDEV_OBJ_PORT_FDB:
368+
err = dsa_slave_port_fdb_dump(dev, obj);
369+
break;
370+
default:
371+
err = -EOPNOTSUPP;
372+
break;
373+
}
374+
375+
return err;
376+
}
377+
367378
static int dsa_slave_bridge_port_join(struct net_device *dev,
368379
struct net_device *br)
369380
{
@@ -765,9 +776,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
765776
.ndo_change_rx_flags = dsa_slave_change_rx_flags,
766777
.ndo_set_rx_mode = dsa_slave_set_rx_mode,
767778
.ndo_set_mac_address = dsa_slave_set_mac_address,
768-
.ndo_fdb_add = dsa_slave_fdb_add,
769-
.ndo_fdb_del = dsa_slave_fdb_del,
770-
.ndo_fdb_dump = dsa_slave_fdb_dump,
779+
.ndo_fdb_add = switchdev_port_fdb_add,
780+
.ndo_fdb_del = switchdev_port_fdb_del,
781+
.ndo_fdb_dump = switchdev_port_fdb_dump,
771782
.ndo_do_ioctl = dsa_slave_ioctl,
772783
.ndo_get_iflink = dsa_slave_get_iflink,
773784
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -780,6 +791,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
780791
static const struct switchdev_ops dsa_slave_switchdev_ops = {
781792
.switchdev_port_attr_get = dsa_slave_port_attr_get,
782793
.switchdev_port_attr_set = dsa_slave_port_attr_set,
794+
.switchdev_port_obj_add = dsa_slave_port_obj_add,
795+
.switchdev_port_obj_del = dsa_slave_port_obj_del,
796+
.switchdev_port_obj_dump = dsa_slave_port_obj_dump,
783797
};
784798

785799
static void dsa_slave_adjust_link(struct net_device *dev)

0 commit comments

Comments
 (0)