From patchwork Thu Jun 4 08:40:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Teras X-Patchwork-Id: 28091 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 8FD5EB7063 for ; Thu, 4 Jun 2009 18:47:43 +1000 (EST) Received: by ozlabs.org (Postfix) id 80F3BDDDE1; Thu, 4 Jun 2009 18:47:43 +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 1FFABDDDA2 for ; Thu, 4 Jun 2009 18:47:43 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752602AbZFDIrb (ORCPT ); Thu, 4 Jun 2009 04:47:31 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753941AbZFDIra (ORCPT ); Thu, 4 Jun 2009 04:47:30 -0400 Received: from mail-ew0-f210.google.com ([209.85.219.210]:37079 "EHLO mail-ew0-f210.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753406AbZFDIr3 (ORCPT ); Thu, 4 Jun 2009 04:47:29 -0400 X-Greylist: delayed 386 seconds by postgrey-1.27 at vger.kernel.org; Thu, 04 Jun 2009 04:47:28 EDT Received: by ewy6 with SMTP id 6so902289ewy.37 for ; Thu, 04 Jun 2009 01:47:30 -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; bh=4zWZN+DN9sKAtTHylh8YFfdoHTrp7I7qyr3jrey75PE=; b=umTHkEPpD/MVMrWYLp+3irrI7FndxJLNZyxPM36wRBpYX58aG3y2dHJvQvk9NSAvO7 wcJMTR2b/2+iZpa61N8MnWmPHZQAxern3C7h8pChdAEybmchRw3xmU0SEsVnzAYVhqgo R4tVw/9RIvV+HyLRbAqG/wkYXT4UdJPFzj3u0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer; b=Yc16YM0ei9AfOnSfZsC1TsiI/aCgqCTAeYz8GuEUHjXLwIhuhEMBpMYqG0HZOtQ2zb TemaKzDctzNgzsR9Z4NhnNo4CCuVH8XTuQuAWRwBn83hra5PWCzx6r3bgry018BIfvv2 XztDLt1AtKkju4WJ/vZcDqba/5Y3Zt1unUDWc= Received: by 10.216.28.207 with SMTP id g57mr673989wea.163.1244104863150; Thu, 04 Jun 2009 01:41:03 -0700 (PDT) Received: from localhost.localdomain (xdsl-83-150-94-239.nebulazone.fi [83.150.94.239]) by mx.google.com with ESMTPS id m5sm20595723gve.18.2009.06.04.01.41.02 (version=SSLv3 cipher=RC4-MD5); Thu, 04 Jun 2009 01:41:02 -0700 (PDT) From: Timo Teras To: netdev@vger.kernel.org Cc: Timo Teras Subject: [PATCH] neigh: error out pending skbs if netlink invalidates incomplete neigh Date: Thu, 4 Jun 2009 11:40:55 +0300 Message-Id: <1244104855-2129-1-git-send-email-timo.teras@iki.fi> X-Mailer: git-send-email 1.6.0.4 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The state transition code from incomplete to invalid via neigh_update() is missing the proper clean up of skb queue. Separate the clean up code from neigh_timer_handler() to a new function and make neigh_update() is it also. 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; }