aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2015-03-26 21:36:37 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-29 16:23:54 -0400
commit339d82626d225e9b876665e4e89b7eb123e96b3d (patch)
tree03ef0d816547cd8423c6c2e89c651926fb228bb8 /net/dsa
parent3f244abb53665bf1ae0a762bb452d33b6648b7df (diff)
net: dsa: Add basic framework to support ndo_fdb functions
Provide callbacks for ndo_fdb_add, ndo_fdb_del, and ndo_fdb_dump. Reviewed-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/slave.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 39555f3f263b..3597724ec3d8 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -201,6 +201,105 @@ out:
201 return 0; 201 return 0;
202} 202}
203 203
204static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
205 struct net_device *dev,
206 const unsigned char *addr, u16 vid, u16 nlm_flags)
207{
208 struct dsa_slave_priv *p = netdev_priv(dev);
209 struct dsa_switch *ds = p->parent;
210 int ret = -EOPNOTSUPP;
211
212 if (ds->drv->fdb_add)
213 ret = ds->drv->fdb_add(ds, p->port, addr, vid);
214
215 return ret;
216}
217
218static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
219 struct net_device *dev,
220 const unsigned char *addr, u16 vid)
221{
222 struct dsa_slave_priv *p = netdev_priv(dev);
223 struct dsa_switch *ds = p->parent;
224 int ret = -EOPNOTSUPP;
225
226 if (ds->drv->fdb_del)
227 ret = ds->drv->fdb_del(ds, p->port, addr, vid);
228
229 return ret;
230}
231
232static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb,
233 const unsigned char *addr, u16 vid,
234 bool is_static,
235 u32 portid, u32 seq, int type,
236 unsigned int flags)
237{
238 struct nlmsghdr *nlh;
239 struct ndmsg *ndm;
240
241 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
242 if (!nlh)
243 return -EMSGSIZE;
244
245 ndm = nlmsg_data(nlh);
246 ndm->ndm_family = AF_BRIDGE;
247 ndm->ndm_pad1 = 0;
248 ndm->ndm_pad2 = 0;
249 ndm->ndm_flags = NTF_EXT_LEARNED;
250 ndm->ndm_type = 0;
251 ndm->ndm_ifindex = dev->ifindex;
252 ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
253
254 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
255 goto nla_put_failure;
256
257 if (vid && nla_put_u16(skb, NDA_VLAN, vid))
258 goto nla_put_failure;
259
260 nlmsg_end(skb, nlh);
261 return 0;
262
263nla_put_failure:
264 nlmsg_cancel(skb, nlh);
265 return -EMSGSIZE;
266}
267
268/* Dump information about entries, in response to GETNEIGH */
269static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
270 struct net_device *dev,
271 struct net_device *filter_dev, int idx)
272{
273 struct dsa_slave_priv *p = netdev_priv(dev);
274 struct dsa_switch *ds = p->parent;
275 unsigned char addr[ETH_ALEN] = { 0 };
276 int ret;
277
278 if (!ds->drv->fdb_getnext)
279 return -EOPNOTSUPP;
280
281 for (; ; idx++) {
282 bool is_static;
283
284 ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static);
285 if (ret < 0)
286 break;
287
288 if (idx < cb->args[0])
289 continue;
290
291 ret = dsa_slave_fill_info(dev, skb, addr, 0,
292 is_static,
293 NETLINK_CB(cb->skb).portid,
294 cb->nlh->nlmsg_seq,
295 RTM_NEWNEIGH, NLM_F_MULTI);
296 if (ret < 0)
297 break;
298 }
299
300 return idx;
301}
302
204static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 303static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
205{ 304{
206 struct dsa_slave_priv *p = netdev_priv(dev); 305 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -572,6 +671,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
572 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 671 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
573 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 672 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
574 .ndo_set_mac_address = dsa_slave_set_mac_address, 673 .ndo_set_mac_address = dsa_slave_set_mac_address,
674 .ndo_fdb_add = dsa_slave_fdb_add,
675 .ndo_fdb_del = dsa_slave_fdb_del,
676 .ndo_fdb_dump = dsa_slave_fdb_dump,
575 .ndo_do_ioctl = dsa_slave_ioctl, 677 .ndo_do_ioctl = dsa_slave_ioctl,
576}; 678};
577 679