diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 176 |
1 files changed, 67 insertions, 109 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0075514bf32f..85e813c7762b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -762,32 +762,6 @@ static int bond_check_dev_link(struct bonding *bond, | |||
762 | /*----------------------------- Multicast list ------------------------------*/ | 762 | /*----------------------------- Multicast list ------------------------------*/ |
763 | 763 | ||
764 | /* | 764 | /* |
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 | 765 | * Push the promiscuity flag down to appropriate slaves |
792 | */ | 766 | */ |
793 | static int bond_set_promiscuity(struct bonding *bond, int inc) | 767 | static int bond_set_promiscuity(struct bonding *bond, int inc) |
@@ -839,18 +813,18 @@ static int bond_set_allmulti(struct bonding *bond, int inc) | |||
839 | * Add a Multicast address to slaves | 813 | * Add a Multicast address to slaves |
840 | * according to mode | 814 | * according to mode |
841 | */ | 815 | */ |
842 | static void bond_mc_add(struct bonding *bond, void *addr, int alen) | 816 | static void bond_mc_add(struct bonding *bond, void *addr) |
843 | { | 817 | { |
844 | if (USES_PRIMARY(bond->params.mode)) { | 818 | if (USES_PRIMARY(bond->params.mode)) { |
845 | /* write lock already acquired */ | 819 | /* write lock already acquired */ |
846 | if (bond->curr_active_slave) | 820 | if (bond->curr_active_slave) |
847 | dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); | 821 | dev_mc_add(bond->curr_active_slave->dev, addr); |
848 | } else { | 822 | } else { |
849 | struct slave *slave; | 823 | struct slave *slave; |
850 | int i; | 824 | int i; |
851 | 825 | ||
852 | bond_for_each_slave(bond, slave, i) | 826 | bond_for_each_slave(bond, slave, i) |
853 | dev_mc_add(slave->dev, addr, alen, 0); | 827 | dev_mc_add(slave->dev, addr); |
854 | } | 828 | } |
855 | } | 829 | } |
856 | 830 | ||
@@ -858,18 +832,17 @@ static void bond_mc_add(struct bonding *bond, void *addr, int alen) | |||
858 | * Remove a multicast address from slave | 832 | * Remove a multicast address from slave |
859 | * according to mode | 833 | * according to mode |
860 | */ | 834 | */ |
861 | static void bond_mc_delete(struct bonding *bond, void *addr, int alen) | 835 | static void bond_mc_del(struct bonding *bond, void *addr) |
862 | { | 836 | { |
863 | if (USES_PRIMARY(bond->params.mode)) { | 837 | if (USES_PRIMARY(bond->params.mode)) { |
864 | /* write lock already acquired */ | 838 | /* write lock already acquired */ |
865 | if (bond->curr_active_slave) | 839 | if (bond->curr_active_slave) |
866 | dev_mc_delete(bond->curr_active_slave->dev, addr, | 840 | dev_mc_del(bond->curr_active_slave->dev, addr); |
867 | alen, 0); | ||
868 | } else { | 841 | } else { |
869 | struct slave *slave; | 842 | struct slave *slave; |
870 | int i; | 843 | int i; |
871 | bond_for_each_slave(bond, slave, i) { | 844 | bond_for_each_slave(bond, slave, i) { |
872 | dev_mc_delete(slave->dev, addr, alen, 0); | 845 | dev_mc_del(slave->dev, addr); |
873 | } | 846 | } |
874 | } | 847 | } |
875 | } | 848 | } |
@@ -896,66 +869,22 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) | |||
896 | } | 869 | } |
897 | 870 | ||
898 | /* | 871 | /* |
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 | 872 | * flush all members of flush->mc_list from device dev->mc_list |
944 | */ | 873 | */ |
945 | static void bond_mc_list_flush(struct net_device *bond_dev, | 874 | static void bond_mc_list_flush(struct net_device *bond_dev, |
946 | struct net_device *slave_dev) | 875 | struct net_device *slave_dev) |
947 | { | 876 | { |
948 | struct bonding *bond = netdev_priv(bond_dev); | 877 | struct bonding *bond = netdev_priv(bond_dev); |
949 | struct dev_mc_list *dmi; | 878 | struct netdev_hw_addr *ha; |
950 | 879 | ||
951 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) | 880 | netdev_for_each_mc_addr(ha, bond_dev) |
952 | dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | 881 | dev_mc_del(slave_dev, ha->addr); |
953 | 882 | ||
954 | if (bond->params.mode == BOND_MODE_8023AD) { | 883 | if (bond->params.mode == BOND_MODE_8023AD) { |
955 | /* del lacpdu mc addr from mc list */ | 884 | /* del lacpdu mc addr from mc list */ |
956 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; | 885 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; |
957 | 886 | ||
958 | dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0); | 887 | dev_mc_del(slave_dev, lacpdu_multicast); |
959 | } | 888 | } |
960 | } | 889 | } |
961 | 890 | ||
@@ -969,7 +898,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, | 898 | static void bond_mc_swap(struct bonding *bond, struct slave *new_active, |
970 | struct slave *old_active) | 899 | struct slave *old_active) |
971 | { | 900 | { |
972 | struct dev_mc_list *dmi; | 901 | struct netdev_hw_addr *ha; |
973 | 902 | ||
974 | if (!USES_PRIMARY(bond->params.mode)) | 903 | if (!USES_PRIMARY(bond->params.mode)) |
975 | /* nothing to do - mc list is already up-to-date on | 904 | /* nothing to do - mc list is already up-to-date on |
@@ -984,9 +913,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
984 | if (bond->dev->flags & IFF_ALLMULTI) | 913 | if (bond->dev->flags & IFF_ALLMULTI) |
985 | dev_set_allmulti(old_active->dev, -1); | 914 | dev_set_allmulti(old_active->dev, -1); |
986 | 915 | ||
987 | for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) | 916 | netdev_for_each_mc_addr(ha, bond->dev) |
988 | dev_mc_delete(old_active->dev, dmi->dmi_addr, | 917 | dev_mc_del(old_active->dev, ha->addr); |
989 | dmi->dmi_addrlen, 0); | ||
990 | } | 918 | } |
991 | 919 | ||
992 | if (new_active) { | 920 | if (new_active) { |
@@ -997,9 +925,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
997 | if (bond->dev->flags & IFF_ALLMULTI) | 925 | if (bond->dev->flags & IFF_ALLMULTI) |
998 | dev_set_allmulti(new_active->dev, 1); | 926 | dev_set_allmulti(new_active->dev, 1); |
999 | 927 | ||
1000 | for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) | 928 | netdev_for_each_mc_addr(ha, bond->dev) |
1001 | dev_mc_add(new_active->dev, dmi->dmi_addr, | 929 | dev_mc_add(new_active->dev, ha->addr); |
1002 | dmi->dmi_addrlen, 0); | ||
1003 | bond_resend_igmp_join_requests(bond); | 930 | bond_resend_igmp_join_requests(bond); |
1004 | } | 931 | } |
1005 | } | 932 | } |
@@ -1411,7 +1338,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1411 | struct bonding *bond = netdev_priv(bond_dev); | 1338 | struct bonding *bond = netdev_priv(bond_dev); |
1412 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | 1339 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; |
1413 | struct slave *new_slave = NULL; | 1340 | struct slave *new_slave = NULL; |
1414 | struct dev_mc_list *dmi; | 1341 | struct netdev_hw_addr *ha; |
1415 | struct sockaddr addr; | 1342 | struct sockaddr addr; |
1416 | int link_reporting; | 1343 | int link_reporting; |
1417 | int old_features = bond_dev->features; | 1344 | int old_features = bond_dev->features; |
@@ -1485,14 +1412,27 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1485 | bond_dev->name, | 1412 | bond_dev->name, |
1486 | bond_dev->type, slave_dev->type); | 1413 | bond_dev->type, slave_dev->type); |
1487 | 1414 | ||
1488 | netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE); | 1415 | res = netdev_bonding_change(bond_dev, |
1416 | NETDEV_PRE_TYPE_CHANGE); | ||
1417 | res = notifier_to_errno(res); | ||
1418 | if (res) { | ||
1419 | pr_err("%s: refused to change device type\n", | ||
1420 | bond_dev->name); | ||
1421 | res = -EBUSY; | ||
1422 | goto err_undo_flags; | ||
1423 | } | ||
1424 | |||
1425 | /* Flush unicast and multicast addresses */ | ||
1426 | dev_uc_flush(bond_dev); | ||
1427 | dev_mc_flush(bond_dev); | ||
1489 | 1428 | ||
1490 | if (slave_dev->type != ARPHRD_ETHER) | 1429 | if (slave_dev->type != ARPHRD_ETHER) |
1491 | bond_setup_by_slave(bond_dev, slave_dev); | 1430 | bond_setup_by_slave(bond_dev, slave_dev); |
1492 | else | 1431 | else |
1493 | ether_setup(bond_dev); | 1432 | ether_setup(bond_dev); |
1494 | 1433 | ||
1495 | netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE); | 1434 | netdev_bonding_change(bond_dev, |
1435 | NETDEV_POST_TYPE_CHANGE); | ||
1496 | } | 1436 | } |
1497 | } else if (bond_dev->type != slave_dev->type) { | 1437 | } else if (bond_dev->type != slave_dev->type) { |
1498 | pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n", | 1438 | pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n", |
@@ -1593,9 +1533,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1593 | 1533 | ||
1594 | netif_addr_lock_bh(bond_dev); | 1534 | netif_addr_lock_bh(bond_dev); |
1595 | /* upload master's mc_list to new slave */ | 1535 | /* upload master's mc_list to new slave */ |
1596 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) | 1536 | netdev_for_each_mc_addr(ha, bond_dev) |
1597 | dev_mc_add(slave_dev, dmi->dmi_addr, | 1537 | dev_mc_add(slave_dev, ha->addr); |
1598 | dmi->dmi_addrlen, 0); | ||
1599 | netif_addr_unlock_bh(bond_dev); | 1538 | netif_addr_unlock_bh(bond_dev); |
1600 | } | 1539 | } |
1601 | 1540 | ||
@@ -1603,7 +1542,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1603 | /* add lacpdu mc addr to mc list */ | 1542 | /* add lacpdu mc addr to mc list */ |
1604 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; | 1543 | u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; |
1605 | 1544 | ||
1606 | dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0); | 1545 | dev_mc_add(slave_dev, lacpdu_multicast); |
1607 | } | 1546 | } |
1608 | 1547 | ||
1609 | bond_add_vlans_on_slave(bond, slave_dev); | 1548 | bond_add_vlans_on_slave(bond, slave_dev); |
@@ -3905,10 +3844,24 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
3905 | return res; | 3844 | return res; |
3906 | } | 3845 | } |
3907 | 3846 | ||
3847 | static bool bond_addr_in_mc_list(unsigned char *addr, | ||
3848 | struct netdev_hw_addr_list *list, | ||
3849 | int addrlen) | ||
3850 | { | ||
3851 | struct netdev_hw_addr *ha; | ||
3852 | |||
3853 | netdev_hw_addr_list_for_each(ha, list) | ||
3854 | if (!memcmp(ha->addr, addr, addrlen)) | ||
3855 | return true; | ||
3856 | |||
3857 | return false; | ||
3858 | } | ||
3859 | |||
3908 | static void bond_set_multicast_list(struct net_device *bond_dev) | 3860 | static void bond_set_multicast_list(struct net_device *bond_dev) |
3909 | { | 3861 | { |
3910 | struct bonding *bond = netdev_priv(bond_dev); | 3862 | struct bonding *bond = netdev_priv(bond_dev); |
3911 | struct dev_mc_list *dmi; | 3863 | struct netdev_hw_addr *ha; |
3864 | bool found; | ||
3912 | 3865 | ||
3913 | /* | 3866 | /* |
3914 | * Do promisc before checking multicast_mode | 3867 | * Do promisc before checking multicast_mode |
@@ -3943,20 +3896,25 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3943 | bond->flags = bond_dev->flags; | 3896 | bond->flags = bond_dev->flags; |
3944 | 3897 | ||
3945 | /* looking for addresses to add to slaves' mc list */ | 3898 | /* looking for addresses to add to slaves' mc list */ |
3946 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { | 3899 | netdev_for_each_mc_addr(ha, bond_dev) { |
3947 | if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) | 3900 | found = bond_addr_in_mc_list(ha->addr, &bond->mc_list, |
3948 | bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); | 3901 | bond_dev->addr_len); |
3902 | if (!found) | ||
3903 | bond_mc_add(bond, ha->addr); | ||
3949 | } | 3904 | } |
3950 | 3905 | ||
3951 | /* looking for addresses to delete from slaves' list */ | 3906 | /* looking for addresses to delete from slaves' list */ |
3952 | for (dmi = bond->mc_list; dmi; dmi = dmi->next) { | 3907 | netdev_hw_addr_list_for_each(ha, &bond->mc_list) { |
3953 | if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) | 3908 | found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc, |
3954 | bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); | 3909 | bond_dev->addr_len); |
3910 | if (!found) | ||
3911 | bond_mc_del(bond, ha->addr); | ||
3955 | } | 3912 | } |
3956 | 3913 | ||
3957 | /* save master's multicast list */ | 3914 | /* save master's multicast list */ |
3958 | bond_mc_list_destroy(bond); | 3915 | __hw_addr_flush(&bond->mc_list); |
3959 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); | 3916 | __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc, |
3917 | bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST); | ||
3960 | 3918 | ||
3961 | read_unlock(&bond->lock); | 3919 | read_unlock(&bond->lock); |
3962 | } | 3920 | } |
@@ -4550,9 +4508,7 @@ static void bond_uninit(struct net_device *bond_dev) | |||
4550 | 4508 | ||
4551 | bond_remove_proc_entry(bond); | 4509 | bond_remove_proc_entry(bond); |
4552 | 4510 | ||
4553 | netif_addr_lock_bh(bond_dev); | 4511 | __hw_addr_flush(&bond->mc_list); |
4554 | bond_mc_list_destroy(bond); | ||
4555 | netif_addr_unlock_bh(bond_dev); | ||
4556 | } | 4512 | } |
4557 | 4513 | ||
4558 | /*------------------------- Module initialization ---------------------------*/ | 4514 | /*------------------------- Module initialization ---------------------------*/ |
@@ -4683,13 +4639,13 @@ static int bond_check_params(struct bond_params *params) | |||
4683 | } | 4639 | } |
4684 | 4640 | ||
4685 | if (num_grat_arp < 0 || num_grat_arp > 255) { | 4641 | if (num_grat_arp < 0 || num_grat_arp > 255) { |
4686 | pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1 \n", | 4642 | pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1\n", |
4687 | num_grat_arp); | 4643 | num_grat_arp); |
4688 | num_grat_arp = 1; | 4644 | num_grat_arp = 1; |
4689 | } | 4645 | } |
4690 | 4646 | ||
4691 | if (num_unsol_na < 0 || num_unsol_na > 255) { | 4647 | if (num_unsol_na < 0 || num_unsol_na > 255) { |
4692 | pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1 \n", | 4648 | pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", |
4693 | num_unsol_na); | 4649 | num_unsol_na); |
4694 | num_unsol_na = 1; | 4650 | num_unsol_na = 1; |
4695 | } | 4651 | } |
@@ -4924,6 +4880,8 @@ static int bond_init(struct net_device *bond_dev) | |||
4924 | list_add_tail(&bond->bond_list, &bn->dev_list); | 4880 | list_add_tail(&bond->bond_list, &bn->dev_list); |
4925 | 4881 | ||
4926 | bond_prepare_sysfs_group(bond); | 4882 | bond_prepare_sysfs_group(bond); |
4883 | |||
4884 | __hw_addr_init(&bond->mc_list); | ||
4927 | return 0; | 4885 | return 0; |
4928 | } | 4886 | } |
4929 | 4887 | ||