Received: by 2002:a25:86ce:0:0:0:0:0 with SMTP id y14csp2167984ybm; Thu, 23 May 2019 12:28:33 -0700 (PDT) X-Google-Smtp-Source: APXvYqwSkhmm1fZFdUPpWP27XUlaig51Pg7kVJwUvMK3rmtVRiJcLkgE7WYUtRMrgDanAt4W3i0P X-Received: by 2002:a17:902:2883:: with SMTP id f3mr74691173plb.26.1558639713543; Thu, 23 May 2019 12:28:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558639713; cv=none; d=google.com; s=arc-20160816; b=dfnmObIb89xDMd7TzuBnQ1ggejIEZYHhPMfojGRmYybOQJVBrhykLKJP4hUEcq36Pg YgGqBtoNEqsx29WO6VAO5kle+E8nvgTpNmqyTIehlFyCVtG4OPnZv81WFF4/n9q5Vc+b +lIH36ZbCeNlzraRAzN1S5O4JtkdICX2Soe1l5R/jPTnzg6reYq2/9zuSMcbVup+cKN0 nV1S1+LAuPpd3kbRPvqxVUVk7t2HTk53VhjwlNIKqsUCoQidi7BpByJZ8wNP0TqAGIX9 KZaVyFvNpCeSDB4VuHNHUjXBhpLRe4Ah71rsg+wBFecRoJCioXXwvgOwyANdOx/mZ3MF vtvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=2IBWUqIvTNCcy5+kPROUS6shCX3KXHSFh8RgG9Vyf2A=; b=WvsQXLWpMN6tHr1N2ihfl7HquTP5jjR6uNDoBk5D05w7KKocZ3BfL8ZmUvXuQNOQkN 2LCjWzbN4LK9TB8kmjI3qFVAhj4riW0jIjNRSCpiMysHoewNaImEEWm14KkFtPOy8KAd ZLzNFWUAjsddxzWIAlOGBQ/M9NwtcY9CQXtJ1dITxZCKZzcvMVfinGvH5Ox2n1/Ke0Jg Dg1xai5KLonDKJ9Rp2ByPwD2axm9h4fAiEXOe3EdDYUYJh1oTcr01HchFtT8Nv8f62nE fo59gItep2j8d5mpbfSxX/MLM9x5iM6fXrN66M8qMu4uuDrAgsvwSuBoTDklqTuIWdJI PF/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=Se5eqo7Y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y134si389839pfc.156.2019.05.23.12.28.18; Thu, 23 May 2019 12:28:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=Se5eqo7Y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391242AbfEWTZ7 (ORCPT + 99 others); Thu, 23 May 2019 15:25:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:37668 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391228AbfEWTZ5 (ORCPT ); Thu, 23 May 2019 15:25:57 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 5D4F6217D9; Thu, 23 May 2019 19:25:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1558639556; bh=2oQPVjb/XH6t5N0VlZPojdoMnrm+tfWh1CGpuHuzy8M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Se5eqo7YphNDsf/vlKqGOvdtp3p/oyMHFtnr7O2NEU7qZsiiIv2fqcl6GkbJa4FeH V6j/hJe25e5ICGJwCxV4a33UZy2Wz1Mc5FQThW43Nii4p7PDanqhMRVAFcoj+fr7cW ifOmkO+fYTfewcRTY0YJxXPTcU9DBFuCbC8lKrHA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mikael Magnusson , Wei Wang , Martin Lau , Eric Dumazet , "David S. Miller" , David Ahern Subject: [PATCH 5.1 001/122] ipv6: fix src addr routing with the exception table Date: Thu, 23 May 2019 21:05:23 +0200 Message-Id: <20190523181705.324928617@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190523181705.091418060@linuxfoundation.org> References: <20190523181705.091418060@linuxfoundation.org> User-Agent: quilt/0.66 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Wei Wang [ Upstream commit 510e2ceda031eed97a7a0f9aad65d271a58b460d ] When inserting route cache into the exception table, the key is generated with both src_addr and dest_addr with src addr routing. However, current logic always assumes the src_addr used to generate the key is a /128 host address. This is not true in the following scenarios: 1. When the route is a gateway route or does not have next hop. (rt6_is_gw_or_nonexthop() == false) 2. When calling ip6_rt_cache_alloc(), saddr is passed in as NULL. This means, when looking for a route cache in the exception table, we have to do the lookup twice: first time with the passed in /128 host address, second time with the src_addr stored in fib6_info. This solves the pmtu discovery issue reported by Mikael Magnusson where a route cache with a lower mtu info is created for a gateway route with src addr. However, the lookup code is not able to find this route cache. Fixes: 2b760fcf5cfb ("ipv6: hook up exception table to store dst cache") Reported-by: Mikael Magnusson Bisected-by: David Ahern Signed-off-by: Wei Wang Cc: Martin Lau Cc: Eric Dumazet Acked-by: Martin KaFai Lau Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -110,8 +110,8 @@ static int rt6_fill_node(struct net *net int iif, int type, u32 portid, u32 seq, unsigned int flags); static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt, - struct in6_addr *daddr, - struct in6_addr *saddr); + const struct in6_addr *daddr, + const struct in6_addr *saddr); #ifdef CONFIG_IPV6_ROUTE_INFO static struct fib6_info *rt6_add_route_info(struct net *net, @@ -1529,31 +1529,44 @@ out: * Caller has to hold rcu_read_lock() */ static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt, - struct in6_addr *daddr, - struct in6_addr *saddr) + const struct in6_addr *daddr, + const struct in6_addr *saddr) { + const struct in6_addr *src_key = NULL; struct rt6_exception_bucket *bucket; - struct in6_addr *src_key = NULL; struct rt6_exception *rt6_ex; struct rt6_info *res = NULL; - bucket = rcu_dereference(rt->rt6i_exception_bucket); - #ifdef CONFIG_IPV6_SUBTREES /* rt6i_src.plen != 0 indicates rt is in subtree * and exception table is indexed by a hash of * both rt6i_dst and rt6i_src. - * Otherwise, the exception table is indexed by - * a hash of only rt6i_dst. + * However, the src addr used to create the hash + * might not be exactly the passed in saddr which + * is a /128 addr from the flow. + * So we need to use f6i->fib6_src to redo lookup + * if the passed in saddr does not find anything. + * (See the logic in ip6_rt_cache_alloc() on how + * rt->rt6i_src is updated.) */ if (rt->fib6_src.plen) src_key = saddr; +find_ex: #endif + bucket = rcu_dereference(rt->rt6i_exception_bucket); rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key); if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i)) res = rt6_ex->rt6i; +#ifdef CONFIG_IPV6_SUBTREES + /* Use fib6_src as src_key and redo lookup */ + if (!res && src_key && src_key != &rt->fib6_src.addr) { + src_key = &rt->fib6_src.addr; + goto find_ex; + } +#endif + return res; } @@ -2608,10 +2621,8 @@ out: u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr, struct in6_addr *saddr) { - struct rt6_exception_bucket *bucket; - struct rt6_exception *rt6_ex; - struct in6_addr *src_key; struct inet6_dev *idev; + struct rt6_info *rt; u32 mtu = 0; if (unlikely(fib6_metric_locked(f6i, RTAX_MTU))) { @@ -2620,18 +2631,10 @@ u32 ip6_mtu_from_fib6(struct fib6_info * goto out; } - src_key = NULL; -#ifdef CONFIG_IPV6_SUBTREES - if (f6i->fib6_src.plen) - src_key = saddr; -#endif - - bucket = rcu_dereference(f6i->rt6i_exception_bucket); - rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key); - if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i)) - mtu = dst_metric_raw(&rt6_ex->rt6i->dst, RTAX_MTU); - - if (likely(!mtu)) { + rt = rt6_find_cached_rt(f6i, daddr, saddr); + if (unlikely(rt)) { + mtu = dst_metric_raw(&rt->dst, RTAX_MTU); + } else { struct net_device *dev = fib6_info_nh_dev(f6i); mtu = IPV6_MIN_MTU;