Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754049AbdIRJNH (ORCPT ); Mon, 18 Sep 2017 05:13:07 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:55334 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754028AbdIRJNF (ORCPT ); Mon, 18 Sep 2017 05:13:05 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Hannes Frederic Sowa , Paolo Abeni , "David S. Miller" Subject: [PATCH 4.12 15/52] udp6: set rx_dst_cookie on rx_dst updates Date: Mon, 18 Sep 2017 11:11:09 +0200 Message-Id: <20170918091018.871749129@linuxfoundation.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170918091016.620101134@linuxfoundation.org> References: <20170918091016.620101134@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2680 Lines: 89 4.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Paolo Abeni [ Upstream commit 64f0f5d18a47c703c85576375cc010e83dac6a48 ] Currently, in the udp6 code, the dst cookie is not initialized/updated concurrently with the RX dst used by early demux. As a result, the dst_check() in the early_demux path always fails, the rx dst cache is always invalidated, and we can't really leverage significant gain from the demux lookup. Fix it adding udp6 specific variant of sk_rx_dst_set() and use it to set the dst cookie when the dst entry is really changed. The issue is there since the introduction of early demux for ipv6. Fixes: 5425077d73e0 ("net: ipv6: Add early demux handler for UDP unicast") Acked-by: Hannes Frederic Sowa Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/udp.h | 2 +- net/ipv4/udp.c | 3 ++- net/ipv6/udp.c | 11 ++++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) --- a/include/net/udp.h +++ b/include/net/udp.h @@ -265,7 +265,7 @@ static inline struct sk_buff *skb_recv_u } void udp_v4_early_demux(struct sk_buff *skb); -void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst); +bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst); int udp_get_port(struct sock *sk, unsigned short snum, int (*saddr_cmp)(const struct sock *, const struct sock *)); --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1762,13 +1762,14 @@ drop: /* For TCP sockets, sk_rx_dst is protected by socket lock * For UDP, we use xchg() to guard against concurrent changes. */ -void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) +bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) { struct dst_entry *old; dst_hold(dst); old = xchg(&sk->sk_rx_dst, dst); dst_release(old); + return old != dst; } /* --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -752,6 +752,15 @@ start_lookup: return 0; } +static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) +{ + if (udp_sk_rx_dst_set(sk, dst)) { + const struct rt6_info *rt = (const struct rt6_info *)dst; + + inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); + } +} + int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int proto) { @@ -801,7 +810,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, int ret; if (unlikely(sk->sk_rx_dst != dst)) - udp_sk_rx_dst_set(sk, dst); + udp6_sk_rx_dst_set(sk, dst); ret = udpv6_queue_rcv_skb(sk, skb); sock_put(sk);