From patchwork Thu Jun 11 10:32:25 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Teras X-Patchwork-Id: 28561 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@bilbo.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ozlabs.org (ozlabs.org [203.10.76.45]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mx.ozlabs.org", Issuer "CA Cert Signing Authority" (verified OK)) by bilbo.ozlabs.org (Postfix) with ESMTPS id 09890B714A for ; Thu, 11 Jun 2009 20:32:38 +1000 (EST) Received: by ozlabs.org (Postfix) id E8F60DDDA1; Thu, 11 Jun 2009 20:32:37 +1000 (EST) Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 83057DDDA0 for ; Thu, 11 Jun 2009 20:32:37 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761486AbZFKKc3 (ORCPT ); Thu, 11 Jun 2009 06:32:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1760519AbZFKKc2 (ORCPT ); Thu, 11 Jun 2009 06:32:28 -0400 Received: from mail-ew0-f210.google.com ([209.85.219.210]:42295 "EHLO mail-ew0-f210.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754509AbZFKKc1 (ORCPT ); Thu, 11 Jun 2009 06:32:27 -0400 Received: by ewy6 with SMTP id 6so1875840ewy.37 for ; Thu, 11 Jun 2009 03:32:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:from:to:cc:subject :date:message-id:x-mailer:in-reply-to:references; bh=aHr0ZyGTAHalhaClLy2bMH7DF5HwYenQNDkwtMby12o=; b=lHSdf826/y5cb9PH84Ko0iigkFEOB6M1bGlRX2UNemt1rgffVrQKuL20LQ+nqP58oO 1gegvkzxzOUZCh6BJiUccdoypA3vTYqdXoSvYHucfuXgGVNzx/wnYY+dkl5t5KCGGMKB 4G/FdVTGKaCVdZO2gaf/jmZdyGUch4iaRUGZg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; b=BZ/DmnBGvdzcXbGKnl0kkWFKbLE5SyIkdkGw3uYXTwRkRcNvgU7xNCVLjV+mCm+gqm kn8/V95tMbQOgk8nw9C1/khpcFODdjEy0wFhIUMNTrctHXUb+5810TQFBx4ZawF+2lGu EklqhU/MS7Yh4jvxfxeyW9xfsS47fp83DX6RU= Received: by 10.210.125.7 with SMTP id x7mr2941419ebc.45.1244716348634; Thu, 11 Jun 2009 03:32:28 -0700 (PDT) Received: from localhost.localdomain (xdsl-83-150-94-239.nebulazone.fi [83.150.94.239]) by mx.google.com with ESMTPS id 7sm13044eyg.7.2009.06.11.03.32.27 (version=SSLv3 cipher=RC4-MD5); Thu, 11 Jun 2009 03:32:28 -0700 (PDT) From: Timo Teras To: davem@davemloft.net, netdev@vger.kernel.org Cc: Timo Teras Subject: [PATCH] neigh: fix state transition INCOMPLETE->FAILED via Netlink request Date: Thu, 11 Jun 2009 13:32:25 +0300 Message-Id: <1244716345-9407-1-git-send-email-timo.teras@iki.fi> X-Mailer: git-send-email 1.6.0.4 In-Reply-To: <20090611.031215.17106793.davem@davemloft.net> References: <20090611.031215.17106793.davem@davemloft.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- net/core/neighbour.c | 46 ++++++++++++++++++++++++++++------------------ 1 files changed, 28 insertions(+), 18 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index a1cbce7..a17cb9d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -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) @@ -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) { @@ -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; }