From patchwork Mon Dec 3 20:26:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Marks X-Patchwork-Id: 203438 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B9B812C007C for ; Tue, 4 Dec 2012 07:28:20 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752446Ab2LCU2Q (ORCPT ); Mon, 3 Dec 2012 15:28:16 -0500 Received: from mail-qa0-f74.google.com ([209.85.216.74]:41261 "EHLO mail-qa0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752314Ab2LCU2O (ORCPT ); Mon, 3 Dec 2012 15:28:14 -0500 Received: by mail-qa0-f74.google.com with SMTP id r4so15706qaq.1 for ; Mon, 03 Dec 2012 12:28:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=ZnVu8ffp8TjuBHUOJJ94InZuzdVhgJjBqsJIsfuSe+Y=; b=kfipeT15c1fWyvjQa/krDadYoJuVGjgKWHLMXS20tkPJFoS9HTRjAK3fw4dfyKH4x8 7O4g2RnavxhW66enN99RAb44eRKfwbrKV3oMi7Mo88SmN9ZPvNRFJ82QCnnsc754ka9e 25+jCEJEndr2R/WyNr+f2RVX5j2h4aRZ8fek513UBCM5NoI36zPq4ibdrlJR/7RegNJ8 d1TON09KqGm+h6Ea9OsM8JVe5xzgwCkOHfZI1FTSvYLuewqLQnadzKEyTECHs4u24nX8 F29IpReVyYwS04G8EAmk31zTR7RvrtmQXjwr2XfNJFWc7X9AG31934EWMYaedCc4llXR cI0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=ZnVu8ffp8TjuBHUOJJ94InZuzdVhgJjBqsJIsfuSe+Y=; b=L2Xa/K46zppOWMwIR/49nydSWXg6PRMoV3kuqJEiHw8DIcPzWVoxLIlzffjlYC1VpB ZkdQ8uOYonwgx5F+1d3Hx3434Pfb5dQzzk78m0+aCx4UL13P9dptSGXN4c3thRzqJXkF AY7ZBrrFHS0Y65NnThMGt8RXkWKhwKkRZOyp1C4DnltkIwYHhuruMpg/n6JKm3sSY4dg LBoy4wojzerRYLrClTH5wjobj4gZq7O/Y6eQJFMwmaey3uwjY0XU+MqC2qT7mM+/onK5 uvbhPvEGH3ycbe0ObdQlzWG4Qx7lrH9cT1R7ztYP/TPRiMbSNz7eiOqjgJipClvGRBoi vcFA== Received: by 10.236.175.7 with SMTP id y7mr7162763yhl.14.1354566493395; Mon, 03 Dec 2012 12:28:13 -0800 (PST) Received: from wpzn3.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id j36si510711anp.0.2012.12.03.12.28.13 (version=TLSv1/SSLv3 cipher=AES128-SHA); Mon, 03 Dec 2012 12:28:13 -0800 (PST) Received: from mosfet.mtv.corp.google.com (mosfet.mtv.corp.google.com [172.17.131.44]) by wpzn3.hot.corp.google.com (Postfix) with ESMTP id 3C33C100047; Mon, 3 Dec 2012 12:28:13 -0800 (PST) Received: by mosfet.mtv.corp.google.com (Postfix, from userid 56300) id DC7FE1E12C0; Mon, 3 Dec 2012 12:28:12 -0800 (PST) From: Paul Marks To: davem@davemloft.net Cc: yoshfuji@linux-ipv6.org, netdev@vger.kernel.org, Paul Marks Subject: [PATCH v2] ipv6: Fix default route failover when CONFIG_IPV6_ROUTER_PREF=n Date: Mon, 3 Dec 2012 12:26:54 -0800 Message-Id: <1354566414-5752-1-git-send-email-pmarks@google.com> X-Mailer: git-send-email 1.7.7.3 In-Reply-To: <20121203.135923.1359930693250099951.davem@davemloft.net> References: <20121203.135923.1359930693250099951.davem@davemloft.net> X-Gm-Message-State: ALoCoQkyC9ln+XRap8rb0oe54tLxTON94jh9/UaXblqb36/acMWeE5wv3bKe3YBjgNaYG6ZzzPtrTJXzDrdawInbP4xPS5W4TUmKHM9cixAGU69jCA6LNpKN4rNY58gwDxK6kIBBbJotLsIs3v2h+OsXaQQgWfDNwYgAbaFFYv1L0fzdZalK/lySZrhp6xzeFhDWUuxS4ktn Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org I believe this commit from 2008 was incorrect: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=398bcbebb6f721ac308df1e3d658c0029bb74503 When CONFIG_IPV6_ROUTER_PREF is disabled, the kernel should follow RFC4861 section 6.3.6: if no route is NUD_VALID, then traffic should be sprayed across all routers (indirectly triggering NUD) until one of them becomes NUD_VALID. However, the following experiment demonstrates that this does not work: 1) Connect to an IPv6 network. 2) Change the router's MAC (and link-local) address. The kernel will lock onto the first router and never try the new one, even if the first becomes unreachable. This patch fixes the problem by allowing rt6_check_neigh() to return 0; if all routers return 0, then rt6_select() will fall back to round-robin behavior. This patch should have no effect when CONFIG_IPV6_ROUTER_PREF=y. Note that rt6_check_neigh() is only used in a boolean context, so I've changed its return type accordingly. Signed-off-by: Paul Marks --- Changelog since v1: - Changed return type from 'int' to 'bool'. net/ipv6/route.c | 24 ++++++++++-------------- 1 files changed, 10 insertions(+), 14 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b1e6cf0..35f2815 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -487,35 +487,32 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif) return 0; } -static inline int rt6_check_neigh(struct rt6_info *rt) +static inline bool rt6_check_neigh(struct rt6_info *rt) { struct neighbour *neigh; - int m; + bool ret = false; neigh = rt->n; if (rt->rt6i_flags & RTF_NONEXTHOP || !(rt->rt6i_flags & RTF_GATEWAY)) - m = 1; + ret = true; else if (neigh) { read_lock_bh(&neigh->lock); if (neigh->nud_state & NUD_VALID) - m = 2; + ret = true; #ifdef CONFIG_IPV6_ROUTER_PREF - else if (neigh->nud_state & NUD_FAILED) - m = 0; + else if (!(neigh->nud_state & NUD_FAILED)) + ret = true; #endif - else - m = 1; read_unlock_bh(&neigh->lock); - } else - m = 0; - return m; + } + return ret; } static int rt6_score_route(struct rt6_info *rt, int oif, int strict) { - int m, n; + int m; m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_LOOKUP_F_IFACE)) @@ -523,8 +520,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; #endif - n = rt6_check_neigh(rt); - if (!n && (strict & RT6_LOOKUP_F_REACHABLE)) + if (!rt6_check_neigh(rt) && (strict & RT6_LOOKUP_F_REACHABLE)) return -1; return m; }