diff options
author | Jiri Pirko <jpirko@redhat.com> | 2010-04-01 17:22:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-03 17:22:15 -0400 |
commit | 22bedad3ce112d5ca1eaf043d4990fa2ed698c87 (patch) | |
tree | b6fba5688d48b1396f01d13ee53610dea7749c15 /net/core/dev.c | |
parent | a748ee2426817a95b1f03012d8f339c45c722ae1 (diff) |
net: convert multicast list to list_head
Converts the list and the core manipulating with it to be the same as uc_list.
+uses two functions for adding/removing mc address (normal and "global"
variant) instead of a function parameter.
+removes dev_mcast.c completely.
+exposes netdev_hw_addr_list_* macros along with __hw_addr_* functions for
manipulation with lists on a sandbox (used in bonding and 80211 drivers)
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 145 |
1 files changed, 5 insertions, 140 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 949c62dba719..2a9b7dd0bb6e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3968,140 +3968,6 @@ void dev_set_rx_mode(struct net_device *dev) | |||
3968 | netif_addr_unlock_bh(dev); | 3968 | netif_addr_unlock_bh(dev); |
3969 | } | 3969 | } |
3970 | 3970 | ||
3971 | /* multicast addresses handling functions */ | ||
3972 | |||
3973 | int __dev_addr_delete(struct dev_addr_list **list, int *count, | ||
3974 | void *addr, int alen, int glbl) | ||
3975 | { | ||
3976 | struct dev_addr_list *da; | ||
3977 | |||
3978 | for (; (da = *list) != NULL; list = &da->next) { | ||
3979 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
3980 | alen == da->da_addrlen) { | ||
3981 | if (glbl) { | ||
3982 | int old_glbl = da->da_gusers; | ||
3983 | da->da_gusers = 0; | ||
3984 | if (old_glbl == 0) | ||
3985 | break; | ||
3986 | } | ||
3987 | if (--da->da_users) | ||
3988 | return 0; | ||
3989 | |||
3990 | *list = da->next; | ||
3991 | kfree(da); | ||
3992 | (*count)--; | ||
3993 | return 0; | ||
3994 | } | ||
3995 | } | ||
3996 | return -ENOENT; | ||
3997 | } | ||
3998 | |||
3999 | int __dev_addr_add(struct dev_addr_list **list, int *count, | ||
4000 | void *addr, int alen, int glbl) | ||
4001 | { | ||
4002 | struct dev_addr_list *da; | ||
4003 | |||
4004 | for (da = *list; da != NULL; da = da->next) { | ||
4005 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
4006 | da->da_addrlen == alen) { | ||
4007 | if (glbl) { | ||
4008 | int old_glbl = da->da_gusers; | ||
4009 | da->da_gusers = 1; | ||
4010 | if (old_glbl) | ||
4011 | return 0; | ||
4012 | } | ||
4013 | da->da_users++; | ||
4014 | return 0; | ||
4015 | } | ||
4016 | } | ||
4017 | |||
4018 | da = kzalloc(sizeof(*da), GFP_ATOMIC); | ||
4019 | if (da == NULL) | ||
4020 | return -ENOMEM; | ||
4021 | memcpy(da->da_addr, addr, alen); | ||
4022 | da->da_addrlen = alen; | ||
4023 | da->da_users = 1; | ||
4024 | da->da_gusers = glbl ? 1 : 0; | ||
4025 | da->next = *list; | ||
4026 | *list = da; | ||
4027 | (*count)++; | ||
4028 | return 0; | ||
4029 | } | ||
4030 | |||
4031 | |||
4032 | int __dev_addr_sync(struct dev_addr_list **to, int *to_count, | ||
4033 | struct dev_addr_list **from, int *from_count) | ||
4034 | { | ||
4035 | struct dev_addr_list *da, *next; | ||
4036 | int err = 0; | ||
4037 | |||
4038 | da = *from; | ||
4039 | while (da != NULL) { | ||
4040 | next = da->next; | ||
4041 | if (!da->da_synced) { | ||
4042 | err = __dev_addr_add(to, to_count, | ||
4043 | da->da_addr, da->da_addrlen, 0); | ||
4044 | if (err < 0) | ||
4045 | break; | ||
4046 | da->da_synced = 1; | ||
4047 | da->da_users++; | ||
4048 | } else if (da->da_users == 1) { | ||
4049 | __dev_addr_delete(to, to_count, | ||
4050 | da->da_addr, da->da_addrlen, 0); | ||
4051 | __dev_addr_delete(from, from_count, | ||
4052 | da->da_addr, da->da_addrlen, 0); | ||
4053 | } | ||
4054 | da = next; | ||
4055 | } | ||
4056 | return err; | ||
4057 | } | ||
4058 | EXPORT_SYMBOL_GPL(__dev_addr_sync); | ||
4059 | |||
4060 | void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | ||
4061 | struct dev_addr_list **from, int *from_count) | ||
4062 | { | ||
4063 | struct dev_addr_list *da, *next; | ||
4064 | |||
4065 | da = *from; | ||
4066 | while (da != NULL) { | ||
4067 | next = da->next; | ||
4068 | if (da->da_synced) { | ||
4069 | __dev_addr_delete(to, to_count, | ||
4070 | da->da_addr, da->da_addrlen, 0); | ||
4071 | da->da_synced = 0; | ||
4072 | __dev_addr_delete(from, from_count, | ||
4073 | da->da_addr, da->da_addrlen, 0); | ||
4074 | } | ||
4075 | da = next; | ||
4076 | } | ||
4077 | } | ||
4078 | EXPORT_SYMBOL_GPL(__dev_addr_unsync); | ||
4079 | |||
4080 | static void __dev_addr_discard(struct dev_addr_list **list) | ||
4081 | { | ||
4082 | struct dev_addr_list *tmp; | ||
4083 | |||
4084 | while (*list != NULL) { | ||
4085 | tmp = *list; | ||
4086 | *list = tmp->next; | ||
4087 | if (tmp->da_users > tmp->da_gusers) | ||
4088 | printk("__dev_addr_discard: address leakage! " | ||
4089 | "da_users=%d\n", tmp->da_users); | ||
4090 | kfree(tmp); | ||
4091 | } | ||
4092 | } | ||
4093 | |||
4094 | void dev_addr_discard(struct net_device *dev) | ||
4095 | { | ||
4096 | netif_addr_lock_bh(dev); | ||
4097 | |||
4098 | __dev_addr_discard(&dev->mc_list); | ||
4099 | netdev_mc_count(dev) = 0; | ||
4100 | |||
4101 | netif_addr_unlock_bh(dev); | ||
4102 | } | ||
4103 | EXPORT_SYMBOL(dev_addr_discard); | ||
4104 | |||
4105 | /** | 3971 | /** |
4106 | * dev_get_flags - get flags reported to userspace | 3972 | * dev_get_flags - get flags reported to userspace |
4107 | * @dev: device | 3973 | * @dev: device |
@@ -4412,8 +4278,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
4412 | return -EINVAL; | 4278 | return -EINVAL; |
4413 | if (!netif_device_present(dev)) | 4279 | if (!netif_device_present(dev)) |
4414 | return -ENODEV; | 4280 | return -ENODEV; |
4415 | return dev_mc_add(dev, ifr->ifr_hwaddr.sa_data, | 4281 | return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data); |
4416 | dev->addr_len, 1); | ||
4417 | 4282 | ||
4418 | case SIOCDELMULTI: | 4283 | case SIOCDELMULTI: |
4419 | if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || | 4284 | if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || |
@@ -4421,8 +4286,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
4421 | return -EINVAL; | 4286 | return -EINVAL; |
4422 | if (!netif_device_present(dev)) | 4287 | if (!netif_device_present(dev)) |
4423 | return -ENODEV; | 4288 | return -ENODEV; |
4424 | return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data, | 4289 | return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data); |
4425 | dev->addr_len, 1); | ||
4426 | 4290 | ||
4427 | case SIOCSIFTXQLEN: | 4291 | case SIOCSIFTXQLEN: |
4428 | if (ifr->ifr_qlen < 0) | 4292 | if (ifr->ifr_qlen < 0) |
@@ -4730,7 +4594,7 @@ static void rollback_registered_many(struct list_head *head) | |||
4730 | * Flush the unicast and multicast chains | 4594 | * Flush the unicast and multicast chains |
4731 | */ | 4595 | */ |
4732 | dev_uc_flush(dev); | 4596 | dev_uc_flush(dev); |
4733 | dev_addr_discard(dev); | 4597 | dev_mc_flush(dev); |
4734 | 4598 | ||
4735 | if (dev->netdev_ops->ndo_uninit) | 4599 | if (dev->netdev_ops->ndo_uninit) |
4736 | dev->netdev_ops->ndo_uninit(dev); | 4600 | dev->netdev_ops->ndo_uninit(dev); |
@@ -5310,6 +5174,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5310 | if (dev_addr_init(dev)) | 5174 | if (dev_addr_init(dev)) |
5311 | goto free_rx; | 5175 | goto free_rx; |
5312 | 5176 | ||
5177 | dev_mc_init(dev); | ||
5313 | dev_uc_init(dev); | 5178 | dev_uc_init(dev); |
5314 | 5179 | ||
5315 | dev_net_set(dev, &init_net); | 5180 | dev_net_set(dev, &init_net); |
@@ -5545,7 +5410,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5545 | * Flush the unicast and multicast chains | 5410 | * Flush the unicast and multicast chains |
5546 | */ | 5411 | */ |
5547 | dev_uc_flush(dev); | 5412 | dev_uc_flush(dev); |
5548 | dev_addr_discard(dev); | 5413 | dev_mc_flush(dev); |
5549 | 5414 | ||
5550 | netdev_unregister_kobject(dev); | 5415 | netdev_unregister_kobject(dev); |
5551 | 5416 | ||