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 | |
| 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')
| -rw-r--r-- | net/802/garp.c | 4 | ||||
| -rw-r--r-- | net/appletalk/ddp.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/bnep/netdev.c | 8 | ||||
| -rw-r--r-- | net/core/Makefile | 5 | ||||
| -rw-r--r-- | net/core/dev.c | 145 | ||||
| -rw-r--r-- | net/core/dev_addr_lists.c | 305 | ||||
| -rw-r--r-- | net/core/dev_mcast.c | 232 | ||||
| -rw-r--r-- | net/decnet/dn_dev.c | 12 | ||||
| -rw-r--r-- | net/ipv4/igmp.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 4 | ||||
| -rw-r--r-- | net/mac80211/driver-ops.h | 8 | ||||
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
| -rw-r--r-- | net/mac80211/iface.c | 6 | ||||
| -rw-r--r-- | net/mac80211/main.c | 2 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 4 |
16 files changed, 319 insertions, 429 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index 1dcb0660c49d..78cff9ec2cb4 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
| @@ -575,7 +575,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl) | |||
| 575 | if (!app) | 575 | if (!app) |
| 576 | goto err2; | 576 | goto err2; |
| 577 | 577 | ||
| 578 | err = dev_mc_add(dev, appl->proto.group_address, ETH_ALEN, 0); | 578 | err = dev_mc_add(dev, appl->proto.group_address); |
| 579 | if (err < 0) | 579 | if (err < 0) |
| 580 | goto err3; | 580 | goto err3; |
| 581 | 581 | ||
| @@ -615,7 +615,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
| 615 | garp_pdu_queue(app); | 615 | garp_pdu_queue(app); |
| 616 | garp_queue_xmit(app); | 616 | garp_queue_xmit(app); |
| 617 | 617 | ||
| 618 | dev_mc_delete(dev, appl->proto.group_address, ETH_ALEN, 0); | 618 | dev_mc_del(dev, appl->proto.group_address); |
| 619 | kfree(app); | 619 | kfree(app); |
| 620 | garp_release_port(dev); | 620 | garp_release_port(dev); |
| 621 | } | 621 | } |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 9fc4da56fb1d..1d15a60b23af 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
| @@ -781,7 +781,7 @@ static int atif_ioctl(int cmd, void __user *arg) | |||
| 781 | atrtr_create(&rtdef, dev); | 781 | atrtr_create(&rtdef, dev); |
| 782 | } | 782 | } |
| 783 | } | 783 | } |
| 784 | dev_mc_add(dev, aarp_mcast, 6, 1); | 784 | dev_mc_add_global(dev, aarp_mcast); |
| 785 | return 0; | 785 | return 0; |
| 786 | 786 | ||
| 787 | case SIOCGIFADDR: | 787 | case SIOCGIFADDR: |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 326ab453edb7..260a9507e542 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
| @@ -87,7 +87,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
| 87 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); | 87 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); |
| 88 | r->len = htons(ETH_ALEN * 2); | 88 | r->len = htons(ETH_ALEN * 2); |
| 89 | } else { | 89 | } else { |
| 90 | struct dev_mc_list *dmi; | 90 | struct netdev_hw_addr *ha; |
| 91 | int i, len = skb->len; | 91 | int i, len = skb->len; |
| 92 | 92 | ||
| 93 | if (dev->flags & IFF_BROADCAST) { | 93 | if (dev->flags & IFF_BROADCAST) { |
| @@ -98,11 +98,11 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
| 98 | /* FIXME: We should group addresses here. */ | 98 | /* FIXME: We should group addresses here. */ |
| 99 | 99 | ||
| 100 | i = 0; | 100 | i = 0; |
| 101 | netdev_for_each_mc_addr(dmi, dev) { | 101 | netdev_for_each_mc_addr(ha, dev) { |
| 102 | if (i == BNEP_MAX_MULTICAST_FILTERS) | 102 | if (i == BNEP_MAX_MULTICAST_FILTERS) |
| 103 | break; | 103 | break; |
| 104 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 104 | memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); |
| 105 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 105 | memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); |
| 106 | } | 106 | } |
| 107 | r->len = htons(skb->len - len); | 107 | r->len = htons(skb->len - len); |
| 108 | } | 108 | } |
diff --git a/net/core/Makefile b/net/core/Makefile index 0a899f1aadb9..51c3eec850ef 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
| @@ -7,9 +7,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ | |||
| 7 | 7 | ||
| 8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o | 8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o |
| 9 | 9 | ||
| 10 | obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ | 10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ |
| 11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ | 11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o |
| 12 | dev_addr_lists.o | ||
| 13 | 12 | ||
| 14 | obj-$(CONFIG_XFRM) += flow.o | 13 | obj-$(CONFIG_XFRM) += flow.o |
| 15 | obj-y += net-sysfs.o | 14 | obj-y += net-sysfs.o |
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 | ||
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 7e52b6d18add..37d5975e18a3 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c | |||
| @@ -19,8 +19,9 @@ | |||
| 19 | * General list handling functions | 19 | * General list handling functions |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | 22 | static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, |
| 23 | int addr_len, unsigned char addr_type) | 23 | unsigned char *addr, int addr_len, |
| 24 | unsigned char addr_type, bool global) | ||
| 24 | { | 25 | { |
| 25 | struct netdev_hw_addr *ha; | 26 | struct netdev_hw_addr *ha; |
| 26 | int alloc_size; | 27 | int alloc_size; |
| @@ -31,6 +32,13 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | |||
| 31 | list_for_each_entry(ha, &list->list, list) { | 32 | list_for_each_entry(ha, &list->list, list) { |
| 32 | if (!memcmp(ha->addr, addr, addr_len) && | 33 | if (!memcmp(ha->addr, addr, addr_len) && |
| 33 | ha->type == addr_type) { | 34 | ha->type == addr_type) { |
| 35 | if (global) { | ||
| 36 | /* check if addr is already used as global */ | ||
| 37 | if (ha->global_use) | ||
| 38 | return 0; | ||
| 39 | else | ||
| 40 | ha->global_use = true; | ||
| 41 | } | ||
| 34 | ha->refcount++; | 42 | ha->refcount++; |
| 35 | return 0; | 43 | return 0; |
| 36 | } | 44 | } |
| @@ -46,12 +54,19 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | |||
| 46 | memcpy(ha->addr, addr, addr_len); | 54 | memcpy(ha->addr, addr, addr_len); |
| 47 | ha->type = addr_type; | 55 | ha->type = addr_type; |
| 48 | ha->refcount = 1; | 56 | ha->refcount = 1; |
| 57 | ha->global_use = global; | ||
| 49 | ha->synced = false; | 58 | ha->synced = false; |
| 50 | list_add_tail_rcu(&ha->list, &list->list); | 59 | list_add_tail_rcu(&ha->list, &list->list); |
| 51 | list->count++; | 60 | list->count++; |
| 52 | return 0; | 61 | return 0; |
| 53 | } | 62 | } |
| 54 | 63 | ||
| 64 | static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | ||
| 65 | int addr_len, unsigned char addr_type) | ||
| 66 | { | ||
| 67 | return __hw_addr_add_ex(list, addr, addr_len, addr_type, false); | ||
| 68 | } | ||
| 69 | |||
| 55 | static void ha_rcu_free(struct rcu_head *head) | 70 | static void ha_rcu_free(struct rcu_head *head) |
| 56 | { | 71 | { |
| 57 | struct netdev_hw_addr *ha; | 72 | struct netdev_hw_addr *ha; |
| @@ -60,14 +75,21 @@ static void ha_rcu_free(struct rcu_head *head) | |||
| 60 | kfree(ha); | 75 | kfree(ha); |
| 61 | } | 76 | } |
| 62 | 77 | ||
| 63 | static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, | 78 | static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, |
| 64 | int addr_len, unsigned char addr_type) | 79 | unsigned char *addr, int addr_len, |
| 80 | unsigned char addr_type, bool global) | ||
| 65 | { | 81 | { |
| 66 | struct netdev_hw_addr *ha; | 82 | struct netdev_hw_addr *ha; |
| 67 | 83 | ||
| 68 | list_for_each_entry(ha, &list->list, list) { | 84 | list_for_each_entry(ha, &list->list, list) { |
| 69 | if (!memcmp(ha->addr, addr, addr_len) && | 85 | if (!memcmp(ha->addr, addr, addr_len) && |
| 70 | (ha->type == addr_type || !addr_type)) { | 86 | (ha->type == addr_type || !addr_type)) { |
| 87 | if (global) { | ||
| 88 | if (!ha->global_use) | ||
| 89 | break; | ||
| 90 | else | ||
| 91 | ha->global_use = false; | ||
| 92 | } | ||
| 71 | if (--ha->refcount) | 93 | if (--ha->refcount) |
| 72 | return 0; | 94 | return 0; |
| 73 | list_del_rcu(&ha->list); | 95 | list_del_rcu(&ha->list); |
| @@ -79,10 +101,15 @@ static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, | |||
| 79 | return -ENOENT; | 101 | return -ENOENT; |
| 80 | } | 102 | } |
| 81 | 103 | ||
| 82 | static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, | 104 | static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, |
| 83 | struct netdev_hw_addr_list *from_list, | 105 | int addr_len, unsigned char addr_type) |
| 84 | int addr_len, | 106 | { |
| 85 | unsigned char addr_type) | 107 | return __hw_addr_del_ex(list, addr, addr_len, addr_type, false); |
| 108 | } | ||
| 109 | |||
| 110 | int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, | ||
| 111 | struct netdev_hw_addr_list *from_list, | ||
| 112 | int addr_len, unsigned char addr_type) | ||
| 86 | { | 113 | { |
| 87 | int err; | 114 | int err; |
| 88 | struct netdev_hw_addr *ha, *ha2; | 115 | struct netdev_hw_addr *ha, *ha2; |
| @@ -105,11 +132,11 @@ unroll: | |||
| 105 | } | 132 | } |
| 106 | return err; | 133 | return err; |
| 107 | } | 134 | } |
| 135 | EXPORT_SYMBOL(__hw_addr_add_multiple); | ||
| 108 | 136 | ||
| 109 | static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, | 137 | void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, |
| 110 | struct netdev_hw_addr_list *from_list, | 138 | struct netdev_hw_addr_list *from_list, |
| 111 | int addr_len, | 139 | int addr_len, unsigned char addr_type) |
| 112 | unsigned char addr_type) | ||
| 113 | { | 140 | { |
| 114 | struct netdev_hw_addr *ha; | 141 | struct netdev_hw_addr *ha; |
| 115 | unsigned char type; | 142 | unsigned char type; |
| @@ -119,10 +146,11 @@ static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, | |||
| 119 | __hw_addr_del(to_list, ha->addr, addr_len, addr_type); | 146 | __hw_addr_del(to_list, ha->addr, addr_len, addr_type); |
| 120 | } | 147 | } |
| 121 | } | 148 | } |
| 149 | EXPORT_SYMBOL(__hw_addr_del_multiple); | ||
| 122 | 150 | ||
| 123 | static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, | 151 | int __hw_addr_sync(struct netdev_hw_addr_list *to_list, |
| 124 | struct netdev_hw_addr_list *from_list, | 152 | struct netdev_hw_addr_list *from_list, |
| 125 | int addr_len) | 153 | int addr_len) |
| 126 | { | 154 | { |
| 127 | int err = 0; | 155 | int err = 0; |
| 128 | struct netdev_hw_addr *ha, *tmp; | 156 | struct netdev_hw_addr *ha, *tmp; |
| @@ -142,10 +170,11 @@ static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, | |||
| 142 | } | 170 | } |
| 143 | return err; | 171 | return err; |
| 144 | } | 172 | } |
| 173 | EXPORT_SYMBOL(__hw_addr_sync); | ||
| 145 | 174 | ||
| 146 | static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, | 175 | void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, |
| 147 | struct netdev_hw_addr_list *from_list, | 176 | struct netdev_hw_addr_list *from_list, |
| 148 | int addr_len) | 177 | int addr_len) |
| 149 | { | 178 | { |
| 150 | struct netdev_hw_addr *ha, *tmp; | 179 | struct netdev_hw_addr *ha, *tmp; |
| 151 | 180 | ||
| @@ -159,8 +188,9 @@ static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, | |||
| 159 | } | 188 | } |
| 160 | } | 189 | } |
| 161 | } | 190 | } |
| 191 | EXPORT_SYMBOL(__hw_addr_unsync); | ||
| 162 | 192 | ||
| 163 | static void __hw_addr_flush(struct netdev_hw_addr_list *list) | 193 | void __hw_addr_flush(struct netdev_hw_addr_list *list) |
| 164 | { | 194 | { |
| 165 | struct netdev_hw_addr *ha, *tmp; | 195 | struct netdev_hw_addr *ha, *tmp; |
| 166 | 196 | ||
| @@ -170,12 +200,14 @@ static void __hw_addr_flush(struct netdev_hw_addr_list *list) | |||
| 170 | } | 200 | } |
| 171 | list->count = 0; | 201 | list->count = 0; |
| 172 | } | 202 | } |
| 203 | EXPORT_SYMBOL(__hw_addr_flush); | ||
| 173 | 204 | ||
| 174 | static void __hw_addr_init(struct netdev_hw_addr_list *list) | 205 | void __hw_addr_init(struct netdev_hw_addr_list *list) |
| 175 | { | 206 | { |
| 176 | INIT_LIST_HEAD(&list->list); | 207 | INIT_LIST_HEAD(&list->list); |
| 177 | list->count = 0; | 208 | list->count = 0; |
| 178 | } | 209 | } |
| 210 | EXPORT_SYMBOL(__hw_addr_init); | ||
| 179 | 211 | ||
| 180 | /* | 212 | /* |
| 181 | * Device addresses handling functions | 213 | * Device addresses handling functions |
| @@ -475,4 +507,235 @@ EXPORT_SYMBOL(dev_uc_init); | |||
| 475 | * Multicast list handling functions | 507 | * Multicast list handling functions |
| 476 | */ | 508 | */ |
| 477 | 509 | ||
| 478 | /* To be filled here */ | 510 | static int __dev_mc_add(struct net_device *dev, unsigned char *addr, |
| 511 | bool global) | ||
| 512 | { | ||
| 513 | int err; | ||
| 514 | |||
| 515 | netif_addr_lock_bh(dev); | ||
| 516 | err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, | ||
| 517 | NETDEV_HW_ADDR_T_MULTICAST, global); | ||
| 518 | if (!err) | ||
| 519 | __dev_set_rx_mode(dev); | ||
| 520 | netif_addr_unlock_bh(dev); | ||
| 521 | return err; | ||
| 522 | } | ||
| 523 | /** | ||
| 524 | * dev_mc_add - Add a multicast address | ||
| 525 | * @dev: device | ||
| 526 | * @addr: address to add | ||
| 527 | * | ||
| 528 | * Add a multicast address to the device or increase | ||
| 529 | * the reference count if it already exists. | ||
| 530 | */ | ||
| 531 | int dev_mc_add(struct net_device *dev, unsigned char *addr) | ||
| 532 | { | ||
| 533 | return __dev_mc_add(dev, addr, false); | ||
| 534 | } | ||
| 535 | EXPORT_SYMBOL(dev_mc_add); | ||
| 536 | |||
| 537 | /** | ||
| 538 | * dev_mc_add_global - Add a global multicast address | ||
| 539 | * @dev: device | ||
| 540 | * @addr: address to add | ||
| 541 | * | ||
| 542 | * Add a global multicast address to the device. | ||
| 543 | */ | ||
| 544 | int dev_mc_add_global(struct net_device *dev, unsigned char *addr) | ||
| 545 | { | ||
| 546 | return __dev_mc_add(dev, addr, true); | ||
| 547 | } | ||
| 548 | EXPORT_SYMBOL(dev_mc_add_global); | ||
| 549 | |||
| 550 | static int __dev_mc_del(struct net_device *dev, unsigned char *addr, | ||
| 551 | bool global) | ||
| 552 | { | ||
| 553 | int err; | ||
| 554 | |||
| 555 | netif_addr_lock_bh(dev); | ||
| 556 | err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len, | ||
| 557 | NETDEV_HW_ADDR_T_MULTICAST, global); | ||
| 558 | if (!err) | ||
| 559 | __dev_set_rx_mode(dev); | ||
| 560 | netif_addr_unlock_bh(dev); | ||
| 561 | return err; | ||
| 562 | } | ||
| 563 | |||
| 564 | /** | ||
| 565 | * dev_mc_del - Delete a multicast address. | ||
| 566 | * @dev: device | ||
| 567 | * @addr: address to delete | ||
| 568 | * | ||
| 569 | * Release reference to a multicast address and remove it | ||
| 570 | * from the device if the reference count drops to zero. | ||
| 571 | */ | ||
| 572 | int dev_mc_del(struct net_device *dev, unsigned char *addr) | ||
| 573 | { | ||
| 574 | return __dev_mc_del(dev, addr, false); | ||
| 575 | } | ||
| 576 | EXPORT_SYMBOL(dev_mc_del); | ||
| 577 | |||
| 578 | /** | ||
| 579 | * dev_mc_del_global - Delete a global multicast address. | ||
| 580 | * @dev: device | ||
| 581 | * @addr: address to delete | ||
| 582 | * | ||
| 583 | * Release reference to a multicast address and remove it | ||
| 584 | * from the device if the reference count drops to zero. | ||
| 585 | */ | ||
| 586 | int dev_mc_del_global(struct net_device *dev, unsigned char *addr) | ||
| 587 | { | ||
| 588 | return __dev_mc_del(dev, addr, true); | ||
| 589 | } | ||
| 590 | EXPORT_SYMBOL(dev_mc_del_global); | ||
| 591 | |||
| 592 | /** | ||
| 593 | * dev_mc_sync - Synchronize device's unicast list to another device | ||
| 594 | * @to: destination device | ||
| 595 | * @from: source device | ||
| 596 | * | ||
| 597 | * Add newly added addresses to the destination device and release | ||
| 598 | * addresses that have no users left. The source device must be | ||
| 599 | * locked by netif_tx_lock_bh. | ||
| 600 | * | ||
| 601 | * This function is intended to be called from the dev->set_multicast_list | ||
| 602 | * or dev->set_rx_mode function of layered software devices. | ||
| 603 | */ | ||
| 604 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
| 605 | { | ||
| 606 | int err = 0; | ||
| 607 | |||
| 608 | if (to->addr_len != from->addr_len) | ||
| 609 | return -EINVAL; | ||
| 610 | |||
| 611 | netif_addr_lock_bh(to); | ||
| 612 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | ||
| 613 | if (!err) | ||
| 614 | __dev_set_rx_mode(to); | ||
| 615 | netif_addr_unlock_bh(to); | ||
| 616 | return err; | ||
| 617 | } | ||
| 618 | EXPORT_SYMBOL(dev_mc_sync); | ||
| 619 | |||
| 620 | /** | ||
| 621 | * dev_mc_unsync - Remove synchronized addresses from the destination device | ||
| 622 | * @to: destination device | ||
| 623 | * @from: source device | ||
| 624 | * | ||
| 625 | * Remove all addresses that were added to the destination device by | ||
| 626 | * dev_mc_sync(). This function is intended to be called from the | ||
| 627 | * dev->stop function of layered software devices. | ||
| 628 | */ | ||
| 629 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
| 630 | { | ||
| 631 | if (to->addr_len != from->addr_len) | ||
| 632 | return; | ||
| 633 | |||
| 634 | netif_addr_lock_bh(from); | ||
| 635 | netif_addr_lock(to); | ||
| 636 | __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); | ||
| 637 | __dev_set_rx_mode(to); | ||
| 638 | netif_addr_unlock(to); | ||
| 639 | netif_addr_unlock_bh(from); | ||
| 640 | } | ||
| 641 | EXPORT_SYMBOL(dev_mc_unsync); | ||
| 642 | |||
| 643 | /** | ||
| 644 | * dev_mc_flush - Flush multicast addresses | ||
| 645 | * @dev: device | ||
| 646 | * | ||
| 647 | * Flush multicast addresses. | ||
| 648 | */ | ||
| 649 | void dev_mc_flush(struct net_device *dev) | ||
| 650 | { | ||
| 651 | netif_addr_lock_bh(dev); | ||
| 652 | __hw_addr_flush(&dev->mc); | ||
| 653 | netif_addr_unlock_bh(dev); | ||
| 654 | } | ||
| 655 | EXPORT_SYMBOL(dev_mc_flush); | ||
| 656 | |||
| 657 | /** | ||
| 658 | * dev_mc_flush - Init multicast address list | ||
| 659 | * @dev: device | ||
| 660 | * | ||
| 661 | * Init multicast address list. | ||
| 662 | */ | ||
| 663 | void dev_mc_init(struct net_device *dev) | ||
| 664 | { | ||
| 665 | __hw_addr_init(&dev->mc); | ||
| 666 | } | ||
| 667 | EXPORT_SYMBOL(dev_mc_init); | ||
| 668 | |||
| 669 | #ifdef CONFIG_PROC_FS | ||
| 670 | #include <linux/proc_fs.h> | ||
| 671 | #include <linux/seq_file.h> | ||
| 672 | |||
| 673 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | ||
| 674 | { | ||
| 675 | struct netdev_hw_addr *ha; | ||
| 676 | struct net_device *dev = v; | ||
| 677 | |||
| 678 | if (v == SEQ_START_TOKEN) | ||
| 679 | return 0; | ||
| 680 | |||
| 681 | netif_addr_lock_bh(dev); | ||
| 682 | netdev_for_each_mc_addr(ha, dev) { | ||
| 683 | int i; | ||
| 684 | |||
| 685 | seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, | ||
| 686 | dev->name, ha->refcount, ha->global_use); | ||
| 687 | |||
| 688 | for (i = 0; i < dev->addr_len; i++) | ||
| 689 | seq_printf(seq, "%02x", ha->addr[i]); | ||
| 690 | |||
| 691 | seq_putc(seq, '\n'); | ||
| 692 | } | ||
| 693 | netif_addr_unlock_bh(dev); | ||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | static const struct seq_operations dev_mc_seq_ops = { | ||
| 698 | .start = dev_seq_start, | ||
| 699 | .next = dev_seq_next, | ||
| 700 | .stop = dev_seq_stop, | ||
| 701 | .show = dev_mc_seq_show, | ||
| 702 | }; | ||
| 703 | |||
| 704 | static int dev_mc_seq_open(struct inode *inode, struct file *file) | ||
| 705 | { | ||
| 706 | return seq_open_net(inode, file, &dev_mc_seq_ops, | ||
| 707 | sizeof(struct seq_net_private)); | ||
| 708 | } | ||
| 709 | |||
| 710 | static const struct file_operations dev_mc_seq_fops = { | ||
| 711 | .owner = THIS_MODULE, | ||
| 712 | .open = dev_mc_seq_open, | ||
| 713 | .read = seq_read, | ||
| 714 | .llseek = seq_lseek, | ||
| 715 | .release = seq_release_net, | ||
| 716 | }; | ||
| 717 | |||
| 718 | #endif | ||
| 719 | |||
| 720 | static int __net_init dev_mc_net_init(struct net *net) | ||
| 721 | { | ||
| 722 | if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) | ||
| 723 | return -ENOMEM; | ||
| 724 | return 0; | ||
| 725 | } | ||
| 726 | |||
| 727 | static void __net_exit dev_mc_net_exit(struct net *net) | ||
| 728 | { | ||
| 729 | proc_net_remove(net, "dev_mcast"); | ||
| 730 | } | ||
| 731 | |||
| 732 | static struct pernet_operations __net_initdata dev_mc_net_ops = { | ||
| 733 | .init = dev_mc_net_init, | ||
| 734 | .exit = dev_mc_net_exit, | ||
| 735 | }; | ||
| 736 | |||
| 737 | void __init dev_mcast_init(void) | ||
| 738 | { | ||
| 739 | register_pernet_subsys(&dev_mc_net_ops); | ||
| 740 | } | ||
| 741 | |||
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c deleted file mode 100644 index 3dc295beb483..000000000000 --- a/net/core/dev_mcast.c +++ /dev/null | |||
| @@ -1,232 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Linux NET3: Multicast List maintenance. | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Tim Kordas <tjk@nostromo.eeap.cwru.edu> | ||
| 6 | * Richard Underwood <richard@wuzz.demon.co.uk> | ||
| 7 | * | ||
| 8 | * Stir fried together from the IP multicast and CAP patches above | ||
| 9 | * Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
| 10 | * | ||
| 11 | * Fixes: | ||
| 12 | * Alan Cox : Update the device on a real delete | ||
| 13 | * rather than any time but... | ||
| 14 | * Alan Cox : IFF_ALLMULTI support. | ||
| 15 | * Alan Cox : New format set_multicast_list() calls. | ||
| 16 | * Gleb Natapov : Remove dev_mc_lock. | ||
| 17 | * | ||
| 18 | * This program is free software; you can redistribute it and/or | ||
| 19 | * modify it under the terms of the GNU General Public License | ||
| 20 | * as published by the Free Software Foundation; either version | ||
| 21 | * 2 of the License, or (at your option) any later version. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <asm/uaccess.h> | ||
| 26 | #include <asm/system.h> | ||
| 27 | #include <linux/bitops.h> | ||
| 28 | #include <linux/types.h> | ||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/mm.h> | ||
| 32 | #include <linux/socket.h> | ||
| 33 | #include <linux/sockios.h> | ||
| 34 | #include <linux/in.h> | ||
| 35 | #include <linux/errno.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/if_ether.h> | ||
| 38 | #include <linux/inet.h> | ||
| 39 | #include <linux/netdevice.h> | ||
| 40 | #include <linux/etherdevice.h> | ||
| 41 | #include <linux/proc_fs.h> | ||
| 42 | #include <linux/seq_file.h> | ||
| 43 | #include <linux/init.h> | ||
| 44 | #include <net/net_namespace.h> | ||
| 45 | #include <net/ip.h> | ||
| 46 | #include <net/route.h> | ||
| 47 | #include <linux/skbuff.h> | ||
| 48 | #include <net/sock.h> | ||
| 49 | #include <net/arp.h> | ||
| 50 | |||
| 51 | |||
| 52 | /* | ||
| 53 | * Device multicast list maintenance. | ||
| 54 | * | ||
| 55 | * This is used both by IP and by the user level maintenance functions. | ||
| 56 | * Unlike BSD we maintain a usage count on a given multicast address so | ||
| 57 | * that a casual user application can add/delete multicasts used by | ||
| 58 | * protocols without doing damage to the protocols when it deletes the | ||
| 59 | * entries. It also helps IP as it tracks overlapping maps. | ||
| 60 | * | ||
| 61 | * Device mc lists are changed by bh at least if IPv6 is enabled, | ||
| 62 | * so that it must be bh protected. | ||
| 63 | * | ||
| 64 | * We block accesses to device mc filters with netif_tx_lock. | ||
| 65 | */ | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Delete a device level multicast | ||
| 69 | */ | ||
| 70 | |||
| 71 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | ||
| 72 | { | ||
| 73 | int err; | ||
| 74 | |||
| 75 | netif_addr_lock_bh(dev); | ||
| 76 | err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, | ||
| 77 | addr, alen, glbl); | ||
| 78 | if (!err) { | ||
| 79 | /* | ||
| 80 | * We have altered the list, so the card | ||
| 81 | * loaded filter is now wrong. Fix it | ||
| 82 | */ | ||
| 83 | |||
| 84 | __dev_set_rx_mode(dev); | ||
| 85 | } | ||
| 86 | netif_addr_unlock_bh(dev); | ||
| 87 | return err; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Add a device level multicast | ||
| 92 | */ | ||
| 93 | |||
| 94 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | ||
| 95 | { | ||
| 96 | int err; | ||
| 97 | |||
| 98 | netif_addr_lock_bh(dev); | ||
| 99 | if (alen != dev->addr_len) | ||
| 100 | err = -EINVAL; | ||
| 101 | else | ||
| 102 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); | ||
| 103 | if (!err) | ||
| 104 | __dev_set_rx_mode(dev); | ||
| 105 | netif_addr_unlock_bh(dev); | ||
| 106 | return err; | ||
| 107 | } | ||
| 108 | |||
| 109 | /** | ||
| 110 | * dev_mc_sync - Synchronize device's multicast list to another device | ||
| 111 | * @to: destination device | ||
| 112 | * @from: source device | ||
| 113 | * | ||
| 114 | * Add newly added addresses to the destination device and release | ||
| 115 | * addresses that have no users left. The source device must be | ||
| 116 | * locked by netif_tx_lock_bh. | ||
| 117 | * | ||
| 118 | * This function is intended to be called from the dev->set_multicast_list | ||
| 119 | * or dev->set_rx_mode function of layered software devices. | ||
| 120 | */ | ||
| 121 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
| 122 | { | ||
| 123 | int err = 0; | ||
| 124 | |||
| 125 | netif_addr_lock_bh(to); | ||
| 126 | err = __dev_addr_sync(&to->mc_list, &to->mc_count, | ||
| 127 | &from->mc_list, &from->mc_count); | ||
| 128 | if (!err) | ||
| 129 | __dev_set_rx_mode(to); | ||
| 130 | netif_addr_unlock_bh(to); | ||
| 131 | |||
| 132 | return err; | ||
| 133 | } | ||
| 134 | EXPORT_SYMBOL(dev_mc_sync); | ||
| 135 | |||
| 136 | |||
| 137 | /** | ||
| 138 | * dev_mc_unsync - Remove synchronized addresses from the destination | ||
| 139 | * device | ||
| 140 | * @to: destination device | ||
| 141 | * @from: source device | ||
| 142 | * | ||
| 143 | * Remove all addresses that were added to the destination device by | ||
| 144 | * dev_mc_sync(). This function is intended to be called from the | ||
| 145 | * dev->stop function of layered software devices. | ||
| 146 | */ | ||
| 147 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
| 148 | { | ||
| 149 | netif_addr_lock_bh(from); | ||
| 150 | netif_addr_lock(to); | ||
| 151 | |||
| 152 | __dev_addr_unsync(&to->mc_list, &to->mc_count, | ||
| 153 | &from->mc_list, &from->mc_count); | ||
| 154 | __dev_set_rx_mode(to); | ||
| 155 | |||
| 156 | netif_addr_unlock(to); | ||
| 157 | netif_addr_unlock_bh(from); | ||
| 158 | } | ||
| 159 | EXPORT_SYMBOL(dev_mc_unsync); | ||
| 160 | |||
| 161 | #ifdef CONFIG_PROC_FS | ||
| 162 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | ||
| 163 | { | ||
| 164 | struct dev_addr_list *m; | ||
| 165 | struct net_device *dev = v; | ||
| 166 | |||
| 167 | if (v == SEQ_START_TOKEN) | ||
| 168 | return 0; | ||
| 169 | |||
| 170 | netif_addr_lock_bh(dev); | ||
| 171 | for (m = dev->mc_list; m; m = m->next) { | ||
| 172 | int i; | ||
| 173 | |||
| 174 | seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, | ||
| 175 | dev->name, m->dmi_users, m->dmi_gusers); | ||
| 176 | |||
| 177 | for (i = 0; i < m->dmi_addrlen; i++) | ||
| 178 | seq_printf(seq, "%02x", m->dmi_addr[i]); | ||
| 179 | |||
| 180 | seq_putc(seq, '\n'); | ||
| 181 | } | ||
| 182 | netif_addr_unlock_bh(dev); | ||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static const struct seq_operations dev_mc_seq_ops = { | ||
| 187 | .start = dev_seq_start, | ||
| 188 | .next = dev_seq_next, | ||
| 189 | .stop = dev_seq_stop, | ||
| 190 | .show = dev_mc_seq_show, | ||
| 191 | }; | ||
| 192 | |||
| 193 | static int dev_mc_seq_open(struct inode *inode, struct file *file) | ||
| 194 | { | ||
| 195 | return seq_open_net(inode, file, &dev_mc_seq_ops, | ||
| 196 | sizeof(struct seq_net_private)); | ||
| 197 | } | ||
| 198 | |||
| 199 | static const struct file_operations dev_mc_seq_fops = { | ||
| 200 | .owner = THIS_MODULE, | ||
| 201 | .open = dev_mc_seq_open, | ||
| 202 | .read = seq_read, | ||
| 203 | .llseek = seq_lseek, | ||
| 204 | .release = seq_release_net, | ||
| 205 | }; | ||
| 206 | |||
| 207 | #endif | ||
| 208 | |||
| 209 | static int __net_init dev_mc_net_init(struct net *net) | ||
| 210 | { | ||
| 211 | if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) | ||
| 212 | return -ENOMEM; | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static void __net_exit dev_mc_net_exit(struct net *net) | ||
| 217 | { | ||
| 218 | proc_net_remove(net, "dev_mcast"); | ||
| 219 | } | ||
| 220 | |||
| 221 | static struct pernet_operations __net_initdata dev_mc_net_ops = { | ||
| 222 | .init = dev_mc_net_init, | ||
| 223 | .exit = dev_mc_net_exit, | ||
| 224 | }; | ||
| 225 | |||
| 226 | void __init dev_mcast_init(void) | ||
| 227 | { | ||
| 228 | register_pernet_subsys(&dev_mc_net_ops); | ||
| 229 | } | ||
| 230 | |||
| 231 | EXPORT_SYMBOL(dev_mc_add); | ||
| 232 | EXPORT_SYMBOL(dev_mc_delete); | ||
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 238af093495b..f3e4734d207f 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
| @@ -349,7 +349,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de | |||
| 349 | if (dn_db->dev->type == ARPHRD_ETHER) { | 349 | if (dn_db->dev->type == ARPHRD_ETHER) { |
| 350 | if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { | 350 | if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { |
| 351 | dn_dn2eth(mac_addr, ifa1->ifa_local); | 351 | dn_dn2eth(mac_addr, ifa1->ifa_local); |
| 352 | dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); | 352 | dev_mc_del(dev, mac_addr); |
| 353 | } | 353 | } |
| 354 | } | 354 | } |
| 355 | 355 | ||
| @@ -380,7 +380,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
| 380 | if (dev->type == ARPHRD_ETHER) { | 380 | if (dev->type == ARPHRD_ETHER) { |
| 381 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { | 381 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { |
| 382 | dn_dn2eth(mac_addr, ifa->ifa_local); | 382 | dn_dn2eth(mac_addr, ifa->ifa_local); |
| 383 | dev_mc_add(dev, mac_addr, ETH_ALEN, 0); | 383 | dev_mc_add(dev, mac_addr); |
| 384 | } | 384 | } |
| 385 | } | 385 | } |
| 386 | 386 | ||
| @@ -1000,9 +1000,9 @@ static int dn_eth_up(struct net_device *dev) | |||
| 1000 | struct dn_dev *dn_db = dev->dn_ptr; | 1000 | struct dn_dev *dn_db = dev->dn_ptr; |
| 1001 | 1001 | ||
| 1002 | if (dn_db->parms.forwarding == 0) | 1002 | if (dn_db->parms.forwarding == 0) |
| 1003 | dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); | 1003 | dev_mc_add(dev, dn_rt_all_end_mcast); |
| 1004 | else | 1004 | else |
| 1005 | dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); | 1005 | dev_mc_add(dev, dn_rt_all_rt_mcast); |
| 1006 | 1006 | ||
| 1007 | dn_db->use_long = 1; | 1007 | dn_db->use_long = 1; |
| 1008 | 1008 | ||
| @@ -1014,9 +1014,9 @@ static void dn_eth_down(struct net_device *dev) | |||
| 1014 | struct dn_dev *dn_db = dev->dn_ptr; | 1014 | struct dn_dev *dn_db = dev->dn_ptr; |
| 1015 | 1015 | ||
| 1016 | if (dn_db->parms.forwarding == 0) | 1016 | if (dn_db->parms.forwarding == 0) |
| 1017 | dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); | 1017 | dev_mc_del(dev, dn_rt_all_end_mcast); |
| 1018 | else | 1018 | else |
| 1019 | dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); | 1019 | dev_mc_del(dev, dn_rt_all_rt_mcast); |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | static void dn_dev_set_timer(struct net_device *dev); | 1022 | static void dn_dev_set_timer(struct net_device *dev); |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 63bf298ca109..51824c42b775 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
| @@ -997,7 +997,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr) | |||
| 997 | --ANK | 997 | --ANK |
| 998 | */ | 998 | */ |
| 999 | if (arp_mc_map(addr, buf, dev, 0) == 0) | 999 | if (arp_mc_map(addr, buf, dev, 0) == 0) |
| 1000 | dev_mc_add(dev, buf, dev->addr_len, 0); | 1000 | dev_mc_add(dev, buf); |
| 1001 | } | 1001 | } |
| 1002 | 1002 | ||
| 1003 | /* | 1003 | /* |
| @@ -1010,7 +1010,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr) | |||
| 1010 | struct net_device *dev = in_dev->dev; | 1010 | struct net_device *dev = in_dev->dev; |
| 1011 | 1011 | ||
| 1012 | if (arp_mc_map(addr, buf, dev, 0) == 0) | 1012 | if (arp_mc_map(addr, buf, dev, 0) == 0) |
| 1013 | dev_mc_delete(dev, buf, dev->addr_len, 0); | 1013 | dev_mc_del(dev, buf); |
| 1014 | } | 1014 | } |
| 1015 | 1015 | ||
| 1016 | #ifdef CONFIG_IP_MULTICAST | 1016 | #ifdef CONFIG_IP_MULTICAST |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 0886f96c736b..a2208b7b313d 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
| @@ -87,7 +87,7 @@ clusterip_config_entry_put(struct clusterip_config *c) | |||
| 87 | list_del(&c->list); | 87 | list_del(&c->list); |
| 88 | write_unlock_bh(&clusterip_lock); | 88 | write_unlock_bh(&clusterip_lock); |
| 89 | 89 | ||
| 90 | dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); | 90 | dev_mc_del(c->dev, c->clustermac); |
| 91 | dev_put(c->dev); | 91 | dev_put(c->dev); |
| 92 | 92 | ||
| 93 | /* In case anyone still accesses the file, the open/close | 93 | /* In case anyone still accesses the file, the open/close |
| @@ -396,7 +396,7 @@ static bool clusterip_tg_check(const struct xt_tgchk_param *par) | |||
| 396 | dev_put(dev); | 396 | dev_put(dev); |
| 397 | return false; | 397 | return false; |
| 398 | } | 398 | } |
| 399 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); | 399 | dev_mc_add(config->dev, config->clustermac); |
| 400 | } | 400 | } |
| 401 | } | 401 | } |
| 402 | cipinfo->config = config; | 402 | cipinfo->config = config; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index bcd971915969..37d1868c0064 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -714,7 +714,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc) | |||
| 714 | if (!(mc->mca_flags&MAF_LOADED)) { | 714 | if (!(mc->mca_flags&MAF_LOADED)) { |
| 715 | mc->mca_flags |= MAF_LOADED; | 715 | mc->mca_flags |= MAF_LOADED; |
| 716 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 716 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
| 717 | dev_mc_add(dev, buf, dev->addr_len, 0); | 717 | dev_mc_add(dev, buf); |
| 718 | } | 718 | } |
| 719 | spin_unlock_bh(&mc->mca_lock); | 719 | spin_unlock_bh(&mc->mca_lock); |
| 720 | 720 | ||
| @@ -740,7 +740,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc) | |||
| 740 | if (mc->mca_flags&MAF_LOADED) { | 740 | if (mc->mca_flags&MAF_LOADED) { |
| 741 | mc->mca_flags &= ~MAF_LOADED; | 741 | mc->mca_flags &= ~MAF_LOADED; |
| 742 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 742 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
| 743 | dev_mc_delete(dev, buf, dev->addr_len, 0); | 743 | dev_mc_del(dev, buf); |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | if (mc->mca_flags & MAF_NOREPORT) | 746 | if (mc->mca_flags & MAF_NOREPORT) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index c3d844093a2f..9179196da264 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -84,16 +84,14 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
| 87 | int mc_count, | 87 | struct netdev_hw_addr_list *mc_list) |
| 88 | struct dev_addr_list *mc_list) | ||
| 89 | { | 88 | { |
| 90 | u64 ret = 0; | 89 | u64 ret = 0; |
| 91 | 90 | ||
| 92 | if (local->ops->prepare_multicast) | 91 | if (local->ops->prepare_multicast) |
| 93 | ret = local->ops->prepare_multicast(&local->hw, mc_count, | 92 | ret = local->ops->prepare_multicast(&local->hw, mc_list); |
| 94 | mc_list); | ||
| 95 | 93 | ||
| 96 | trace_drv_prepare_multicast(local, mc_count, ret); | 94 | trace_drv_prepare_multicast(local, mc_list->count, ret); |
| 97 | 95 | ||
| 98 | return ret; | 96 | return ret; |
| 99 | } | 97 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ab369e2a5282..7fdacf9408b1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -646,8 +646,7 @@ struct ieee80211_local { | |||
| 646 | struct work_struct recalc_smps; | 646 | struct work_struct recalc_smps; |
| 647 | 647 | ||
| 648 | /* aggregated multicast list */ | 648 | /* aggregated multicast list */ |
| 649 | struct dev_addr_list *mc_list; | 649 | struct netdev_hw_addr_list mc_list; |
| 650 | int mc_count; | ||
| 651 | 650 | ||
| 652 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 651 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
| 653 | 652 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b4ec59a8dc03..00f3a93c6b04 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -412,8 +412,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 412 | 412 | ||
| 413 | netif_addr_lock_bh(dev); | 413 | netif_addr_lock_bh(dev); |
| 414 | spin_lock_bh(&local->filter_lock); | 414 | spin_lock_bh(&local->filter_lock); |
| 415 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | 415 | __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len); |
| 416 | &dev->mc_list, &dev->mc_count); | ||
| 417 | spin_unlock_bh(&local->filter_lock); | 416 | spin_unlock_bh(&local->filter_lock); |
| 418 | netif_addr_unlock_bh(dev); | 417 | netif_addr_unlock_bh(dev); |
| 419 | 418 | ||
| @@ -596,8 +595,7 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
| 596 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 595 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
| 597 | } | 596 | } |
| 598 | spin_lock_bh(&local->filter_lock); | 597 | spin_lock_bh(&local->filter_lock); |
| 599 | __dev_addr_sync(&local->mc_list, &local->mc_count, | 598 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
| 600 | &dev->mc_list, &dev->mc_count); | ||
| 601 | spin_unlock_bh(&local->filter_lock); | 599 | spin_unlock_bh(&local->filter_lock); |
| 602 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 600 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); |
| 603 | } | 601 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e5..84ad249a4e2e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -71,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
| 71 | spin_lock_bh(&local->filter_lock); | 71 | spin_lock_bh(&local->filter_lock); |
| 72 | changed_flags = local->filter_flags ^ new_flags; | 72 | changed_flags = local->filter_flags ^ new_flags; |
| 73 | 73 | ||
| 74 | mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); | 74 | mc = drv_prepare_multicast(local, &local->mc_list); |
| 75 | spin_unlock_bh(&local->filter_lock); | 75 | spin_unlock_bh(&local->filter_lock); |
| 76 | 76 | ||
| 77 | /* be a bit nasty */ | 77 | /* be a bit nasty */ |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 48c1e0ae565f..b0f037cc899c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -1691,9 +1691,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
| 1691 | if (i->alen != dev->addr_len) | 1691 | if (i->alen != dev->addr_len) |
| 1692 | return -EINVAL; | 1692 | return -EINVAL; |
| 1693 | if (what > 0) | 1693 | if (what > 0) |
| 1694 | return dev_mc_add(dev, i->addr, i->alen, 0); | 1694 | return dev_mc_add(dev, i->addr); |
| 1695 | else | 1695 | else |
| 1696 | return dev_mc_delete(dev, i->addr, i->alen, 0); | 1696 | return dev_mc_del(dev, i->addr); |
| 1697 | break; | 1697 | break; |
| 1698 | case PACKET_MR_PROMISC: | 1698 | case PACKET_MR_PROMISC: |
| 1699 | return dev_set_promiscuity(dev, what); | 1699 | return dev_set_promiscuity(dev, what); |
