aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-06-11 07:16:28 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-11 07:16:28 -0400
commit5ef12d98a19254ee5dc851bd83e214b43ec1f725 (patch)
tree703846f5298cca8f8a9f95712d47365e1de1df4a
parent2b85a34e911bf483c27cfdd124aeb1605145dc80 (diff)
neigh: fix state transition INCOMPLETE->FAILED via Netlink request
The current code errors out the INCOMPLETE neigh entry skb queue only from the timer if maximum probes have been attempted and there has been no reply. This also causes the transtion to FAILED state. However, the neigh entry can be also updated via Netlink to inform that the address is unavailable. Currently, neigh_update() just stops the timers and leaves the pending skb's unreleased. This results that the clean up code in the timer callback is never called, preventing also proper garbage collection. This fixes neigh_update() to process the pending skb queue immediately if INCOMPLETE -> FAILED state transtion occurs due to a Netlink request. Signed-off-by: Timo Teras <timo.teras@iki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/neighbour.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index c54229befcfe..163b4f5b0365 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -771,6 +771,28 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
771 p->ucast_probes + p->app_probes + p->mcast_probes); 771 p->ucast_probes + p->app_probes + p->mcast_probes);
772} 772}
773 773
774static void neigh_invalidate(struct neighbour *neigh)
775{
776 struct sk_buff *skb;
777
778 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
779 NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
780 neigh->updated = jiffies;
781
782 /* It is very thin place. report_unreachable is very complicated
783 routine. Particularly, it can hit the same neighbour entry!
784
785 So that, we try to be accurate and avoid dead loop. --ANK
786 */
787 while (neigh->nud_state == NUD_FAILED &&
788 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
789 write_unlock(&neigh->lock);
790 neigh->ops->error_report(neigh, skb);
791 write_lock(&neigh->lock);
792 }
793 skb_queue_purge(&neigh->arp_queue);
794}
795
774/* Called when a timer expires for a neighbour entry. */ 796/* Called when a timer expires for a neighbour entry. */
775 797
776static void neigh_timer_handler(unsigned long arg) 798static void neigh_timer_handler(unsigned long arg)
@@ -835,26 +857,9 @@ static void neigh_timer_handler(unsigned long arg)
835 857
836 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) && 858 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
837 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) { 859 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
838 struct sk_buff *skb;
839
840 neigh->nud_state = NUD_FAILED; 860 neigh->nud_state = NUD_FAILED;
841 neigh->updated = jiffies;
842 notify = 1; 861 notify = 1;
843 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed); 862 neigh_invalidate(neigh);
844 NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
845
846 /* It is very thin place. report_unreachable is very complicated
847 routine. Particularly, it can hit the same neighbour entry!
848
849 So that, we try to be accurate and avoid dead loop. --ANK
850 */
851 while (neigh->nud_state == NUD_FAILED &&
852 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
853 write_unlock(&neigh->lock);
854 neigh->ops->error_report(neigh, skb);
855 write_lock(&neigh->lock);
856 }
857 skb_queue_purge(&neigh->arp_queue);
858 } 863 }
859 864
860 if (neigh->nud_state & NUD_IN_TIMER) { 865 if (neigh->nud_state & NUD_IN_TIMER) {
@@ -1001,6 +1006,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1001 neigh->nud_state = new; 1006 neigh->nud_state = new;
1002 err = 0; 1007 err = 0;
1003 notify = old & NUD_VALID; 1008 notify = old & NUD_VALID;
1009 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1010 (new & NUD_FAILED)) {
1011 neigh_invalidate(neigh);
1012 notify = 1;
1013 }
1004 goto out; 1014 goto out;
1005 } 1015 }
1006 1016