Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 150847
b: refs/heads/master
c: 5ef12d9
h: refs/heads/master
i:
  150845: 60f4710
  150843: a07f4d1
  150839: 4d3467d
  150831: 92c946c
  150815: b794079
  150783: 3130ca7
v: v3
  • Loading branch information
Timo Teras authored and David S. Miller committed Jun 11, 2009
1 parent 9a643c4 commit 773e615
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2b85a34e911bf483c27cfdd124aeb1605145dc80
refs/heads/master: 5ef12d98a19254ee5dc851bd83e214b43ec1f725
46 changes: 28 additions & 18 deletions trunk/net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,28 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
p->ucast_probes + p->app_probes + p->mcast_probes);
}

static void neigh_invalidate(struct neighbour *neigh)
{
struct sk_buff *skb;

NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
neigh->updated = jiffies;

/* It is very thin place. report_unreachable is very complicated
routine. Particularly, it can hit the same neighbour entry!
So that, we try to be accurate and avoid dead loop. --ANK
*/
while (neigh->nud_state == NUD_FAILED &&
(skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
write_unlock(&neigh->lock);
neigh->ops->error_report(neigh, skb);
write_lock(&neigh->lock);
}
skb_queue_purge(&neigh->arp_queue);
}

/* Called when a timer expires for a neighbour entry. */

static void neigh_timer_handler(unsigned long arg)
Expand Down Expand Up @@ -835,26 +857,9 @@ static void neigh_timer_handler(unsigned long arg)

if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
struct sk_buff *skb;

neigh->nud_state = NUD_FAILED;
neigh->updated = jiffies;
notify = 1;
NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
NEIGH_PRINTK2("neigh %p is failed.\n", neigh);

/* It is very thin place. report_unreachable is very complicated
routine. Particularly, it can hit the same neighbour entry!
So that, we try to be accurate and avoid dead loop. --ANK
*/
while (neigh->nud_state == NUD_FAILED &&
(skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
write_unlock(&neigh->lock);
neigh->ops->error_report(neigh, skb);
write_lock(&neigh->lock);
}
skb_queue_purge(&neigh->arp_queue);
neigh_invalidate(neigh);
}

if (neigh->nud_state & NUD_IN_TIMER) {
Expand Down Expand Up @@ -1001,6 +1006,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
neigh->nud_state = new;
err = 0;
notify = old & NUD_VALID;
if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
(new & NUD_FAILED)) {
neigh_invalidate(neigh);
notify = 1;
}
goto out;
}

Expand Down

0 comments on commit 773e615

Please sign in to comment.