Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 265253
b: refs/heads/master
c: cd28ca0
h: refs/heads/master
i:
  265251: d0fefe6
v: v3
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Aug 12, 2011
1 parent 1b46d4c commit 908f5a8
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 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: 68c3e5a7b91513010d2536e4bcd7bdd54d0e6acf
refs/heads/master: cd28ca0a3dd17c68d24b839602a0e6268ad28b5d
40 changes: 26 additions & 14 deletions trunk/net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,19 @@ static void neigh_invalidate(struct neighbour *neigh)
skb_queue_purge(&neigh->arp_queue);
}

static void neigh_probe(struct neighbour *neigh)
__releases(neigh->lock)
{
struct sk_buff *skb = skb_peek(&neigh->arp_queue);
/* keep skb alive even if arp_queue overflows */
if (skb)
skb = skb_copy(skb, GFP_ATOMIC);
write_unlock(&neigh->lock);
neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
kfree_skb(skb);
}

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

static void neigh_timer_handler(unsigned long arg)
Expand Down Expand Up @@ -920,14 +933,7 @@ static void neigh_timer_handler(unsigned long arg)
neigh_hold(neigh);
}
if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
struct sk_buff *skb = skb_peek(&neigh->arp_queue);
/* keep skb alive even if arp_queue overflows */
if (skb)
skb = skb_copy(skb, GFP_ATOMIC);
write_unlock(&neigh->lock);
neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
kfree_skb(skb);
neigh_probe(neigh);
} else {
out:
write_unlock(&neigh->lock);
Expand All @@ -942,22 +948,24 @@ static void neigh_timer_handler(unsigned long arg)
int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
{
int rc;
unsigned long now;
bool immediate_probe = false;

write_lock_bh(&neigh->lock);

rc = 0;
if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
goto out_unlock_bh;

now = jiffies;

if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
unsigned long next, now = jiffies;

atomic_set(&neigh->probes, neigh->parms->ucast_probes);
neigh->nud_state = NUD_INCOMPLETE;
neigh->updated = jiffies;
neigh_add_timer(neigh, now + 1);
neigh->updated = now;
next = now + max(neigh->parms->retrans_time, HZ/2);
neigh_add_timer(neigh, next);
immediate_probe = true;
} else {
neigh->nud_state = NUD_FAILED;
neigh->updated = jiffies;
Expand Down Expand Up @@ -989,7 +997,11 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
rc = 1;
}
out_unlock_bh:
write_unlock_bh(&neigh->lock);
if (immediate_probe)
neigh_probe(neigh);
else
write_unlock(&neigh->lock);
local_bh_enable();
return rc;
}
EXPORT_SYMBOL(__neigh_event_send);
Expand Down

0 comments on commit 908f5a8

Please sign in to comment.