aboutsummaryrefslogtreecommitdiffstats
path: root/net/switchdev/switchdev.c
diff options
context:
space:
mode:
authorSamudrala, Sridhar <sridhar.samudrala@intel.com>2015-05-14 00:55:43 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-17 22:49:09 -0400
commit45d4122ca7cdb3a4b91f392605cd22cfa75f1d99 (patch)
tree5b4524c25f701e345a1526ce9379ea5b3c1beee2 /net/switchdev/switchdev.c
parent5d48ef3e954cae2f237ff8e006322d2f3b672375 (diff)
switchdev: add support for fdb add/del/dump via switchdev_port_obj ops.
- introduce port fdb obj and generic switchdev_port_fdb_add/del/dump() - use switchdev_port_fdb_add/del/dump in rocker/team/bonding ndo ops. - add support for fdb obj in switchdev_port_obj_add/del/dump() - switch rocker to implement fdb ops via switchdev_ops v3: updated to sync with named union changes. Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> Signed-off-by: Scott Feldman <sfeldma@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r--net/switchdev/switchdev.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 0409f9b5bdbc..d4c8cf828240 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -296,6 +296,36 @@ int switchdev_port_obj_del(struct net_device *dev, struct switchdev_obj *obj)
296} 296}
297EXPORT_SYMBOL_GPL(switchdev_port_obj_del); 297EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
298 298
299/**
300 * switchdev_port_obj_dump - Dump port objects
301 *
302 * @dev: port device
303 * @obj: object to dump
304 */
305int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj)
306{
307 const struct switchdev_ops *ops = dev->switchdev_ops;
308 struct net_device *lower_dev;
309 struct list_head *iter;
310 int err = -EOPNOTSUPP;
311
312 if (ops && ops->switchdev_port_obj_dump)
313 return ops->switchdev_port_obj_dump(dev, obj);
314
315 /* Switch device port(s) may be stacked under
316 * bond/team/vlan dev, so recurse down to dump objects on
317 * first port at bottom of stack.
318 */
319
320 netdev_for_each_lower_dev(dev, lower_dev, iter) {
321 err = switchdev_port_obj_dump(lower_dev, obj);
322 break;
323 }
324
325 return err;
326}
327EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
328
299static DEFINE_MUTEX(switchdev_mutex); 329static DEFINE_MUTEX(switchdev_mutex);
300static RAW_NOTIFIER_HEAD(switchdev_notif_chain); 330static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
301 331
@@ -566,6 +596,151 @@ int switchdev_port_bridge_dellink(struct net_device *dev,
566} 596}
567EXPORT_SYMBOL_GPL(switchdev_port_bridge_dellink); 597EXPORT_SYMBOL_GPL(switchdev_port_bridge_dellink);
568 598
599/**
600 * switchdev_port_fdb_add - Add FDB (MAC/VLAN) entry to port
601 *
602 * @ndmsg: netlink hdr
603 * @nlattr: netlink attributes
604 * @dev: port device
605 * @addr: MAC address to add
606 * @vid: VLAN to add
607 *
608 * Add FDB entry to switch device.
609 */
610int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
611 struct net_device *dev, const unsigned char *addr,
612 u16 vid, u16 nlm_flags)
613{
614 struct switchdev_obj obj = {
615 .id = SWITCHDEV_OBJ_PORT_FDB,
616 .u.fdb = {
617 .addr = addr,
618 .vid = vid,
619 },
620 };
621
622 return switchdev_port_obj_add(dev, &obj);
623}
624EXPORT_SYMBOL_GPL(switchdev_port_fdb_add);
625
626/**
627 * switchdev_port_fdb_del - Delete FDB (MAC/VLAN) entry from port
628 *
629 * @ndmsg: netlink hdr
630 * @nlattr: netlink attributes
631 * @dev: port device
632 * @addr: MAC address to delete
633 * @vid: VLAN to delete
634 *
635 * Delete FDB entry from switch device.
636 */
637int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
638 struct net_device *dev, const unsigned char *addr,
639 u16 vid)
640{
641 struct switchdev_obj obj = {
642 .id = SWITCHDEV_OBJ_PORT_FDB,
643 .u.fdb = {
644 .addr = addr,
645 .vid = vid,
646 },
647 };
648
649 return switchdev_port_obj_del(dev, &obj);
650}
651EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
652
653struct switchdev_fdb_dump {
654 struct switchdev_obj obj;
655 struct sk_buff *skb;
656 struct netlink_callback *cb;
657 struct net_device *filter_dev;
658 int idx;
659};
660
661static int switchdev_port_fdb_dump_cb(struct net_device *dev,
662 struct switchdev_obj *obj)
663{
664 struct switchdev_fdb_dump *dump =
665 container_of(obj, struct switchdev_fdb_dump, obj);
666 u32 portid = NETLINK_CB(dump->cb->skb).portid;
667 u32 seq = dump->cb->nlh->nlmsg_seq;
668 struct nlmsghdr *nlh;
669 struct ndmsg *ndm;
670 struct net_device *master = netdev_master_upper_dev_get(dev);
671
672 if (dump->idx < dump->cb->args[0])
673 goto skip;
674
675 if (master && dump->filter_dev != master)
676 goto skip;
677
678 nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
679 sizeof(*ndm), NLM_F_MULTI);
680 if (!nlh)
681 return -EMSGSIZE;
682
683 ndm = nlmsg_data(nlh);
684 ndm->ndm_family = AF_BRIDGE;
685 ndm->ndm_pad1 = 0;
686 ndm->ndm_pad2 = 0;
687 ndm->ndm_flags = NTF_SELF;
688 ndm->ndm_type = 0;
689 ndm->ndm_ifindex = dev->ifindex;
690 ndm->ndm_state = NUD_REACHABLE;
691
692 if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, obj->u.fdb.addr))
693 goto nla_put_failure;
694
695 if (obj->u.fdb.vid && nla_put_u16(dump->skb, NDA_VLAN, obj->u.fdb.vid))
696 goto nla_put_failure;
697
698 nlmsg_end(dump->skb, nlh);
699
700skip:
701 dump->idx++;
702 return 0;
703
704nla_put_failure:
705 nlmsg_cancel(dump->skb, nlh);
706 return -EMSGSIZE;
707}
708
709/**
710 * switchdev_port_fdb_dump - Dump port FDB (MAC/VLAN) entries
711 *
712 * @skb: netlink skb
713 * @cb: netlink callback
714 * @dev: port device
715 * @filter_dev: filter device
716 * @idx:
717 *
718 * Delete FDB entry from switch device.
719 */
720int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
721 struct net_device *dev,
722 struct net_device *filter_dev, int idx)
723{
724 struct switchdev_fdb_dump dump = {
725 .obj = {
726 .id = SWITCHDEV_OBJ_PORT_FDB,
727 .cb = switchdev_port_fdb_dump_cb,
728 },
729 .skb = skb,
730 .cb = cb,
731 .filter_dev = filter_dev,
732 .idx = idx,
733 };
734 int err;
735
736 err = switchdev_port_obj_dump(dev, &dump.obj);
737 if (err)
738 return err;
739
740 return dump.idx;
741}
742EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
743
569static struct net_device *switchdev_get_lowest_dev(struct net_device *dev) 744static struct net_device *switchdev_get_lowest_dev(struct net_device *dev)
570{ 745{
571 const struct switchdev_ops *ops = dev->switchdev_ops; 746 const struct switchdev_ops *ops = dev->switchdev_ops;