Blame view
net/core/dev_mcast.c
5.52 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
4ec93edb1 [NET] CORE: Fix w... |
2 |
* Linux NET3: Multicast List maintenance. |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* * Authors: |
4ec93edb1 [NET] CORE: Fix w... |
5 |
* Tim Kordas <tjk@nostromo.eeap.cwru.edu> |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 |
* Richard Underwood <richard@wuzz.demon.co.uk> * * Stir fried together from the IP multicast and CAP patches above |
113aa838e net: Rationalise ... |
9 |
* Alan Cox <alan@lxorguk.ukuu.org.uk> |
1da177e4c Linux-2.6.12-rc2 |
10 11 12 13 14 15 16 17 18 19 20 21 22 |
* * Fixes: * Alan Cox : Update the device on a real delete * rather than any time but... * Alan Cox : IFF_ALLMULTI support. * Alan Cox : New format set_multicast_list() calls. * Gleb Natapov : Remove dev_mc_lock. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
bf0d52492 [NET]: Remove unn... |
23 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 |
#include <asm/uaccess.h> #include <asm/system.h> #include <linux/bitops.h> #include <linux/types.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <linux/string.h> #include <linux/mm.h> #include <linux/socket.h> #include <linux/sockios.h> #include <linux/in.h> #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/if_ether.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/init.h> |
457c4cbc5 [NET]: Make /proc... |
43 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 49 50 51 |
#include <net/ip.h> #include <net/route.h> #include <linux/skbuff.h> #include <net/sock.h> #include <net/arp.h> /* |
4ec93edb1 [NET] CORE: Fix w... |
52 |
* Device multicast list maintenance. |
1da177e4c Linux-2.6.12-rc2 |
53 |
* |
4ec93edb1 [NET] CORE: Fix w... |
54 55 56 |
* This is used both by IP and by the user level maintenance functions. * Unlike BSD we maintain a usage count on a given multicast address so * that a casual user application can add/delete multicasts used by |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 60 61 62 |
* protocols without doing damage to the protocols when it deletes the * entries. It also helps IP as it tracks overlapping maps. * * Device mc lists are changed by bh at least if IPv6 is enabled, * so that it must be bh protected. * |
932ff279a [NET]: Add netif_... |
63 |
* We block accesses to device mc filters with netif_tx_lock. |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 |
*/ /* |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
* Delete a device level multicast */ |
4ec93edb1 [NET] CORE: Fix w... |
69 |
|
1da177e4c Linux-2.6.12-rc2 |
70 71 |
int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) { |
3fba5a8b1 [NET]: dev_mcast:... |
72 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
73 |
|
b9e408576 netdev: Do not us... |
74 |
netif_addr_lock_bh(dev); |
61cbc2fca [NET]: Fix second... |
75 76 |
err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, addr, alen, glbl); |
3fba5a8b1 [NET]: dev_mcast:... |
77 |
if (!err) { |
1da177e4c Linux-2.6.12-rc2 |
78 |
/* |
3fba5a8b1 [NET]: dev_mcast:... |
79 80 |
* We have altered the list, so the card * loaded filter is now wrong. Fix it |
1da177e4c Linux-2.6.12-rc2 |
81 |
*/ |
3fba5a8b1 [NET]: dev_mcast:... |
82 |
|
4417da668 [NET]: dev: secon... |
83 |
__dev_set_rx_mode(dev); |
1da177e4c Linux-2.6.12-rc2 |
84 |
} |
b9e408576 netdev: Do not us... |
85 |
netif_addr_unlock_bh(dev); |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 89 90 91 |
return err; } /* * Add a device level multicast */ |
4ec93edb1 [NET] CORE: Fix w... |
92 |
|
1da177e4c Linux-2.6.12-rc2 |
93 94 |
int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) { |
3fba5a8b1 [NET]: dev_mcast:... |
95 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
96 |
|
b9e408576 netdev: Do not us... |
97 |
netif_addr_lock_bh(dev); |
61cbc2fca [NET]: Fix second... |
98 99 |
err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); if (!err) |
4417da668 [NET]: dev: secon... |
100 |
__dev_set_rx_mode(dev); |
b9e408576 netdev: Do not us... |
101 |
netif_addr_unlock_bh(dev); |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
return err; } |
a0a400d79 [NET]: dev_mcast:... |
104 105 106 107 108 109 110 111 112 113 |
/** * dev_mc_sync - Synchronize device's multicast list to another device * @to: destination device * @from: source device * * Add newly added addresses to the destination device and release * addresses that have no users left. The source device must be * locked by netif_tx_lock_bh. * * This function is intended to be called from the dev->set_multicast_list |
e83a2ea85 [VLAN]: set_rx_mo... |
114 |
* or dev->set_rx_mode function of layered software devices. |
a0a400d79 [NET]: dev_mcast:... |
115 116 117 |
*/ int dev_mc_sync(struct net_device *to, struct net_device *from) { |
a0a400d79 [NET]: dev_mcast:... |
118 |
int err = 0; |
b9e408576 netdev: Do not us... |
119 |
netif_addr_lock_bh(to); |
e83a2ea85 [VLAN]: set_rx_mo... |
120 121 |
err = __dev_addr_sync(&to->mc_list, &to->mc_count, &from->mc_list, &from->mc_count); |
a0a400d79 [NET]: dev_mcast:... |
122 123 |
if (!err) __dev_set_rx_mode(to); |
b9e408576 netdev: Do not us... |
124 |
netif_addr_unlock_bh(to); |
a0a400d79 [NET]: dev_mcast:... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
return err; } EXPORT_SYMBOL(dev_mc_sync); /** * dev_mc_unsync - Remove synchronized addresses from the destination * device * @to: destination device * @from: source device * * Remove all addresses that were added to the destination device by * dev_mc_sync(). This function is intended to be called from the * dev->stop function of layered software devices. */ void dev_mc_unsync(struct net_device *to, struct net_device *from) { |
b9e408576 netdev: Do not us... |
143 |
netif_addr_lock_bh(from); |
e308a5d80 netdev: Add netde... |
144 |
netif_addr_lock(to); |
a0a400d79 [NET]: dev_mcast:... |
145 |
|
e83a2ea85 [VLAN]: set_rx_mo... |
146 147 |
__dev_addr_unsync(&to->mc_list, &to->mc_count, &from->mc_list, &from->mc_count); |
a0a400d79 [NET]: dev_mcast:... |
148 |
__dev_set_rx_mode(to); |
e308a5d80 netdev: Add netde... |
149 |
netif_addr_unlock(to); |
b9e408576 netdev: Do not us... |
150 |
netif_addr_unlock_bh(from); |
a0a400d79 [NET]: dev_mcast:... |
151 152 |
} EXPORT_SYMBOL(dev_mc_unsync); |
1da177e4c Linux-2.6.12-rc2 |
153 |
#ifdef CONFIG_PROC_FS |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
static int dev_mc_seq_show(struct seq_file *seq, void *v) { |
3fba5a8b1 [NET]: dev_mcast:... |
156 |
struct dev_addr_list *m; |
1da177e4c Linux-2.6.12-rc2 |
157 |
struct net_device *dev = v; |
95a363582 [NET]: Use existi... |
158 159 |
if (v == SEQ_START_TOKEN) return 0; |
b9e408576 netdev: Do not us... |
160 |
netif_addr_lock_bh(dev); |
1da177e4c Linux-2.6.12-rc2 |
161 162 163 164 165 166 167 168 169 170 171 172 |
for (m = dev->mc_list; m; m = m->next) { int i; seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, dev->name, m->dmi_users, m->dmi_gusers); for (i = 0; i < m->dmi_addrlen; i++) seq_printf(seq, "%02x", m->dmi_addr[i]); seq_putc(seq, ' '); } |
b9e408576 netdev: Do not us... |
173 |
netif_addr_unlock_bh(dev); |
1da177e4c Linux-2.6.12-rc2 |
174 175 |
return 0; } |
f690808e1 [NET]: make seq_o... |
176 |
static const struct seq_operations dev_mc_seq_ops = { |
95a363582 [NET]: Use existi... |
177 178 179 |
.start = dev_seq_start, .next = dev_seq_next, .stop = dev_seq_stop, |
1da177e4c Linux-2.6.12-rc2 |
180 181 182 183 184 |
.show = dev_mc_seq_show, }; static int dev_mc_seq_open(struct inode *inode, struct file *file) { |
e372c4140 [NET]: Consolidat... |
185 186 |
return seq_open_net(inode, file, &dev_mc_seq_ops, sizeof(struct seq_net_private)); |
1da177e4c Linux-2.6.12-rc2 |
187 |
} |
9a32144e9 [PATCH] mark stru... |
188 |
static const struct file_operations dev_mc_seq_fops = { |
1da177e4c Linux-2.6.12-rc2 |
189 190 191 192 |
.owner = THIS_MODULE, .open = dev_mc_seq_open, .read = seq_read, .llseek = seq_lseek, |
e372c4140 [NET]: Consolidat... |
193 |
.release = seq_release_net, |
1da177e4c Linux-2.6.12-rc2 |
194 195 196 |
}; #endif |
4665079cb [NETNS]: Move som... |
197 |
static int __net_init dev_mc_net_init(struct net *net) |
881d966b4 [NET]: Make the d... |
198 199 200 201 202 |
{ if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) return -ENOMEM; return 0; } |
4665079cb [NETNS]: Move som... |
203 |
static void __net_exit dev_mc_net_exit(struct net *net) |
881d966b4 [NET]: Make the d... |
204 205 206 |
{ proc_net_remove(net, "dev_mcast"); } |
022cbae61 [NET]: Move unnee... |
207 |
static struct pernet_operations __net_initdata dev_mc_net_ops = { |
881d966b4 [NET]: Make the d... |
208 209 210 |
.init = dev_mc_net_init, .exit = dev_mc_net_exit, }; |
1da177e4c Linux-2.6.12-rc2 |
211 212 |
void __init dev_mcast_init(void) { |
881d966b4 [NET]: Make the d... |
213 |
register_pernet_subsys(&dev_mc_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
214 215 216 217 |
} EXPORT_SYMBOL(dev_mc_add); EXPORT_SYMBOL(dev_mc_delete); |