[NET]: Fix secondary unicast/multicast address count maintenance
When a reference to an existing address is increased or decreased without hitting zero, the address count is incorrectly adjusted. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
d62733c8e4
commit
61cbc2fca6
@@ -1091,8 +1091,8 @@ extern int dev_unicast_add(struct net_device *dev, void *addr, int alen);
|
|||||||
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
|
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
|
||||||
extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
|
extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
|
||||||
extern void dev_mc_discard(struct net_device *dev);
|
extern void dev_mc_discard(struct net_device *dev);
|
||||||
extern int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, int all);
|
extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
|
||||||
extern int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int newonly);
|
extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
|
||||||
extern void __dev_addr_discard(struct dev_addr_list **list);
|
extern void __dev_addr_discard(struct dev_addr_list **list);
|
||||||
extern void dev_set_promiscuity(struct net_device *dev, int inc);
|
extern void dev_set_promiscuity(struct net_device *dev, int inc);
|
||||||
extern void dev_set_allmulti(struct net_device *dev, int inc);
|
extern void dev_set_allmulti(struct net_device *dev, int inc);
|
||||||
|
@@ -2607,8 +2607,8 @@ void dev_set_rx_mode(struct net_device *dev)
|
|||||||
netif_tx_unlock_bh(dev);
|
netif_tx_unlock_bh(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
|
int __dev_addr_delete(struct dev_addr_list **list, int *count,
|
||||||
int glbl)
|
void *addr, int alen, int glbl)
|
||||||
{
|
{
|
||||||
struct dev_addr_list *da;
|
struct dev_addr_list *da;
|
||||||
|
|
||||||
@@ -2626,13 +2626,15 @@ int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
|
|||||||
|
|
||||||
*list = da->next;
|
*list = da->next;
|
||||||
kfree(da);
|
kfree(da);
|
||||||
|
(*count)--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl)
|
int __dev_addr_add(struct dev_addr_list **list, int *count,
|
||||||
|
void *addr, int alen, int glbl)
|
||||||
{
|
{
|
||||||
struct dev_addr_list *da;
|
struct dev_addr_list *da;
|
||||||
|
|
||||||
@@ -2659,6 +2661,7 @@ int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl)
|
|||||||
da->da_gusers = glbl ? 1 : 0;
|
da->da_gusers = glbl ? 1 : 0;
|
||||||
da->next = *list;
|
da->next = *list;
|
||||||
*list = da;
|
*list = da;
|
||||||
|
(*count)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2692,11 +2695,9 @@ int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
|
|||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
netif_tx_lock_bh(dev);
|
netif_tx_lock_bh(dev);
|
||||||
err = __dev_addr_delete(&dev->uc_list, addr, alen, 0);
|
err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
|
||||||
if (!err) {
|
if (!err)
|
||||||
dev->uc_count--;
|
|
||||||
__dev_set_rx_mode(dev);
|
__dev_set_rx_mode(dev);
|
||||||
}
|
|
||||||
netif_tx_unlock_bh(dev);
|
netif_tx_unlock_bh(dev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -2718,11 +2719,9 @@ int dev_unicast_add(struct net_device *dev, void *addr, int alen)
|
|||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
netif_tx_lock_bh(dev);
|
netif_tx_lock_bh(dev);
|
||||||
err = __dev_addr_add(&dev->uc_list, addr, alen, 0);
|
err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
|
||||||
if (!err) {
|
if (!err)
|
||||||
dev->uc_count++;
|
|
||||||
__dev_set_rx_mode(dev);
|
__dev_set_rx_mode(dev);
|
||||||
}
|
|
||||||
netif_tx_unlock_bh(dev);
|
netif_tx_unlock_bh(dev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@@ -72,10 +72,9 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
netif_tx_lock_bh(dev);
|
netif_tx_lock_bh(dev);
|
||||||
err = __dev_addr_delete(&dev->mc_list, addr, alen, glbl);
|
err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
|
||||||
|
addr, alen, glbl);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
dev->mc_count--;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have altered the list, so the card
|
* We have altered the list, so the card
|
||||||
* loaded filter is now wrong. Fix it
|
* loaded filter is now wrong. Fix it
|
||||||
@@ -96,11 +95,9 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
netif_tx_lock_bh(dev);
|
netif_tx_lock_bh(dev);
|
||||||
err = __dev_addr_add(&dev->mc_list, addr, alen, glbl);
|
err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
|
||||||
if (!err) {
|
if (!err)
|
||||||
dev->mc_count++;
|
|
||||||
__dev_set_rx_mode(dev);
|
__dev_set_rx_mode(dev);
|
||||||
}
|
|
||||||
netif_tx_unlock_bh(dev);
|
netif_tx_unlock_bh(dev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user