[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>
This commit is contained in:
parent
bf742482d7
commit
3fba5a8b1e
2 changed files with 21 additions and 90 deletions
|
@ -189,15 +189,12 @@ struct dev_addr_list
|
|||
/*
|
||||
* We tag multicasts with these structures.
|
||||
*/
|
||||
|
||||
struct dev_mc_list
|
||||
{
|
||||
struct dev_mc_list *next;
|
||||
__u8 dmi_addr[MAX_ADDR_LEN];
|
||||
unsigned char dmi_addrlen;
|
||||
int dmi_users;
|
||||
int dmi_gusers;
|
||||
};
|
||||
|
||||
#define dev_mc_list dev_addr_list
|
||||
#define dmi_addr da_addr
|
||||
#define dmi_addrlen da_addrlen
|
||||
#define dmi_users da_users
|
||||
#define dmi_gusers da_gusers
|
||||
|
||||
struct hh_cache
|
||||
{
|
||||
|
@ -400,7 +397,7 @@ struct net_device
|
|||
unsigned char addr_len; /* hardware address length */
|
||||
unsigned short dev_id; /* for shared network cards */
|
||||
|
||||
struct dev_mc_list *mc_list; /* Multicast mac addresses */
|
||||
struct dev_addr_list *mc_list; /* Multicast mac addresses */
|
||||
int mc_count; /* Number of installed mcasts */
|
||||
int promiscuity;
|
||||
int allmulti;
|
||||
|
|
|
@ -102,47 +102,20 @@ void dev_mc_upload(struct net_device *dev)
|
|||
|
||||
int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
|
||||
{
|
||||
int err = 0;
|
||||
struct dev_mc_list *dmi, **dmip;
|
||||
int err;
|
||||
|
||||
netif_tx_lock_bh(dev);
|
||||
err = __dev_addr_delete(&dev->mc_list, addr, alen, glbl);
|
||||
if (!err) {
|
||||
dev->mc_count--;
|
||||
|
||||
for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
|
||||
/*
|
||||
* Find the entry we want to delete. The device could
|
||||
* have variable length entries so check these too.
|
||||
* We have altered the list, so the card
|
||||
* loaded filter is now wrong. Fix it
|
||||
*/
|
||||
if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
|
||||
alen == dmi->dmi_addrlen) {
|
||||
if (glbl) {
|
||||
int old_glbl = dmi->dmi_gusers;
|
||||
dmi->dmi_gusers = 0;
|
||||
if (old_glbl == 0)
|
||||
break;
|
||||
}
|
||||
if (--dmi->dmi_users)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Last user. So delete the entry.
|
||||
*/
|
||||
*dmip = dmi->next;
|
||||
dev->mc_count--;
|
||||
|
||||
kfree(dmi);
|
||||
|
||||
/*
|
||||
* We have altered the list, so the card
|
||||
* loaded filter is now wrong. Fix it
|
||||
*/
|
||||
__dev_mc_upload(dev);
|
||||
|
||||
netif_tx_unlock_bh(dev);
|
||||
return 0;
|
||||
}
|
||||
__dev_mc_upload(dev);
|
||||
}
|
||||
err = -ENOENT;
|
||||
done:
|
||||
netif_tx_unlock_bh(dev);
|
||||
return err;
|
||||
}
|
||||
|
@ -153,46 +126,15 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
|
|||
|
||||
int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
|
||||
{
|
||||
int err = 0;
|
||||
struct dev_mc_list *dmi, *dmi1;
|
||||
|
||||
dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
|
||||
int err;
|
||||
|
||||
netif_tx_lock_bh(dev);
|
||||
for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
|
||||
if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
|
||||
dmi->dmi_addrlen == alen) {
|
||||
if (glbl) {
|
||||
int old_glbl = dmi->dmi_gusers;
|
||||
dmi->dmi_gusers = 1;
|
||||
if (old_glbl)
|
||||
goto done;
|
||||
}
|
||||
dmi->dmi_users++;
|
||||
goto done;
|
||||
}
|
||||
err = __dev_addr_add(&dev->mc_list, addr, alen, glbl);
|
||||
if (!err) {
|
||||
dev->mc_count++;
|
||||
__dev_mc_upload(dev);
|
||||
}
|
||||
|
||||
if ((dmi = dmi1) == NULL) {
|
||||
netif_tx_unlock_bh(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(dmi->dmi_addr, addr, alen);
|
||||
dmi->dmi_addrlen = alen;
|
||||
dmi->next = dev->mc_list;
|
||||
dmi->dmi_users = 1;
|
||||
dmi->dmi_gusers = glbl ? 1 : 0;
|
||||
dev->mc_list = dmi;
|
||||
dev->mc_count++;
|
||||
|
||||
__dev_mc_upload(dev);
|
||||
|
||||
netif_tx_unlock_bh(dev);
|
||||
return 0;
|
||||
|
||||
done:
|
||||
netif_tx_unlock_bh(dev);
|
||||
kfree(dmi1);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -203,16 +145,8 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
|
|||
void dev_mc_discard(struct net_device *dev)
|
||||
{
|
||||
netif_tx_lock_bh(dev);
|
||||
|
||||
while (dev->mc_list != NULL) {
|
||||
struct dev_mc_list *tmp = dev->mc_list;
|
||||
dev->mc_list = tmp->next;
|
||||
if (tmp->dmi_users > tmp->dmi_gusers)
|
||||
printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
|
||||
kfree(tmp);
|
||||
}
|
||||
__dev_addr_discard(&dev->mc_list);
|
||||
dev->mc_count = 0;
|
||||
|
||||
netif_tx_unlock_bh(dev);
|
||||
}
|
||||
|
||||
|
@ -244,7 +178,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v)
|
|||
|
||||
static int dev_mc_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct dev_mc_list *m;
|
||||
struct dev_addr_list *m;
|
||||
struct net_device *dev = v;
|
||||
|
||||
netif_tx_lock_bh(dev);
|
||||
|
|
Loading…
Reference in a new issue