diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 341 |
1 files changed, 211 insertions, 130 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 430c02267d7e..5e12462a9d5e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/uaccess.h> | 59 | #include <linux/uaccess.h> |
60 | #include <linux/errno.h> | 60 | #include <linux/errno.h> |
61 | #include <linux/netdevice.h> | 61 | #include <linux/netdevice.h> |
62 | #include <linux/netpoll.h> | ||
62 | #include <linux/inetdevice.h> | 63 | #include <linux/inetdevice.h> |
63 | #include <linux/igmp.h> | 64 | #include <linux/igmp.h> |
64 | #include <linux/etherdevice.h> | 65 | #include <linux/etherdevice.h> |
@@ -430,7 +431,18 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, | |||
430 | } | 431 | } |
431 | 432 | ||
432 | skb->priority = 1; | 433 | skb->priority = 1; |
433 | dev_queue_xmit(skb); | 434 | #ifdef CONFIG_NET_POLL_CONTROLLER |
435 | if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
436 | struct netpoll *np = bond->dev->npinfo->netpoll; | ||
437 | slave_dev->npinfo = bond->dev->npinfo; | ||
438 | np->real_dev = np->dev = skb->dev; | ||
439 | slave_dev->priv_flags |= IFF_IN_NETPOLL; | ||
440 | netpoll_send_skb(np, skb); | ||
441 | slave_dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
442 | np->dev = bond->dev; | ||
443 | } else | ||
444 | #endif | ||
445 | dev_queue_xmit(skb); | ||
434 | 446 | ||
435 | return 0; | 447 | return 0; |
436 | } | 448 | } |
@@ -762,32 +774,6 @@ static int bond_check_dev_link(struct bonding *bond, | |||
762 | /*----------------------------- Multicast list ------------------------------*/ | 774 | /*----------------------------- Multicast list ------------------------------*/ |
763 | 775 | ||
764 | /* | 776 | /* |
765 | * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise | ||
766 | */ | ||
767 | static inline int bond_is_dmi_same(const struct dev_mc_list *dmi1, | ||
768 | const struct dev_mc_list *dmi2) | ||
769 | { | ||
770 | return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 && | ||
771 | dmi1->dmi_addrlen == dmi2->dmi_addrlen; | ||
772 | } | ||
773 | |||
774 | /* | ||
775 | * returns dmi entry if found, NULL otherwise | ||
776 | */ | ||
777 | static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, | ||
778 | struct dev_mc_list *mc_list) | ||
779 | { | ||
780 | struct dev_mc_list *idmi; | ||
781 | |||
782 | for (idmi = mc_list; idmi; idmi = idmi->next) { | ||
783 | if (bond_is_dmi_same(dmi, idmi)) | ||
784 | return idmi; | ||
785 | } | ||
786 | |||
787 | return NULL; | ||
788 | } | ||
789 | |||
790 | /* | ||
791 | * Push the promiscuity flag down to appropriate slaves | 777 | * Push the promiscuity flag down to appropriate slaves |
792 | */ | 778 | */ |
793 | static int bond_set_promiscuity(struct bonding *bond, int inc) | 779 | static int bond_set_promiscuity(struct bonding *bond, int inc) |
@@ -839,18 +825,18 @@ static int bond_set_allmulti(struct bonding *bond, int inc) | |||
839 | * Add a Multicast address to slaves | 825 | * Add a Multicast address to slaves |
840 | * according to mode | 826 | * according to mode |
841 | */ | 827 | */ |
842 | static void bond_mc_add(struct bonding *bond, void *addr, int alen) | 828 | static void bond_mc_add(struct bonding *bond, void *addr) |
843 | { | 829 | { |
844 | if (USES_PRIMARY(bond->params.mode)) { | 830 | if (USES_PRIMARY(bond->params.mode)) { |
845 | /* write lock already acquired */ | 831 | /* write lock already acquired */ |
846 | if (bond->curr_active_slave) | 832 | if (bond->curr_active_slave) |
847 | dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); | 833 | dev_mc_add(bond->curr_active_slave->dev, addr); |
848 | } else { | 834 | } else { |
849 | struct slave *slave; | 835 | struct slave *slave; |
850 | int i; | 836 | int i; |
851 | 837 | ||
852 | bond_for_each_slave(bond, slave, i) | 838 | bond_for_each_slave(bond, slave, i) |
853 | dev_mc_add(slave->dev, addr, alen, 0); | 839 | dev_mc_add(slave->dev, addr); |
854 | } | 840 | } |
855 | } | 841 | } |
856 | 842 | ||
@@ -858,18 +844,17 @@ static void bond_mc_add(struct bonding *bond, void *addr, int alen) | |||
858 | * Remove a multicast address from slave | 844 | * Remove a multicast address from slave |
859 | * according to mode | 845 | * according to mode |
860 | */ | 846 | */ |
861 | static void bond_mc_delete(struct bonding *bond, void *addr, int alen) | 847 | static void bond_mc_del(struct bonding *bond, void *addr) |
862 | { | 848 | { |
863 | if (USES_PRIMARY(bond->params.mode)) { | 849 | if (USES_PRIMARY(bond->params.mode)) { |
864 | /* write lock already acquired */ | 850 | /* write lock already acquired */ |
865 | if (bond->curr_active_slave) | 851 | if (bond->curr_active_slave) |
866 | dev_mc_delete(bond->curr_active_slave->dev, addr, | 852 | dev_mc_del(bond->curr_active_slave->dev, addr); |
867 | alen, 0); | ||
868 | } else { | 853 | } else { |
869 | struct slave *slave; | 854 | struct slave *slave; |
870 | int i; | 855 | int i; |
871 | bond_for_each_slave(bond, slave, i) { | 856 | bond_for_each_slave(bond, slave, i) { |
872 | dev_mc_delete(slave->dev, addr, alen, 0); | 857 | dev_mc_del(slave->dev, addr); |
873 | } | 858 | } |
874 | } | 859 | } |
875 | } | 860 | } |
@@ -896,66 +881,22 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) | |||
896 | } | 881 | } |
897 | 882 | ||
898 | /* | 883 | /* |
899 | * Totally destroys the mc_list in bond | ||
900 | */ | ||
901 | static void bond_mc_list_destroy(struct bonding *bond) | ||
902 | { | ||
903 | struct dev_mc_list *dmi; | ||
904 | |||
905 | dmi = bond->mc_list; | ||
906 | while (dmi) { | ||
907 | bond->mc_list = dmi->next; | ||
908 | kfree(dmi); | ||
909 | dmi = bond->mc_list; | ||
910 | } | ||
911 | |||
912 | bond->mc_list = NULL; | ||
913 | } | ||
914 | |||
915 | /* | ||
916 | * Copy all the Multicast addresses from src to the bonding device dst | ||
917 | */ | ||
918 | static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, | ||
919 | gfp_t gfp_flag) | ||
920 | { | ||
921 | struct dev_mc_list *dmi, *new_dmi; | ||
922 | |||
923 | for (dmi = mc_list; dmi; dmi = dmi->next) { | ||
924 | new_dmi = kmalloc(sizeof(struct dev_mc_list), gfp_flag); | ||
925 | |||
926 | if (!new_dmi) { | ||
927 | /* FIXME: Potential memory leak !!! */ | ||
928 | return -ENOMEM; | ||
929 | } | ||
930 | |||
931 | new_dmi->next = bond->mc_list; | ||
932 | bond->mc_list = new_dmi; | ||
933 | new_dmi->dmi_addrlen = dmi->dmi_addrlen; | ||
934 | memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); | ||
935 | new_dmi->dmi_users = dmi->dmi_users; | ||
936 | new_dmi->dmi_gusers = dmi->dmi_gusers; | ||
937 | } | ||
938 | |||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * flush all members of flush->mc_list from device dev->mc_list | 884 | * flush all members of flush->mc_list from device dev->mc_list |
944 | */ | 885 | */ |
945 | static void bond_mc_list_flush(struct net_device *bond_dev, | 886 | static void bond_mc_list_flush(struct net_device *bond_dev, |
946 | struct net_device *slave_dev) | 887 | struct net_device *slave_dev) |
947 | { | 888 | { |
948 | struct bonding *bond = netdev_priv(bond_dev); | 889 | struct bonding *bond = netdev_priv(bond_dev); |
949 | struct dev_mc_list *dmi; | 890 | struct netdev_hw_addr *ha; |
950 | 891 | ||
951 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) | 892 | netdev_for_each_mc_addr(ha, bond_dev) |
952 | dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | 893 | dev_mc_del(slave_dev, ha->addr); |
953 | 894 | ||
954 | if (bond->params.mode == BOND_MODE_8023AD) { | 895 | if (bond->params.mode == BOND_MODE_8023AD) { |
955 | /* del lacpdu mc addr from mc list */ | 896 | /* del lacpdu mc addr from mc list */ |
956 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; | 897 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; |
957 | 898 | ||
958 | dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0); | 899 | dev_mc_del(slave_dev, lacpdu_multicast); |
959 | } | 900 | } |
960 | } | 901 | } |
961 | 902 | ||
@@ -969,7 +910,7 @@ static void bond_mc_list_flush(struct net_device *bond_dev, | |||
969 | static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | 910 | static void bond_mc_swap(struct bonding *bond, struct slave *new_active, |
970 | struct slave *old_active) | 911 | struct slave *old_active) |
971 | { | 912 | { |
972 | struct dev_mc_list *dmi; | 913 | struct netdev_hw_addr *ha; |
973 | 914 | ||
974 | if (!USES_PRIMARY(bond->params.mode)) | 915 | if (!USES_PRIMARY(bond->params.mode)) |
975 | /* nothing to do - mc list is already up-to-date on | 916 | /* nothing to do - mc list is already up-to-date on |
@@ -984,9 +925,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
984 | if (bond->dev->flags & IFF_ALLMULTI) | 925 | if (bond->dev->flags & IFF_ALLMULTI) |
985 | dev_set_allmulti(old_active->dev, -1); | 926 | dev_set_allmulti(old_active->dev, -1); |
986 | 927 | ||
987 | for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) | 928 | netdev_for_each_mc_addr(ha, bond->dev) |
988 | dev_mc_delete(old_active->dev, dmi->dmi_addr, | 929 | dev_mc_del(old_active->dev, ha->addr); |
989 | dmi->dmi_addrlen, 0); | ||
990 | } | 930 | } |
991 | 931 | ||
992 | if (new_active) { | 932 | if (new_active) { |
@@ -997,9 +937,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
997 | if (bond->dev->flags & IFF_ALLMULTI) | 937 | if (bond->dev->flags & IFF_ALLMULTI) |
998 | dev_set_allmulti(new_active->dev, 1); | 938 | dev_set_allmulti(new_active->dev, 1); |
999 | 939 | ||
1000 | for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) | 940 | netdev_for_each_mc_addr(ha, bond->dev) |
1001 | dev_mc_add(new_active->dev, dmi->dmi_addr, | 941 | dev_mc_add(new_active->dev, ha->addr); |
1002 | dmi->dmi_addrlen, 0); | ||
1003 | bond_resend_igmp_join_requests(bond); | 942 | bond_resend_igmp_join_requests(bond); |
1004 | } | 943 | } |
1005 | } | 944 | } |
@@ -1235,6 +1174,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
1235 | write_lock_bh(&bond->curr_slave_lock); | 1174 | write_lock_bh(&bond->curr_slave_lock); |
1236 | } | 1175 | } |
1237 | } | 1176 | } |
1177 | |||
1178 | /* resend IGMP joins since all were sent on curr_active_slave */ | ||
1179 | if (bond->params.mode == BOND_MODE_ROUNDROBIN) { | ||
1180 | bond_resend_igmp_join_requests(bond); | ||
1181 | } | ||
1238 | } | 1182 | } |
1239 | 1183 | ||
1240 | /** | 1184 | /** |
@@ -1324,6 +1268,61 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave) | |||
1324 | bond->slave_cnt--; | 1268 | bond->slave_cnt--; |
1325 | } | 1269 | } |
1326 | 1270 | ||
1271 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1272 | /* | ||
1273 | * You must hold read lock on bond->lock before calling this. | ||
1274 | */ | ||
1275 | static bool slaves_support_netpoll(struct net_device *bond_dev) | ||
1276 | { | ||
1277 | struct bonding *bond = netdev_priv(bond_dev); | ||
1278 | struct slave *slave; | ||
1279 | int i = 0; | ||
1280 | bool ret = true; | ||
1281 | |||
1282 | bond_for_each_slave(bond, slave, i) { | ||
1283 | if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
1284 | !slave->dev->netdev_ops->ndo_poll_controller) | ||
1285 | ret = false; | ||
1286 | } | ||
1287 | return i != 0 && ret; | ||
1288 | } | ||
1289 | |||
1290 | static void bond_poll_controller(struct net_device *bond_dev) | ||
1291 | { | ||
1292 | struct net_device *dev = bond_dev->npinfo->netpoll->real_dev; | ||
1293 | if (dev != bond_dev) | ||
1294 | netpoll_poll_dev(dev); | ||
1295 | } | ||
1296 | |||
1297 | static void bond_netpoll_cleanup(struct net_device *bond_dev) | ||
1298 | { | ||
1299 | struct bonding *bond = netdev_priv(bond_dev); | ||
1300 | struct slave *slave; | ||
1301 | const struct net_device_ops *ops; | ||
1302 | int i; | ||
1303 | |||
1304 | read_lock(&bond->lock); | ||
1305 | bond_dev->npinfo = NULL; | ||
1306 | bond_for_each_slave(bond, slave, i) { | ||
1307 | if (slave->dev) { | ||
1308 | ops = slave->dev->netdev_ops; | ||
1309 | if (ops->ndo_netpoll_cleanup) | ||
1310 | ops->ndo_netpoll_cleanup(slave->dev); | ||
1311 | else | ||
1312 | slave->dev->npinfo = NULL; | ||
1313 | } | ||
1314 | } | ||
1315 | read_unlock(&bond->lock); | ||
1316 | } | ||
1317 | |||
1318 | #else | ||
1319 | |||
1320 | static void bond_netpoll_cleanup(struct net_device *bond_dev) | ||
1321 | { | ||
1322 | } | ||
1323 | |||
1324 | #endif | ||
1325 | |||
1327 | /*---------------------------------- IOCTL ----------------------------------*/ | 1326 | /*---------------------------------- IOCTL ----------------------------------*/ |
1328 | 1327 | ||
1329 | static int bond_sethwaddr(struct net_device *bond_dev, | 1328 | static int bond_sethwaddr(struct net_device *bond_dev, |
@@ -1406,7 +1405,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1406 | struct bonding *bond = netdev_priv(bond_dev); | 1405 | struct bonding *bond = netdev_priv(bond_dev); |
1407 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | 1406 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; |
1408 | struct slave *new_slave = NULL; | 1407 | struct slave *new_slave = NULL; |
1409 | struct dev_mc_list *dmi; | 1408 | struct netdev_hw_addr *ha; |
1410 | struct sockaddr addr; | 1409 | struct sockaddr addr; |
1411 | int link_reporting; | 1410 | int link_reporting; |
1412 | int old_features = bond_dev->features; | 1411 | int old_features = bond_dev->features; |
@@ -1480,14 +1479,27 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1480 | bond_dev->name, | 1479 | bond_dev->name, |
1481 | bond_dev->type, slave_dev->type); | 1480 | bond_dev->type, slave_dev->type); |
1482 | 1481 | ||
1483 | netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE); | 1482 | res = netdev_bonding_change(bond_dev, |
1483 | NETDEV_PRE_TYPE_CHANGE); | ||
1484 | res = notifier_to_errno(res); | ||
1485 | if (res) { | ||
1486 | pr_err("%s: refused to change device type\n", | ||
1487 | bond_dev->name); | ||
1488 | res = -EBUSY; | ||
1489 | goto err_undo_flags; | ||
1490 | } | ||
1491 | |||
1492 | /* Flush unicast and multicast addresses */ | ||
1493 | dev_uc_flush(bond_dev); | ||
1494 | dev_mc_flush(bond_dev); | ||
1484 | 1495 | ||
1485 | if (slave_dev->type != ARPHRD_ETHER) | 1496 | if (slave_dev->type != ARPHRD_ETHER) |
1486 | bond_setup_by_slave(bond_dev, slave_dev); | 1497 | bond_setup_by_slave(bond_dev, slave_dev); |
1487 | else | 1498 | else |
1488 | ether_setup(bond_dev); | 1499 | ether_setup(bond_dev); |
1489 | 1500 | ||
1490 | netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE); | 1501 | netdev_bonding_change(bond_dev, |
1502 | NETDEV_POST_TYPE_CHANGE); | ||
1491 | } | 1503 | } |
1492 | } else if (bond_dev->type != slave_dev->type) { | 1504 | } else if (bond_dev->type != slave_dev->type) { |
1493 | pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n", | 1505 | pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n", |
@@ -1588,9 +1600,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1588 | 1600 | ||
1589 | netif_addr_lock_bh(bond_dev); | 1601 | netif_addr_lock_bh(bond_dev); |
1590 | /* upload master's mc_list to new slave */ | 1602 | /* upload master's mc_list to new slave */ |
1591 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) | 1603 | netdev_for_each_mc_addr(ha, bond_dev) |
1592 | dev_mc_add(slave_dev, dmi->dmi_addr, | 1604 | dev_mc_add(slave_dev, ha->addr); |
1593 | dmi->dmi_addrlen, 0); | ||
1594 | netif_addr_unlock_bh(bond_dev); | 1605 | netif_addr_unlock_bh(bond_dev); |
1595 | } | 1606 | } |
1596 | 1607 | ||
@@ -1598,7 +1609,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1598 | /* add lacpdu mc addr to mc list */ | 1609 | /* add lacpdu mc addr to mc list */ |
1599 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; | 1610 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; |
1600 | 1611 | ||
1601 | dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0); | 1612 | dev_mc_add(slave_dev, lacpdu_multicast); |
1602 | } | 1613 | } |
1603 | 1614 | ||
1604 | bond_add_vlans_on_slave(bond, slave_dev); | 1615 | bond_add_vlans_on_slave(bond, slave_dev); |
@@ -1730,6 +1741,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1730 | 1741 | ||
1731 | bond_set_carrier(bond); | 1742 | bond_set_carrier(bond); |
1732 | 1743 | ||
1744 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1745 | if (slaves_support_netpoll(bond_dev)) { | ||
1746 | bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
1747 | if (bond_dev->npinfo) | ||
1748 | slave_dev->npinfo = bond_dev->npinfo; | ||
1749 | } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { | ||
1750 | bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; | ||
1751 | pr_info("New slave device %s does not support netpoll\n", | ||
1752 | slave_dev->name); | ||
1753 | pr_info("Disabling netpoll support for %s\n", bond_dev->name); | ||
1754 | } | ||
1755 | #endif | ||
1733 | read_unlock(&bond->lock); | 1756 | read_unlock(&bond->lock); |
1734 | 1757 | ||
1735 | res = bond_create_slave_symlinks(bond_dev, slave_dev); | 1758 | res = bond_create_slave_symlinks(bond_dev, slave_dev); |
@@ -1796,6 +1819,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1796 | return -EINVAL; | 1819 | return -EINVAL; |
1797 | } | 1820 | } |
1798 | 1821 | ||
1822 | netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE); | ||
1799 | write_lock_bh(&bond->lock); | 1823 | write_lock_bh(&bond->lock); |
1800 | 1824 | ||
1801 | slave = bond_get_slave_by_dev(bond, slave_dev); | 1825 | slave = bond_get_slave_by_dev(bond, slave_dev); |
@@ -1924,6 +1948,17 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1924 | 1948 | ||
1925 | netdev_set_master(slave_dev, NULL); | 1949 | netdev_set_master(slave_dev, NULL); |
1926 | 1950 | ||
1951 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1952 | read_lock_bh(&bond->lock); | ||
1953 | if (slaves_support_netpoll(bond_dev)) | ||
1954 | bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
1955 | read_unlock_bh(&bond->lock); | ||
1956 | if (slave_dev->netdev_ops->ndo_netpoll_cleanup) | ||
1957 | slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev); | ||
1958 | else | ||
1959 | slave_dev->npinfo = NULL; | ||
1960 | #endif | ||
1961 | |||
1927 | /* close slave before restoring its mac address */ | 1962 | /* close slave before restoring its mac address */ |
1928 | dev_close(slave_dev); | 1963 | dev_close(slave_dev); |
1929 | 1964 | ||
@@ -3900,10 +3935,24 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
3900 | return res; | 3935 | return res; |
3901 | } | 3936 | } |
3902 | 3937 | ||
3938 | static bool bond_addr_in_mc_list(unsigned char *addr, | ||
3939 | struct netdev_hw_addr_list *list, | ||
3940 | int addrlen) | ||
3941 | { | ||
3942 | struct netdev_hw_addr *ha; | ||
3943 | |||
3944 | netdev_hw_addr_list_for_each(ha, list) | ||
3945 | if (!memcmp(ha->addr, addr, addrlen)) | ||
3946 | return true; | ||
3947 | |||
3948 | return false; | ||
3949 | } | ||
3950 | |||
3903 | static void bond_set_multicast_list(struct net_device *bond_dev) | 3951 | static void bond_set_multicast_list(struct net_device *bond_dev) |
3904 | { | 3952 | { |
3905 | struct bonding *bond = netdev_priv(bond_dev); | 3953 | struct bonding *bond = netdev_priv(bond_dev); |
3906 | struct dev_mc_list *dmi; | 3954 | struct netdev_hw_addr *ha; |
3955 | bool found; | ||
3907 | 3956 | ||
3908 | /* | 3957 | /* |
3909 | * Do promisc before checking multicast_mode | 3958 | * Do promisc before checking multicast_mode |
@@ -3938,20 +3987,25 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3938 | bond->flags = bond_dev->flags; | 3987 | bond->flags = bond_dev->flags; |
3939 | 3988 | ||
3940 | /* looking for addresses to add to slaves' mc list */ | 3989 | /* looking for addresses to add to slaves' mc list */ |
3941 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { | 3990 | netdev_for_each_mc_addr(ha, bond_dev) { |
3942 | if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) | 3991 | found = bond_addr_in_mc_list(ha->addr, &bond->mc_list, |
3943 | bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); | 3992 | bond_dev->addr_len); |
3993 | if (!found) | ||
3994 | bond_mc_add(bond, ha->addr); | ||
3944 | } | 3995 | } |
3945 | 3996 | ||
3946 | /* looking for addresses to delete from slaves' list */ | 3997 | /* looking for addresses to delete from slaves' list */ |
3947 | for (dmi = bond->mc_list; dmi; dmi = dmi->next) { | 3998 | netdev_hw_addr_list_for_each(ha, &bond->mc_list) { |
3948 | if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) | 3999 | found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc, |
3949 | bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); | 4000 | bond_dev->addr_len); |
4001 | if (!found) | ||
4002 | bond_mc_del(bond, ha->addr); | ||
3950 | } | 4003 | } |
3951 | 4004 | ||
3952 | /* save master's multicast list */ | 4005 | /* save master's multicast list */ |
3953 | bond_mc_list_destroy(bond); | 4006 | __hw_addr_flush(&bond->mc_list); |
3954 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); | 4007 | __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc, |
4008 | bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST); | ||
3955 | 4009 | ||
3956 | read_unlock(&bond->lock); | 4010 | read_unlock(&bond->lock); |
3957 | } | 4011 | } |
@@ -4138,22 +4192,41 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev | |||
4138 | struct bonding *bond = netdev_priv(bond_dev); | 4192 | struct bonding *bond = netdev_priv(bond_dev); |
4139 | struct slave *slave, *start_at; | 4193 | struct slave *slave, *start_at; |
4140 | int i, slave_no, res = 1; | 4194 | int i, slave_no, res = 1; |
4195 | struct iphdr *iph = ip_hdr(skb); | ||
4141 | 4196 | ||
4142 | read_lock(&bond->lock); | 4197 | read_lock(&bond->lock); |
4143 | 4198 | ||
4144 | if (!BOND_IS_OK(bond)) | 4199 | if (!BOND_IS_OK(bond)) |
4145 | goto out; | 4200 | goto out; |
4146 | |||
4147 | /* | 4201 | /* |
4148 | * Concurrent TX may collide on rr_tx_counter; we accept that | 4202 | * Start with the curr_active_slave that joined the bond as the |
4149 | * as being rare enough not to justify using an atomic op here | 4203 | * default for sending IGMP traffic. For failover purposes one |
4204 | * needs to maintain some consistency for the interface that will | ||
4205 | * send the join/membership reports. The curr_active_slave found | ||
4206 | * will send all of this type of traffic. | ||
4150 | */ | 4207 | */ |
4151 | slave_no = bond->rr_tx_counter++ % bond->slave_cnt; | 4208 | if ((iph->protocol == IPPROTO_IGMP) && |
4209 | (skb->protocol == htons(ETH_P_IP))) { | ||
4152 | 4210 | ||
4153 | bond_for_each_slave(bond, slave, i) { | 4211 | read_lock(&bond->curr_slave_lock); |
4154 | slave_no--; | 4212 | slave = bond->curr_active_slave; |
4155 | if (slave_no < 0) | 4213 | read_unlock(&bond->curr_slave_lock); |
4156 | break; | 4214 | |
4215 | if (!slave) | ||
4216 | goto out; | ||
4217 | } else { | ||
4218 | /* | ||
4219 | * Concurrent TX may collide on rr_tx_counter; we accept | ||
4220 | * that as being rare enough not to justify using an | ||
4221 | * atomic op here. | ||
4222 | */ | ||
4223 | slave_no = bond->rr_tx_counter++ % bond->slave_cnt; | ||
4224 | |||
4225 | bond_for_each_slave(bond, slave, i) { | ||
4226 | slave_no--; | ||
4227 | if (slave_no < 0) | ||
4228 | break; | ||
4229 | } | ||
4157 | } | 4230 | } |
4158 | 4231 | ||
4159 | start_at = slave; | 4232 | start_at = slave; |
@@ -4424,8 +4497,20 @@ static const struct net_device_ops bond_netdev_ops = { | |||
4424 | .ndo_vlan_rx_register = bond_vlan_rx_register, | 4497 | .ndo_vlan_rx_register = bond_vlan_rx_register, |
4425 | .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, | 4498 | .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, |
4426 | .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, | 4499 | .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, |
4500 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
4501 | .ndo_netpoll_cleanup = bond_netpoll_cleanup, | ||
4502 | .ndo_poll_controller = bond_poll_controller, | ||
4503 | #endif | ||
4427 | }; | 4504 | }; |
4428 | 4505 | ||
4506 | static void bond_destructor(struct net_device *bond_dev) | ||
4507 | { | ||
4508 | struct bonding *bond = netdev_priv(bond_dev); | ||
4509 | if (bond->wq) | ||
4510 | destroy_workqueue(bond->wq); | ||
4511 | free_netdev(bond_dev); | ||
4512 | } | ||
4513 | |||
4429 | static void bond_setup(struct net_device *bond_dev) | 4514 | static void bond_setup(struct net_device *bond_dev) |
4430 | { | 4515 | { |
4431 | struct bonding *bond = netdev_priv(bond_dev); | 4516 | struct bonding *bond = netdev_priv(bond_dev); |
@@ -4446,7 +4531,7 @@ static void bond_setup(struct net_device *bond_dev) | |||
4446 | bond_dev->ethtool_ops = &bond_ethtool_ops; | 4531 | bond_dev->ethtool_ops = &bond_ethtool_ops; |
4447 | bond_set_mode_ops(bond, bond->params.mode); | 4532 | bond_set_mode_ops(bond, bond->params.mode); |
4448 | 4533 | ||
4449 | bond_dev->destructor = free_netdev; | 4534 | bond_dev->destructor = bond_destructor; |
4450 | 4535 | ||
4451 | /* Initialize the device options */ | 4536 | /* Initialize the device options */ |
4452 | bond_dev->tx_queue_len = 0; | 4537 | bond_dev->tx_queue_len = 0; |
@@ -4509,6 +4594,8 @@ static void bond_uninit(struct net_device *bond_dev) | |||
4509 | { | 4594 | { |
4510 | struct bonding *bond = netdev_priv(bond_dev); | 4595 | struct bonding *bond = netdev_priv(bond_dev); |
4511 | 4596 | ||
4597 | bond_netpoll_cleanup(bond_dev); | ||
4598 | |||
4512 | /* Release the bonded slaves */ | 4599 | /* Release the bonded slaves */ |
4513 | bond_release_all(bond_dev); | 4600 | bond_release_all(bond_dev); |
4514 | 4601 | ||
@@ -4518,12 +4605,7 @@ static void bond_uninit(struct net_device *bond_dev) | |||
4518 | 4605 | ||
4519 | bond_remove_proc_entry(bond); | 4606 | bond_remove_proc_entry(bond); |
4520 | 4607 | ||
4521 | if (bond->wq) | 4608 | __hw_addr_flush(&bond->mc_list); |
4522 | destroy_workqueue(bond->wq); | ||
4523 | |||
4524 | netif_addr_lock_bh(bond_dev); | ||
4525 | bond_mc_list_destroy(bond); | ||
4526 | netif_addr_unlock_bh(bond_dev); | ||
4527 | } | 4609 | } |
4528 | 4610 | ||
4529 | /*------------------------- Module initialization ---------------------------*/ | 4611 | /*------------------------- Module initialization ---------------------------*/ |
@@ -4654,13 +4736,13 @@ static int bond_check_params(struct bond_params *params) | |||
4654 | } | 4736 | } |
4655 | 4737 | ||
4656 | if (num_grat_arp < 0 || num_grat_arp > 255) { | 4738 | if (num_grat_arp < 0 || num_grat_arp > 255) { |
4657 | pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1 \n", | 4739 | pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1\n", |
4658 | num_grat_arp); | 4740 | num_grat_arp); |
4659 | num_grat_arp = 1; | 4741 | num_grat_arp = 1; |
4660 | } | 4742 | } |
4661 | 4743 | ||
4662 | if (num_unsol_na < 0 || num_unsol_na > 255) { | 4744 | if (num_unsol_na < 0 || num_unsol_na > 255) { |
4663 | pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1 \n", | 4745 | pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", |
4664 | num_unsol_na); | 4746 | num_unsol_na); |
4665 | num_unsol_na = 1; | 4747 | num_unsol_na = 1; |
4666 | } | 4748 | } |
@@ -4895,6 +4977,8 @@ static int bond_init(struct net_device *bond_dev) | |||
4895 | list_add_tail(&bond->bond_list, &bn->dev_list); | 4977 | list_add_tail(&bond->bond_list, &bn->dev_list); |
4896 | 4978 | ||
4897 | bond_prepare_sysfs_group(bond); | 4979 | bond_prepare_sysfs_group(bond); |
4980 | |||
4981 | __hw_addr_init(&bond->mc_list); | ||
4898 | return 0; | 4982 | return 0; |
4899 | } | 4983 | } |
4900 | 4984 | ||
@@ -4932,8 +5016,8 @@ int bond_create(struct net *net, const char *name) | |||
4932 | bond_setup); | 5016 | bond_setup); |
4933 | if (!bond_dev) { | 5017 | if (!bond_dev) { |
4934 | pr_err("%s: eek! can't alloc netdev!\n", name); | 5018 | pr_err("%s: eek! can't alloc netdev!\n", name); |
4935 | res = -ENOMEM; | 5019 | rtnl_unlock(); |
4936 | goto out; | 5020 | return -ENOMEM; |
4937 | } | 5021 | } |
4938 | 5022 | ||
4939 | dev_net_set(bond_dev, net); | 5023 | dev_net_set(bond_dev, net); |
@@ -4942,19 +5026,16 @@ int bond_create(struct net *net, const char *name) | |||
4942 | if (!name) { | 5026 | if (!name) { |
4943 | res = dev_alloc_name(bond_dev, "bond%d"); | 5027 | res = dev_alloc_name(bond_dev, "bond%d"); |
4944 | if (res < 0) | 5028 | if (res < 0) |
4945 | goto out_netdev; | 5029 | goto out; |
4946 | } | 5030 | } |
4947 | 5031 | ||
4948 | res = register_netdevice(bond_dev); | 5032 | res = register_netdevice(bond_dev); |
4949 | if (res < 0) | ||
4950 | goto out_netdev; | ||
4951 | 5033 | ||
4952 | out: | 5034 | out: |
4953 | rtnl_unlock(); | 5035 | rtnl_unlock(); |
5036 | if (res < 0) | ||
5037 | bond_destructor(bond_dev); | ||
4954 | return res; | 5038 | return res; |
4955 | out_netdev: | ||
4956 | free_netdev(bond_dev); | ||
4957 | goto out; | ||
4958 | } | 5039 | } |
4959 | 5040 | ||
4960 | static int __net_init bond_net_init(struct net *net) | 5041 | static int __net_init bond_net_init(struct net *net) |