aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-06-27 04:26:58 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:15:55 -0400
commit3fba5a8b1e3df2384b90493538161e83cf15dd5f (patch)
treef38bb73c1bf2516c6c973c9e7cd18fd5a20b1c20
parentbf742482d7a647c5c6f03f78eb35a862e159ecf5 (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>
-rw-r--r--include/linux/netdevice.h17
-rw-r--r--net/core/dev_mcast.c96
2 files changed, 22 insertions, 91 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index aa389c77aa3..9e114e77e54 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -189,15 +189,12 @@ struct dev_addr_list
189/* 189/*
190 * We tag multicasts with these structures. 190 * We tag multicasts with these structures.
191 */ 191 */
192 192
193struct dev_mc_list 193#define dev_mc_list dev_addr_list
194{ 194#define dmi_addr da_addr
195 struct dev_mc_list *next; 195#define dmi_addrlen da_addrlen
196 __u8 dmi_addr[MAX_ADDR_LEN]; 196#define dmi_users da_users
197 unsigned char dmi_addrlen; 197#define dmi_gusers da_gusers
198 int dmi_users;
199 int dmi_gusers;
200};
201 198
202struct hh_cache 199struct hh_cache
203{ 200{
@@ -400,7 +397,7 @@ struct net_device
400 unsigned char addr_len; /* hardware address length */ 397 unsigned char addr_len; /* hardware address length */
401 unsigned short dev_id; /* for shared network cards */ 398 unsigned short dev_id; /* for shared network cards */
402 399
403 struct dev_mc_list *mc_list; /* Multicast mac addresses */ 400 struct dev_addr_list *mc_list; /* Multicast mac addresses */
404 int mc_count; /* Number of installed mcasts */ 401 int mc_count; /* Number of installed mcasts */
405 int promiscuity; 402 int promiscuity;
406 int allmulti; 403 int allmulti;
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 80bb2e374b7..702907434a4 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
103int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) 103int 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;
145done:
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
154int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) 127int 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
193done:
194 netif_tx_unlock_bh(dev);
195 kfree(dmi1);
196 return err; 138 return err;
197} 139}
198 140
@@ -203,16 +145,8 @@ done:
203void dev_mc_discard(struct net_device *dev) 145void 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
245static int dev_mc_seq_show(struct seq_file *seq, void *v) 179static 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);