Commit 61cbc2fc authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d62733c8
...@@ -1091,8 +1091,8 @@ extern int dev_unicast_add(struct net_device *dev, void *addr, int alen); ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment