aboutsummaryrefslogtreecommitdiffstats
path: root/net/switchdev/switchdev.c
diff options
context:
space:
mode:
authorArkadi Sharshevsky <arkadis@mellanox.com>2017-08-06 09:15:51 -0400
committerDavid S. Miller <davem@davemloft.net>2017-08-07 17:48:48 -0400
commit29ab586c3d83f81c435e269cace9a1619afb5bbd (patch)
treea015ab2c573e384dabc9c43cbae2d17a4f3f14aa /net/switchdev/switchdev.c
parent3a83c2a7a518d4044f7bb73b5b05b59be618e547 (diff)
net: switchdev: Remove bridge bypass support from switchdev
Currently the bridge port flags, vlans, FDBs and MDBs can be offloaded through the bridge code, making the switchdev's SELF bridge bypass implementation to be redundant. This implies several changes: - No need for dump infra in switchdev, DSA's special case is handled privately. - Remove obj_dump from switchdev_ops. - FDBs are removed from obj_add/del routines, due to the fact that they are offloaded through the bridge notification chain. - The switchdev_port_bridge_xx() and switchdev_port_fdb_xx() functions can be removed. Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com> Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Reviewed-by: Ivan Vecera <ivecera@redhat.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r--net/switchdev/switchdev.c435
1 files changed, 0 insertions, 435 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 3d32981b9aa1..0531b41d1f2d 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -343,8 +343,6 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj)
343 switch (obj->id) { 343 switch (obj->id) {
344 case SWITCHDEV_OBJ_ID_PORT_VLAN: 344 case SWITCHDEV_OBJ_ID_PORT_VLAN:
345 return sizeof(struct switchdev_obj_port_vlan); 345 return sizeof(struct switchdev_obj_port_vlan);
346 case SWITCHDEV_OBJ_ID_PORT_FDB:
347 return sizeof(struct switchdev_obj_port_fdb);
348 case SWITCHDEV_OBJ_ID_PORT_MDB: 346 case SWITCHDEV_OBJ_ID_PORT_MDB:
349 return sizeof(struct switchdev_obj_port_mdb); 347 return sizeof(struct switchdev_obj_port_mdb);
350 default: 348 default:
@@ -534,43 +532,6 @@ int switchdev_port_obj_del(struct net_device *dev,
534} 532}
535EXPORT_SYMBOL_GPL(switchdev_port_obj_del); 533EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
536 534
537/**
538 * switchdev_port_obj_dump - Dump port objects
539 *
540 * @dev: port device
541 * @id: object ID
542 * @obj: object to dump
543 * @cb: function to call with a filled object
544 *
545 * rtnl_lock must be held.
546 */
547int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
548 switchdev_obj_dump_cb_t *cb)
549{
550 const struct switchdev_ops *ops = dev->switchdev_ops;
551 struct net_device *lower_dev;
552 struct list_head *iter;
553 int err = -EOPNOTSUPP;
554
555 ASSERT_RTNL();
556
557 if (ops && ops->switchdev_port_obj_dump)
558 return ops->switchdev_port_obj_dump(dev, obj, cb);
559
560 /* Switch device port(s) may be stacked under
561 * bond/team/vlan dev, so recurse down to dump objects on
562 * first port at bottom of stack.
563 */
564
565 netdev_for_each_lower_dev(dev, lower_dev, iter) {
566 err = switchdev_port_obj_dump(lower_dev, obj, cb);
567 break;
568 }
569
570 return err;
571}
572EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
573
574static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain); 535static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
575 536
576/** 537/**
@@ -613,402 +574,6 @@ int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
613} 574}
614EXPORT_SYMBOL_GPL(call_switchdev_notifiers); 575EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
615 576
616struct switchdev_vlan_dump {
617 struct switchdev_obj_port_vlan vlan;
618 struct sk_buff *skb;
619 u32 filter_mask;
620 u16 flags;
621 u16 begin;
622 u16 end;
623};
624
625static int switchdev_port_vlan_dump_put(struct switchdev_vlan_dump *dump)
626{
627 struct bridge_vlan_info vinfo;
628
629 vinfo.flags = dump->flags;
630
631 if (dump->begin == 0 && dump->end == 0) {
632 return 0;
633 } else if (dump->begin == dump->end) {
634 vinfo.vid = dump->begin;
635 if (nla_put(dump->skb, IFLA_BRIDGE_VLAN_INFO,
636 sizeof(vinfo), &vinfo))
637 return -EMSGSIZE;
638 } else {
639 vinfo.vid = dump->begin;
640 vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN;
641 if (nla_put(dump->skb, IFLA_BRIDGE_VLAN_INFO,
642 sizeof(vinfo), &vinfo))
643 return -EMSGSIZE;
644 vinfo.vid = dump->end;
645 vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
646 vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END;
647 if (nla_put(dump->skb, IFLA_BRIDGE_VLAN_INFO,
648 sizeof(vinfo), &vinfo))
649 return -EMSGSIZE;
650 }
651
652 return 0;
653}
654
655static int switchdev_port_vlan_dump_cb(struct switchdev_obj *obj)
656{
657 struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
658 struct switchdev_vlan_dump *dump =
659 container_of(vlan, struct switchdev_vlan_dump, vlan);
660 int err = 0;
661
662 if (vlan->vid_begin > vlan->vid_end)
663 return -EINVAL;
664
665 if (dump->filter_mask & RTEXT_FILTER_BRVLAN) {
666 dump->flags = vlan->flags;
667 for (dump->begin = dump->end = vlan->vid_begin;
668 dump->begin <= vlan->vid_end;
669 dump->begin++, dump->end++) {
670 err = switchdev_port_vlan_dump_put(dump);
671 if (err)
672 return err;
673 }
674 } else if (dump->filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED) {
675 if (dump->begin > vlan->vid_begin &&
676 dump->begin >= vlan->vid_end) {
677 if ((dump->begin - 1) == vlan->vid_end &&
678 dump->flags == vlan->flags) {
679 /* prepend */
680 dump->begin = vlan->vid_begin;
681 } else {
682 err = switchdev_port_vlan_dump_put(dump);
683 dump->flags = vlan->flags;
684 dump->begin = vlan->vid_begin;
685 dump->end = vlan->vid_end;
686 }
687 } else if (dump->end <= vlan->vid_begin &&
688 dump->end < vlan->vid_end) {
689 if ((dump->end + 1) == vlan->vid_begin &&
690 dump->flags == vlan->flags) {
691 /* append */
692 dump->end = vlan->vid_end;
693 } else {
694 err = switchdev_port_vlan_dump_put(dump);
695 dump->flags = vlan->flags;
696 dump->begin = vlan->vid_begin;
697 dump->end = vlan->vid_end;
698 }
699 } else {
700 err = -EINVAL;
701 }
702 }
703
704 return err;
705}
706
707static int switchdev_port_vlan_fill(struct sk_buff *skb, struct net_device *dev,
708 u32 filter_mask)
709{
710 struct switchdev_vlan_dump dump = {
711 .vlan.obj.orig_dev = dev,
712 .vlan.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
713 .skb = skb,
714 .filter_mask = filter_mask,
715 };
716 int err = 0;
717
718 if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
719 (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
720 err = switchdev_port_obj_dump(dev, &dump.vlan.obj,
721 switchdev_port_vlan_dump_cb);
722 if (err)
723 goto err_out;
724 if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
725 /* last one */
726 err = switchdev_port_vlan_dump_put(&dump);
727 }
728
729err_out:
730 return err == -EOPNOTSUPP ? 0 : err;
731}
732
733/**
734 * switchdev_port_bridge_getlink - Get bridge port attributes
735 *
736 * @dev: port device
737 *
738 * Called for SELF on rtnl_bridge_getlink to get bridge port
739 * attributes.
740 */
741int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
742 struct net_device *dev, u32 filter_mask,
743 int nlflags)
744{
745 struct switchdev_attr attr = {
746 .orig_dev = dev,
747 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
748 };
749 u16 mode = BRIDGE_MODE_UNDEF;
750 u32 mask = BR_LEARNING | BR_LEARNING_SYNC | BR_FLOOD;
751 int err;
752
753 if (!netif_is_bridge_port(dev))
754 return -EOPNOTSUPP;
755
756 err = switchdev_port_attr_get(dev, &attr);
757 if (err && err != -EOPNOTSUPP)
758 return err;
759
760 return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode,
761 attr.u.brport_flags, mask, nlflags,
762 filter_mask, switchdev_port_vlan_fill);
763}
764EXPORT_SYMBOL_GPL(switchdev_port_bridge_getlink);
765
766static int switchdev_port_br_setflag(struct net_device *dev,
767 struct nlattr *nlattr,
768 unsigned long brport_flag)
769{
770 struct switchdev_attr attr = {
771 .orig_dev = dev,
772 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
773 };
774 u8 flag = nla_get_u8(nlattr);
775 int err;
776
777 err = switchdev_port_attr_get(dev, &attr);
778 if (err)
779 return err;
780
781 if (flag)
782 attr.u.brport_flags |= brport_flag;
783 else
784 attr.u.brport_flags &= ~brport_flag;
785
786 return switchdev_port_attr_set(dev, &attr);
787}
788
789static const struct nla_policy
790switchdev_port_bridge_policy[IFLA_BRPORT_MAX + 1] = {
791 [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
792 [IFLA_BRPORT_COST] = { .type = NLA_U32 },
793 [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
794 [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
795 [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
796 [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
797 [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 },
798 [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
799 [IFLA_BRPORT_LEARNING_SYNC] = { .type = NLA_U8 },
800 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
801};
802
803static int switchdev_port_br_setlink_protinfo(struct net_device *dev,
804 struct nlattr *protinfo)
805{
806 struct nlattr *attr;
807 int rem;
808 int err;
809
810 err = nla_validate_nested(protinfo, IFLA_BRPORT_MAX,
811 switchdev_port_bridge_policy, NULL);
812 if (err)
813 return err;
814
815 nla_for_each_nested(attr, protinfo, rem) {
816 switch (nla_type(attr)) {
817 case IFLA_BRPORT_LEARNING:
818 err = switchdev_port_br_setflag(dev, attr,
819 BR_LEARNING);
820 break;
821 case IFLA_BRPORT_LEARNING_SYNC:
822 err = switchdev_port_br_setflag(dev, attr,
823 BR_LEARNING_SYNC);
824 break;
825 case IFLA_BRPORT_UNICAST_FLOOD:
826 err = switchdev_port_br_setflag(dev, attr, BR_FLOOD);
827 break;
828 default:
829 err = -EOPNOTSUPP;
830 break;
831 }
832 if (err)
833 return err;
834 }
835
836 return 0;
837}
838
839static int switchdev_port_br_afspec(struct net_device *dev,
840 struct nlattr *afspec,
841 int (*f)(struct net_device *dev,
842 const struct switchdev_obj *obj))
843{
844 struct nlattr *attr;
845 struct bridge_vlan_info *vinfo;
846 struct switchdev_obj_port_vlan vlan = {
847 .obj.orig_dev = dev,
848 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
849 };
850 int rem;
851 int err;
852
853 nla_for_each_nested(attr, afspec, rem) {
854 if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
855 continue;
856 if (nla_len(attr) != sizeof(struct bridge_vlan_info))
857 return -EINVAL;
858 vinfo = nla_data(attr);
859 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
860 return -EINVAL;
861 vlan.flags = vinfo->flags;
862 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
863 if (vlan.vid_begin)
864 return -EINVAL;
865 vlan.vid_begin = vinfo->vid;
866 /* don't allow range of pvids */
867 if (vlan.flags & BRIDGE_VLAN_INFO_PVID)
868 return -EINVAL;
869 } else if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
870 if (!vlan.vid_begin)
871 return -EINVAL;
872 vlan.vid_end = vinfo->vid;
873 if (vlan.vid_end <= vlan.vid_begin)
874 return -EINVAL;
875 err = f(dev, &vlan.obj);
876 if (err)
877 return err;
878 vlan.vid_begin = 0;
879 } else {
880 if (vlan.vid_begin)
881 return -EINVAL;
882 vlan.vid_begin = vinfo->vid;
883 vlan.vid_end = vinfo->vid;
884 err = f(dev, &vlan.obj);
885 if (err)
886 return err;
887 vlan.vid_begin = 0;
888 }
889 }
890
891 return 0;
892}
893
894/**
895 * switchdev_port_bridge_setlink - Set bridge port attributes
896 *
897 * @dev: port device
898 * @nlh: netlink header
899 * @flags: netlink flags
900 *
901 * Called for SELF on rtnl_bridge_setlink to set bridge port
902 * attributes.
903 */
904int switchdev_port_bridge_setlink(struct net_device *dev,
905 struct nlmsghdr *nlh, u16 flags)
906{
907 struct nlattr *protinfo;
908 struct nlattr *afspec;
909 int err = 0;
910
911 if (!netif_is_bridge_port(dev))
912 return -EOPNOTSUPP;
913
914 protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
915 IFLA_PROTINFO);
916 if (protinfo) {
917 err = switchdev_port_br_setlink_protinfo(dev, protinfo);
918 if (err)
919 return err;
920 }
921
922 afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
923 IFLA_AF_SPEC);
924 if (afspec)
925 err = switchdev_port_br_afspec(dev, afspec,
926 switchdev_port_obj_add);
927
928 return err;
929}
930EXPORT_SYMBOL_GPL(switchdev_port_bridge_setlink);
931
932/**
933 * switchdev_port_bridge_dellink - Set bridge port attributes
934 *
935 * @dev: port device
936 * @nlh: netlink header
937 * @flags: netlink flags
938 *
939 * Called for SELF on rtnl_bridge_dellink to set bridge port
940 * attributes.
941 */
942int switchdev_port_bridge_dellink(struct net_device *dev,
943 struct nlmsghdr *nlh, u16 flags)
944{
945 struct nlattr *afspec;
946
947 if (!netif_is_bridge_port(dev))
948 return -EOPNOTSUPP;
949
950 afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
951 IFLA_AF_SPEC);
952 if (afspec)
953 return switchdev_port_br_afspec(dev, afspec,
954 switchdev_port_obj_del);
955
956 return 0;
957}
958EXPORT_SYMBOL_GPL(switchdev_port_bridge_dellink);
959
960/**
961 * switchdev_port_fdb_add - Add FDB (MAC/VLAN) entry to port
962 *
963 * @ndmsg: netlink hdr
964 * @nlattr: netlink attributes
965 * @dev: port device
966 * @addr: MAC address to add
967 * @vid: VLAN to add
968 *
969 * Add FDB entry to switch device.
970 */
971int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
972 struct net_device *dev, const unsigned char *addr,
973 u16 vid, u16 nlm_flags)
974{
975 struct switchdev_obj_port_fdb fdb = {
976 .obj.orig_dev = dev,
977 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
978 .vid = vid,
979 };
980
981 ether_addr_copy(fdb.addr, addr);
982 return switchdev_port_obj_add(dev, &fdb.obj);
983}
984EXPORT_SYMBOL_GPL(switchdev_port_fdb_add);
985
986/**
987 * switchdev_port_fdb_del - Delete FDB (MAC/VLAN) entry from port
988 *
989 * @ndmsg: netlink hdr
990 * @nlattr: netlink attributes
991 * @dev: port device
992 * @addr: MAC address to delete
993 * @vid: VLAN to delete
994 *
995 * Delete FDB entry from switch device.
996 */
997int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
998 struct net_device *dev, const unsigned char *addr,
999 u16 vid)
1000{
1001 struct switchdev_obj_port_fdb fdb = {
1002 .obj.orig_dev = dev,
1003 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
1004 .vid = vid,
1005 };
1006
1007 ether_addr_copy(fdb.addr, addr);
1008 return switchdev_port_obj_del(dev, &fdb.obj);
1009}
1010EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
1011
1012bool switchdev_port_same_parent_id(struct net_device *a, 577bool switchdev_port_same_parent_id(struct net_device *a,
1013 struct net_device *b) 578 struct net_device *b)
1014{ 579{