diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-30 16:35:52 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:16:23 -0400 |
commit | 61cbc2fca6335be52788773b21efdc52a2750924 (patch) | |
tree | 489e6a9571c7fabd49dcff384dd634635fe66555 /net | |
parent | d62733c8e437fdb58325617c4b3331769ba82d70 (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 21 | ||||
-rw-r--r-- | net/core/dev_mcast.c | 11 |
2 files changed, 14 insertions, 18 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 7ddf66d0ad5e..4221dcda88d7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2607,8 +2607,8 @@ void dev_set_rx_mode(struct net_device *dev) | |||
2607 | netif_tx_unlock_bh(dev); | 2607 | netif_tx_unlock_bh(dev); |
2608 | } | 2608 | } |
2609 | 2609 | ||
2610 | int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, | 2610 | int __dev_addr_delete(struct dev_addr_list **list, int *count, |
2611 | int glbl) | 2611 | void *addr, int alen, int glbl) |
2612 | { | 2612 | { |
2613 | struct dev_addr_list *da; | 2613 | struct dev_addr_list *da; |
2614 | 2614 | ||
@@ -2626,13 +2626,15 @@ int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, | |||
2626 | 2626 | ||
2627 | *list = da->next; | 2627 | *list = da->next; |
2628 | kfree(da); | 2628 | kfree(da); |
2629 | (*count)--; | ||
2629 | return 0; | 2630 | return 0; |
2630 | } | 2631 | } |
2631 | } | 2632 | } |
2632 | return -ENOENT; | 2633 | return -ENOENT; |
2633 | } | 2634 | } |
2634 | 2635 | ||
2635 | int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl) | 2636 | int __dev_addr_add(struct dev_addr_list **list, int *count, |
2637 | void *addr, int alen, int glbl) | ||
2636 | { | 2638 | { |
2637 | struct dev_addr_list *da; | 2639 | struct dev_addr_list *da; |
2638 | 2640 | ||
@@ -2659,6 +2661,7 @@ int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl) | |||
2659 | da->da_gusers = glbl ? 1 : 0; | 2661 | da->da_gusers = glbl ? 1 : 0; |
2660 | da->next = *list; | 2662 | da->next = *list; |
2661 | *list = da; | 2663 | *list = da; |
2664 | (*count)++; | ||
2662 | return 0; | 2665 | return 0; |
2663 | } | 2666 | } |
2664 | 2667 | ||
@@ -2692,11 +2695,9 @@ int dev_unicast_delete(struct net_device *dev, void *addr, int alen) | |||
2692 | ASSERT_RTNL(); | 2695 | ASSERT_RTNL(); |
2693 | 2696 | ||
2694 | netif_tx_lock_bh(dev); | 2697 | netif_tx_lock_bh(dev); |
2695 | err = __dev_addr_delete(&dev->uc_list, addr, alen, 0); | 2698 | err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0); |
2696 | if (!err) { | 2699 | if (!err) |
2697 | dev->uc_count--; | ||
2698 | __dev_set_rx_mode(dev); | 2700 | __dev_set_rx_mode(dev); |
2699 | } | ||
2700 | netif_tx_unlock_bh(dev); | 2701 | netif_tx_unlock_bh(dev); |
2701 | return err; | 2702 | return err; |
2702 | } | 2703 | } |
@@ -2718,11 +2719,9 @@ int dev_unicast_add(struct net_device *dev, void *addr, int alen) | |||
2718 | ASSERT_RTNL(); | 2719 | ASSERT_RTNL(); |
2719 | 2720 | ||
2720 | netif_tx_lock_bh(dev); | 2721 | netif_tx_lock_bh(dev); |
2721 | err = __dev_addr_add(&dev->uc_list, addr, alen, 0); | 2722 | err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0); |
2722 | if (!err) { | 2723 | if (!err) |
2723 | dev->uc_count++; | ||
2724 | __dev_set_rx_mode(dev); | 2724 | __dev_set_rx_mode(dev); |
2725 | } | ||
2726 | netif_tx_unlock_bh(dev); | 2725 | netif_tx_unlock_bh(dev); |
2727 | return err; | 2726 | return err; |
2728 | } | 2727 | } |
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 5cc9b448c443..aa38100601fb 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -72,10 +72,9 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | |||
72 | int err; | 72 | int err; |
73 | 73 | ||
74 | netif_tx_lock_bh(dev); | 74 | netif_tx_lock_bh(dev); |
75 | err = __dev_addr_delete(&dev->mc_list, addr, alen, glbl); | 75 | err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, |
76 | addr, alen, glbl); | ||
76 | if (!err) { | 77 | if (!err) { |
77 | dev->mc_count--; | ||
78 | |||
79 | /* | 78 | /* |
80 | * We have altered the list, so the card | 79 | * We have altered the list, so the card |
81 | * loaded filter is now wrong. Fix it | 80 | * 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 | int err; | 95 | int err; |
97 | 96 | ||
98 | netif_tx_lock_bh(dev); | 97 | netif_tx_lock_bh(dev); |
99 | err = __dev_addr_add(&dev->mc_list, addr, alen, glbl); | 98 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); |
100 | if (!err) { | 99 | if (!err) |
101 | dev->mc_count++; | ||
102 | __dev_set_rx_mode(dev); | 100 | __dev_set_rx_mode(dev); |
103 | } | ||
104 | netif_tx_unlock_bh(dev); | 101 | netif_tx_unlock_bh(dev); |
105 | return err; | 102 | return err; |
106 | } | 103 | } |