aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2015-08-10 09:09:53 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-11 15:03:19 -0400
commitba14d9eb1999cad5b810f1fd97d1cb2d3f00869e (patch)
treebea9ab8be2cabcd21272cf1afc6f2cfe52852c9b /net/dsa
parentce80e7bc57e25062c361de8fb6444129a63bac6d (diff)
net: dsa: add support for switchdev FDB objects
Implement the switchdev_port_obj_{add,del,dump} functions in DSA to support the SWITCHDEV_OBJ_PORT_FDB objects. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/slave.c142
1 files changed, 81 insertions, 61 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 3d341b694ecf..276758406065 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -200,74 +200,38 @@ out:
200 return 0; 200 return 0;
201} 201}
202 202
203static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 203static int dsa_slave_port_fdb_add(struct net_device *dev,
204 struct net_device *dev, 204 struct switchdev_obj *obj)
205 const unsigned char *addr, u16 vid, u16 nlm_flags)
206{ 205{
206 struct switchdev_obj_fdb *fdb = &obj->u.fdb;
207 struct dsa_slave_priv *p = netdev_priv(dev); 207 struct dsa_slave_priv *p = netdev_priv(dev);
208 struct dsa_switch *ds = p->parent; 208 struct dsa_switch *ds = p->parent;
209 int ret = -EOPNOTSUPP; 209 int ret = -EOPNOTSUPP;
210 210
211 if (ds->drv->port_fdb_add) 211 if (obj->trans == SWITCHDEV_TRANS_PREPARE)
212 ret = ds->drv->port_fdb_add(ds, p->port, addr, vid); 212 ret = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
213 else if (obj->trans == SWITCHDEV_TRANS_COMMIT)
214 ret = ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
213 215
214 return ret; 216 return ret;
215} 217}
216 218
217static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 219static int dsa_slave_port_fdb_del(struct net_device *dev,
218 struct net_device *dev, 220 struct switchdev_obj *obj)
219 const unsigned char *addr, u16 vid)
220{ 221{
222 struct switchdev_obj_fdb *fdb = &obj->u.fdb;
221 struct dsa_slave_priv *p = netdev_priv(dev); 223 struct dsa_slave_priv *p = netdev_priv(dev);
222 struct dsa_switch *ds = p->parent; 224 struct dsa_switch *ds = p->parent;
223 int ret = -EOPNOTSUPP; 225 int ret = -EOPNOTSUPP;
224 226
225 if (ds->drv->port_fdb_del) 227 if (ds->drv->port_fdb_del)
226 ret = ds->drv->port_fdb_del(ds, p->port, addr, vid); 228 ret = ds->drv->port_fdb_del(ds, p->port, fdb->addr, fdb->vid);
227 229
228 return ret; 230 return ret;
229} 231}
230 232
231static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb, 233static int dsa_slave_port_fdb_dump(struct net_device *dev,
232 const unsigned char *addr, u16 vid, 234 struct switchdev_obj *obj)
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
262nla_put_failure:
263 nlmsg_cancel(skb, nlh);
264 return -EMSGSIZE;
265}
266
267/* Dump information about entries, in response to GETNEIGH */
268static 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{ 235{
272 struct dsa_slave_priv *p = netdev_priv(dev); 236 struct dsa_slave_priv *p = netdev_priv(dev);
273 struct dsa_switch *ds = p->parent; 237 struct dsa_switch *ds = p->parent;
@@ -278,7 +242,7 @@ static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
278 if (!ds->drv->port_fdb_getnext) 242 if (!ds->drv->port_fdb_getnext)
279 return -EOPNOTSUPP; 243 return -EOPNOTSUPP;
280 244
281 for (; ; idx++) { 245 for (;;) {
282 bool is_static; 246 bool is_static;
283 247
284 ret = ds->drv->port_fdb_getnext(ds, p->port, addr, &vid, 248 ret = ds->drv->port_fdb_getnext(ds, p->port, addr, &vid,
@@ -286,19 +250,16 @@ static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
286 if (ret < 0) 250 if (ret < 0)
287 break; 251 break;
288 252
289 if (idx < cb->args[0]) 253 obj->u.fdb.addr = addr;
290 continue; 254 obj->u.fdb.vid = vid;
255 obj->u.fdb.ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
291 256
292 ret = dsa_slave_fill_info(dev, skb, addr, vid, 257 ret = obj->cb(dev, obj);
293 is_static,
294 NETLINK_CB(cb->skb).portid,
295 cb->nlh->nlmsg_seq,
296 RTM_NEWNEIGH, NLM_F_MULTI);
297 if (ret < 0) 258 if (ret < 0)
298 break; 259 break;
299 } 260 }
300 261
301 return idx; 262 return ret == -ENOENT ? 0 : ret;
302} 263}
303 264
304static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 265static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -366,6 +327,62 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
366 return ret; 327 return ret;
367} 328}
368 329
330static int dsa_slave_port_obj_add(struct net_device *dev,
331 struct switchdev_obj *obj)
332{
333 int err;
334
335 /* For the prepare phase, ensure the full set of changes is feasable in
336 * one go in order to signal a failure properly. If an operation is not
337 * supported, return -EOPNOTSUPP.
338 */
339
340 switch (obj->id) {
341 case SWITCHDEV_OBJ_PORT_FDB:
342 err = dsa_slave_port_fdb_add(dev, obj);
343 break;
344 default:
345 err = -EOPNOTSUPP;
346 break;
347 }
348
349 return err;
350}
351
352static int dsa_slave_port_obj_del(struct net_device *dev,
353 struct switchdev_obj *obj)
354{
355 int err;
356
357 switch (obj->id) {
358 case SWITCHDEV_OBJ_PORT_FDB:
359 err = dsa_slave_port_fdb_del(dev, obj);
360 break;
361 default:
362 err = -EOPNOTSUPP;
363 break;
364 }
365
366 return err;
367}
368
369static int dsa_slave_port_obj_dump(struct net_device *dev,
370 struct switchdev_obj *obj)
371{
372 int err;
373
374 switch (obj->id) {
375 case SWITCHDEV_OBJ_PORT_FDB:
376 err = dsa_slave_port_fdb_dump(dev, obj);
377 break;
378 default:
379 err = -EOPNOTSUPP;
380 break;
381 }
382
383 return err;
384}
385
369static int dsa_slave_bridge_port_join(struct net_device *dev, 386static int dsa_slave_bridge_port_join(struct net_device *dev,
370 struct net_device *br) 387 struct net_device *br)
371{ 388{
@@ -767,9 +784,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
767 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 784 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
768 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 785 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
769 .ndo_set_mac_address = dsa_slave_set_mac_address, 786 .ndo_set_mac_address = dsa_slave_set_mac_address,
770 .ndo_fdb_add = dsa_slave_fdb_add, 787 .ndo_fdb_add = switchdev_port_fdb_add,
771 .ndo_fdb_del = dsa_slave_fdb_del, 788 .ndo_fdb_del = switchdev_port_fdb_del,
772 .ndo_fdb_dump = dsa_slave_fdb_dump, 789 .ndo_fdb_dump = switchdev_port_fdb_dump,
773 .ndo_do_ioctl = dsa_slave_ioctl, 790 .ndo_do_ioctl = dsa_slave_ioctl,
774 .ndo_get_iflink = dsa_slave_get_iflink, 791 .ndo_get_iflink = dsa_slave_get_iflink,
775#ifdef CONFIG_NET_POLL_CONTROLLER 792#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -782,6 +799,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
782static const struct switchdev_ops dsa_slave_switchdev_ops = { 799static const struct switchdev_ops dsa_slave_switchdev_ops = {
783 .switchdev_port_attr_get = dsa_slave_port_attr_get, 800 .switchdev_port_attr_get = dsa_slave_port_attr_get,
784 .switchdev_port_attr_set = dsa_slave_port_attr_set, 801 .switchdev_port_attr_set = dsa_slave_port_attr_set,
802 .switchdev_port_obj_add = dsa_slave_port_obj_add,
803 .switchdev_port_obj_del = dsa_slave_port_obj_del,
804 .switchdev_port_obj_dump = dsa_slave_port_obj_dump,
785}; 805};
786 806
787static void dsa_slave_adjust_link(struct net_device *dev) 807static void dsa_slave_adjust_link(struct net_device *dev)