diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-27 04:26:58 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:15:55 -0400 |
commit | 3fba5a8b1e3df2384b90493538161e83cf15dd5f (patch) | |
tree | f38bb73c1bf2516c6c973c9e7cd18fd5a20b1c20 /net/core | |
parent | bf742482d7a647c5c6f03f78eb35a862e159ecf5 (diff) |
[NET]: dev_mcast: switch to generic net_device address lists
Use generic net_device address lists for multicast list handling.
Some defines are used to keep drivers working.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev_mcast.c | 96 |
1 files changed, 15 insertions, 81 deletions
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 80bb2e374b76..702907434a47 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -102,47 +102,20 @@ void dev_mc_upload(struct net_device *dev) | |||
102 | 102 | ||
103 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | 103 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) |
104 | { | 104 | { |
105 | int err = 0; | 105 | int err; |
106 | struct dev_mc_list *dmi, **dmip; | ||
107 | 106 | ||
108 | netif_tx_lock_bh(dev); | 107 | netif_tx_lock_bh(dev); |
108 | err = __dev_addr_delete(&dev->mc_list, addr, alen, glbl); | ||
109 | if (!err) { | ||
110 | dev->mc_count--; | ||
109 | 111 | ||
110 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { | ||
111 | /* | 112 | /* |
112 | * Find the entry we want to delete. The device could | 113 | * We have altered the list, so the card |
113 | * have variable length entries so check these too. | 114 | * loaded filter is now wrong. Fix it |
114 | */ | 115 | */ |
115 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 116 | |
116 | alen == dmi->dmi_addrlen) { | 117 | __dev_mc_upload(dev); |
117 | if (glbl) { | ||
118 | int old_glbl = dmi->dmi_gusers; | ||
119 | dmi->dmi_gusers = 0; | ||
120 | if (old_glbl == 0) | ||
121 | break; | ||
122 | } | ||
123 | if (--dmi->dmi_users) | ||
124 | goto done; | ||
125 | |||
126 | /* | ||
127 | * Last user. So delete the entry. | ||
128 | */ | ||
129 | *dmip = dmi->next; | ||
130 | dev->mc_count--; | ||
131 | |||
132 | kfree(dmi); | ||
133 | |||
134 | /* | ||
135 | * We have altered the list, so the card | ||
136 | * loaded filter is now wrong. Fix it | ||
137 | */ | ||
138 | __dev_mc_upload(dev); | ||
139 | |||
140 | netif_tx_unlock_bh(dev); | ||
141 | return 0; | ||
142 | } | ||
143 | } | 118 | } |
144 | err = -ENOENT; | ||
145 | done: | ||
146 | netif_tx_unlock_bh(dev); | 119 | netif_tx_unlock_bh(dev); |
147 | return err; | 120 | return err; |
148 | } | 121 | } |
@@ -153,46 +126,15 @@ done: | |||
153 | 126 | ||
154 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | 127 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) |
155 | { | 128 | { |
156 | int err = 0; | 129 | int err; |
157 | struct dev_mc_list *dmi, *dmi1; | ||
158 | |||
159 | dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); | ||
160 | 130 | ||
161 | netif_tx_lock_bh(dev); | 131 | netif_tx_lock_bh(dev); |
162 | for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { | 132 | err = __dev_addr_add(&dev->mc_list, addr, alen, glbl); |
163 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 133 | if (!err) { |
164 | dmi->dmi_addrlen == alen) { | 134 | dev->mc_count++; |
165 | if (glbl) { | 135 | __dev_mc_upload(dev); |
166 | int old_glbl = dmi->dmi_gusers; | ||
167 | dmi->dmi_gusers = 1; | ||
168 | if (old_glbl) | ||
169 | goto done; | ||
170 | } | ||
171 | dmi->dmi_users++; | ||
172 | goto done; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if ((dmi = dmi1) == NULL) { | ||
177 | netif_tx_unlock_bh(dev); | ||
178 | return -ENOMEM; | ||
179 | } | 136 | } |
180 | memcpy(dmi->dmi_addr, addr, alen); | ||
181 | dmi->dmi_addrlen = alen; | ||
182 | dmi->next = dev->mc_list; | ||
183 | dmi->dmi_users = 1; | ||
184 | dmi->dmi_gusers = glbl ? 1 : 0; | ||
185 | dev->mc_list = dmi; | ||
186 | dev->mc_count++; | ||
187 | |||
188 | __dev_mc_upload(dev); | ||
189 | |||
190 | netif_tx_unlock_bh(dev); | 137 | netif_tx_unlock_bh(dev); |
191 | return 0; | ||
192 | |||
193 | done: | ||
194 | netif_tx_unlock_bh(dev); | ||
195 | kfree(dmi1); | ||
196 | return err; | 138 | return err; |
197 | } | 139 | } |
198 | 140 | ||
@@ -203,16 +145,8 @@ done: | |||
203 | void dev_mc_discard(struct net_device *dev) | 145 | void dev_mc_discard(struct net_device *dev) |
204 | { | 146 | { |
205 | netif_tx_lock_bh(dev); | 147 | netif_tx_lock_bh(dev); |
206 | 148 | __dev_addr_discard(&dev->mc_list); | |
207 | while (dev->mc_list != NULL) { | ||
208 | struct dev_mc_list *tmp = dev->mc_list; | ||
209 | dev->mc_list = tmp->next; | ||
210 | if (tmp->dmi_users > tmp->dmi_gusers) | ||
211 | printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users); | ||
212 | kfree(tmp); | ||
213 | } | ||
214 | dev->mc_count = 0; | 149 | dev->mc_count = 0; |
215 | |||
216 | netif_tx_unlock_bh(dev); | 150 | netif_tx_unlock_bh(dev); |
217 | } | 151 | } |
218 | 152 | ||
@@ -244,7 +178,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v) | |||
244 | 178 | ||
245 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | 179 | static int dev_mc_seq_show(struct seq_file *seq, void *v) |
246 | { | 180 | { |
247 | struct dev_mc_list *m; | 181 | struct dev_addr_list *m; |
248 | struct net_device *dev = v; | 182 | struct net_device *dev = v; |
249 | 183 | ||
250 | netif_tx_lock_bh(dev); | 184 | netif_tx_lock_bh(dev); |