aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/neighbour.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r--net/core/neighbour.c48
1 files changed, 16 insertions, 32 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 4128fc76ac3..1dcf7fa1f0f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -175,39 +175,10 @@ static void pneigh_queue_purge(struct sk_buff_head *list)
175 } 175 }
176} 176}
177 177
178void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev) 178static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
179{ 179{
180 int i; 180 int i;
181 181
182 write_lock_bh(&tbl->lock);
183
184 for (i=0; i <= tbl->hash_mask; i++) {
185 struct neighbour *n, **np;
186
187 np = &tbl->hash_buckets[i];
188 while ((n = *np) != NULL) {
189 if (dev && n->dev != dev) {
190 np = &n->next;
191 continue;
192 }
193 *np = n->next;
194 write_lock_bh(&n->lock);
195 n->dead = 1;
196 neigh_del_timer(n);
197 write_unlock_bh(&n->lock);
198 neigh_release(n);
199 }
200 }
201
202 write_unlock_bh(&tbl->lock);
203}
204
205int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
206{
207 int i;
208
209 write_lock_bh(&tbl->lock);
210
211 for (i = 0; i <= tbl->hash_mask; i++) { 182 for (i = 0; i <= tbl->hash_mask; i++) {
212 struct neighbour *n, **np = &tbl->hash_buckets[i]; 183 struct neighbour *n, **np = &tbl->hash_buckets[i];
213 184
@@ -243,7 +214,19 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
243 neigh_release(n); 214 neigh_release(n);
244 } 215 }
245 } 216 }
217}
246 218
219void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
220{
221 write_lock_bh(&tbl->lock);
222 neigh_flush_dev(tbl, dev);
223 write_unlock_bh(&tbl->lock);
224}
225
226int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
227{
228 write_lock_bh(&tbl->lock);
229 neigh_flush_dev(tbl, dev);
247 pneigh_ifdown(tbl, dev); 230 pneigh_ifdown(tbl, dev);
248 write_unlock_bh(&tbl->lock); 231 write_unlock_bh(&tbl->lock);
249 232
@@ -732,6 +715,7 @@ static inline void neigh_add_timer(struct neighbour *n, unsigned long when)
732 if (unlikely(mod_timer(&n->timer, when))) { 715 if (unlikely(mod_timer(&n->timer, when))) {
733 printk("NEIGH: BUG, double timer add, state is %x\n", 716 printk("NEIGH: BUG, double timer add, state is %x\n",
734 n->nud_state); 717 n->nud_state);
718 dump_stack();
735 } 719 }
736} 720}
737 721
@@ -815,10 +799,10 @@ static void neigh_timer_handler(unsigned long arg)
815 } 799 }
816 800
817 if (neigh->nud_state & NUD_IN_TIMER) { 801 if (neigh->nud_state & NUD_IN_TIMER) {
818 neigh_hold(neigh);
819 if (time_before(next, jiffies + HZ/2)) 802 if (time_before(next, jiffies + HZ/2))
820 next = jiffies + HZ/2; 803 next = jiffies + HZ/2;
821 neigh_add_timer(neigh, next); 804 if (!mod_timer(&neigh->timer, next))
805 neigh_hold(neigh);
822 } 806 }
823 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) { 807 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
824 struct sk_buff *skb = skb_peek(&neigh->arp_queue); 808 struct sk_buff *skb = skb_peek(&neigh->arp_queue);