From patchwork Thu Jun 11 08:13:05 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Teras X-Patchwork-Id: 28555 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 EF6D6B717E for ; Thu, 11 Jun 2009 18:13:29 +1000 (EST) Received: by ozlabs.org (Postfix) id D8B93DDD04; Thu, 11 Jun 2009 18:13:29 +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 6F4CFDDD01 for ; Thu, 11 Jun 2009 18:13:29 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757127AbZFKINS (ORCPT ); Thu, 11 Jun 2009 04:13:18 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756138AbZFKINR (ORCPT ); Thu, 11 Jun 2009 04:13:17 -0400 Received: from mail-ew0-f210.google.com ([209.85.219.210]:36499 "EHLO mail-ew0-f210.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754604AbZFKINP (ORCPT ); Thu, 11 Jun 2009 04:13:15 -0400 Received: by ewy6 with SMTP id 6so1769644ewy.37 for ; Thu, 11 Jun 2009 01:13:16 -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=+PLLM2QJSasCCRVX39aqZuXTMASX1xtTTaH+bAbeIkY=; b=VPF/4GhVmIFyVkyCIK4GoHQwu9FmyyvAUR6LPcyNaxhNwKKAd/y9wTW7PUgHZIU1sY 41JzG4NP87sSpM5cQR/Y6hPE3P57BdeiisLpdr9MOA4JFi8KTEUMyAaIdeJ/znt4Y6PO Sn8XZ/cZDgSMehhHlma5W4X8s+343QK9Furwk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer; b=t89vBYGTMut3SgQNkq/0ZK648TS5bn2+FFM6eD9RLFf/yxGqVJOCMCgUTANutJVb65 4PIyigc0WcSUVFf+0LhsQHUnoKWkiXRJBLEnyiuHvgbNLhKRsw1Vhor7JqE03BdFnTKa O43HQ70qNDhBasMgd7tvC6zCvF8oiAOgAS+7M= Received: by 10.210.102.12 with SMTP id z12mr2274257ebb.80.1244707996914; Thu, 11 Jun 2009 01:13:16 -0700 (PDT) Received: from localhost.localdomain (xdsl-83-150-94-239.nebulazone.fi [83.150.94.239]) by mx.google.com with ESMTPS id 10sm921467eyz.1.2009.06.11.01.13.15 (version=SSLv3 cipher=RC4-MD5); Thu, 11 Jun 2009 01:13:16 -0700 (PDT) From: Timo Teras To: davem@davemloft.net, netdev@vger.kernel.org Cc: Timo Teras Subject: [RESEND] [PATCH] neigh: error out pending skbs if netlink invalidates incomplete neigh Date: Thu, 11 Jun 2009 11:13:05 +0300 Message-Id: <1244707985-486-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; }