From patchwork Fri Sep 8 07:01:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 811347 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3xpStW2HNjz9t16; Fri, 8 Sep 2017 17:02:11 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1dqDIm-0001Mx-DC; Fri, 08 Sep 2017 07:02:08 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1dqDIj-0001LJ-My for kernel-team@lists.canonical.com; Fri, 08 Sep 2017 07:02:05 +0000 Received: from mail-pg0-f70.google.com ([74.125.83.70]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1dqDIj-0003De-BF for kernel-team@lists.canonical.com; Fri, 08 Sep 2017 07:02:05 +0000 Received: by mail-pg0-f70.google.com with SMTP id m9so3670761pgd.2 for ; Fri, 08 Sep 2017 00:02:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=cgS8m6Ztn55wnDgpkDY3eo8XvLCedmwj/oh0yBxZLhQ=; b=LPpKYwaJTrBH/Jz4qOzC0zuGJ0Qie4eyCRjW0Cxs+BYhGNU3agu7f/X6kkAL/tbicU /4P4x1Ms23AEip1p+kevSXRXdwaZ4qaPSBa+j/+Mc/goulArweJW3MW7bCJWDViUiRus gL8zaLJXBYDA22xT0xDwdNNEPc2uNjuC75mpK6vIMUMrORvAIgioFZ/ytFZ36m8Gs8WT B+E3sxLeb/urW/pwNcVm7oZZWyKQPpnYGdS/v7Jr+GhNF6F2ukTUecMoO7PGuw334BSP NpE5RjSwH7fouYQgxI8kU3LG2haHr6dXOn9oxKCbApUA/zPOWEiFVccZcP0/sNegSkEu Yg1g== X-Gm-Message-State: AHPjjUjBvOnKtbIRaIUPtiRV8BK6FGmKkv37l9XRccfAtl7Vu8Y+H6zb QM5SAVgYSrmv2iixionxmoeN1DNdWlNGPvqDN3wNEtgiyb+9x90f52ocxGcTKL9L241k9J3ey6b nq9AiwbfHz9r3Ain+kd5HB5Mkj90IZLH0a2NQ0wE= X-Received: by 10.98.32.92 with SMTP id g89mr2082702pfg.285.1504854123130; Fri, 08 Sep 2017 00:02:03 -0700 (PDT) X-Google-Smtp-Source: ADKCNb7YYh7Bc4plBhXwfwJuC9A+JYBJrMKmXVH3E5CckzqxdrtwK06Bez2Jj3HmqXFBTfxV9ePYjg== X-Received: by 10.98.32.92 with SMTP id g89mr2082676pfg.285.1504854122538; Fri, 08 Sep 2017 00:02:02 -0700 (PDT) Received: from localhost.localdomain (124-171-202-56.dyn.iinet.net.au. [124.171.202.56]) by smtp.gmail.com with ESMTPSA id h1sm2255518pfg.153.2017.09.08.00.02.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 Sep 2017 00:02:01 -0700 (PDT) From: Daniel Axtens To: kernel-team@lists.canonical.com Subject: [SRU][Xenial][PATCH 6/7] net: use dst_confirm_neigh for UDP, RAW, ICMP, L2TP Date: Fri, 8 Sep 2017 17:01:41 +1000 Message-Id: <20170908070142.4440-7-daniel.axtens@canonical.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170908070142.4440-1-daniel.axtens@canonical.com> References: <20170908070142.4440-1-daniel.axtens@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Julian Anastasov BugLink: https://bugs.launchpad.net/bugs/1715812 When same struct dst_entry can be used for many different neighbours we can not use it for pending confirmations. The datagram protocols can use MSG_CONFIRM to confirm the neighbour. When used with MSG_PROBE we do not reach the code where neighbour is confirmed, so we have to do the same slow lookup by using the dst_confirm_neigh() helper. When MSG_PROBE is not used, ip_append_data/ip6_append_data will set the skb flag dst_pending_confirm. Reported-by: YueHaibing Fixes: 5110effee8fd ("net: Do delayed neigh confirmation.") Fixes: f2bb4bedf35d ("ipv4: Cache output routes in fib_info nexthops.") Signed-off-by: Julian Anastasov Acked-by: Eric Dumazet Signed-off-by: David S. Miller (backported from commit 0dec879f636f11b0ffda1cb5fd96a1754c59ead3) Signed-off-by: Daniel Axtens --- net/ipv4/ip_output.c | 6 ++++++ net/ipv4/ping.c | 3 ++- net/ipv4/raw.c | 6 +++++- net/ipv4/udp.c | 3 ++- net/ipv6/ip6_output.c | 6 ++++++ net/ipv6/raw.c | 6 +++++- net/ipv6/route.c | 27 ++++++++++++++------------- net/ipv6/udp.c | 3 ++- net/l2tp/l2tp_ip6.c | 3 ++- 9 files changed, 44 insertions(+), 19 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 17030a6bed20..b69c680d1a5c 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -853,6 +853,9 @@ static inline int ip_ufo_append_data(struct sock *sk, skb->csum = 0; + if (flags & MSG_CONFIRM) + skb_set_dst_pending_confirm(skb, 1); + __skb_queue_tail(queue, skb); } else if (skb_is_gso(skb)) { goto append; @@ -1055,6 +1058,9 @@ alloc_new_skb: exthdrlen = 0; csummode = CHECKSUM_NONE; + if ((flags & MSG_CONFIRM) && !skb_prev) + skb_set_dst_pending_confirm(skb, 1); + /* * Put the packet on the pending queue. */ diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 37a3b05d175c..c173d794c72c 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -852,7 +852,8 @@ out: return err; do_confirm: - dst_confirm(&rt->dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(&rt->dst, &fl4.daddr); if (!(msg->msg_flags & MSG_PROBE) || len) goto back_from_confirm; err = 0; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 8f2cd7d09720..1f14994f8349 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -382,6 +382,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + if (flags & MSG_CONFIRM) + skb_set_dst_pending_confirm(skb, 1); + skb->transport_header = skb->network_header; err = -EFAULT; if (memcpy_from_msg(iph, msg, length)) @@ -670,7 +673,8 @@ out: return len; do_confirm: - dst_confirm(&rt->dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(&rt->dst, &fl4.daddr); if (!(msg->msg_flags & MSG_PROBE) || len) goto back_from_confirm; err = 0; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 301e60829c7e..6cb4565e4bcc 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1123,7 +1123,8 @@ out: return err; do_confirm: - dst_confirm(&rt->dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(&rt->dst, &fl4->daddr); if (!(msg->msg_flags&MSG_PROBE) || len) goto back_from_confirm; err = 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index f3d5b42584e6..4b775a2269b9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1134,6 +1134,9 @@ static inline int ip6_ufo_append_data(struct sock *sk, skb->protocol = htons(ETH_P_IPV6); skb->csum = 0; + if (flags & MSG_CONFIRM) + skb_set_dst_pending_confirm(skb, 1); + __skb_queue_tail(queue, skb); } else if (skb_is_gso(skb)) { goto append; @@ -1507,6 +1510,9 @@ alloc_new_skb: exthdrlen = 0; dst_exthdrlen = 0; + if ((flags & MSG_CONFIRM) && !skb_prev) + skb_set_dst_pending_confirm(skb, 1); + /* * Put the packet on the pending queue */ diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4d52a0e2f60d..cd2184c1caf9 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -654,6 +654,9 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, skb->ip_summed = CHECKSUM_NONE; + if (flags & MSG_CONFIRM) + skb_set_dst_pending_confirm(skb, 1); + skb->transport_header = skb->network_header; err = memcpy_from_msg(iph, msg, length); if (err) @@ -918,7 +921,8 @@ out: txopt_put(opt_to_free); return err < 0 ? err : len; do_confirm: - dst_confirm(dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(dst, &fl6.daddr); if (!(msg->msg_flags & MSG_PROBE) || len) goto back_from_confirm; err = 0; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bba100e85114..7cfcfbdd99f8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1356,31 +1356,32 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, const struct ipv6hdr *iph, u32 mtu) { + const struct in6_addr *daddr, *saddr; struct rt6_info *rt6 = (struct rt6_info *)dst; if (rt6->rt6i_flags & RTF_LOCAL) return; - dst_confirm(dst); + if (iph) { + daddr = &iph->daddr; + saddr = &iph->saddr; + } else if (sk) { + daddr = &sk->sk_v6_daddr; + saddr = &inet6_sk(sk)->saddr; + } else { + daddr = NULL; + saddr = NULL; + } + dst_confirm_neigh(dst, daddr); mtu = max_t(u32, mtu, IPV6_MIN_MTU); if (mtu >= dst_mtu(dst)) return; if (!rt6_cache_allowed_for_pmtu(rt6)) { rt6_do_update_pmtu(rt6, mtu); - } else { - const struct in6_addr *daddr, *saddr; + } else if (daddr) { struct rt6_info *nrt6; - if (iph) { - daddr = &iph->daddr; - saddr = &iph->saddr; - } else if (sk) { - daddr = &sk->sk_v6_daddr; - saddr = &inet6_sk(sk)->saddr; - } else { - return; - } nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr); if (nrt6) { rt6_do_update_pmtu(nrt6, mtu); @@ -2188,7 +2189,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu * Look, redirects are sent only in response to data packets, * so that this nexthop apparently is reachable. --ANK */ - dst_confirm(&rt->dst); + dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr); neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1); if (!neigh) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 6fd4af3b5b79..4ce78d96d97e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1398,7 +1398,8 @@ out: return err; do_confirm: - dst_confirm(dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(dst, &fl6.daddr); if (!(msg->msg_flags&MSG_PROBE) || len) goto back_from_confirm; err = 0; diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index bcdab1cba773..5cf39d2a3dbd 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -642,7 +642,8 @@ out: return err < 0 ? err : len; do_confirm: - dst_confirm(dst); + if (msg->msg_flags & MSG_PROBE) + dst_confirm_neigh(dst, &fl6.daddr); if (!(msg->msg_flags & MSG_PROBE) || len) goto back_from_confirm; err = 0;