aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2010-04-01 17:22:57 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-03 17:22:15 -0400
commit22bedad3ce112d5ca1eaf043d4990fa2ed698c87 (patch)
treeb6fba5688d48b1396f01d13ee53610dea7749c15 /net/core/dev.c
parenta748ee2426817a95b1f03012d8f339c45c722ae1 (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.c145
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
3973int __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
3999int __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
4032int __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}
4058EXPORT_SYMBOL_GPL(__dev_addr_sync);
4059
4060void __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}
4078EXPORT_SYMBOL_GPL(__dev_addr_unsync);
4079
4080static 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
4094void 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}
4103EXPORT_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