From patchwork Fri Sep 8 07:00:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 811338 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 3xpSrs1qpCz9sDB; Fri, 8 Sep 2017 17:00:45 +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 1dqDHO-0000sJ-B2; Fri, 08 Sep 2017 07:00:42 +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 1dqDHM-0000qF-R0 for kernel-team@lists.canonical.com; Fri, 08 Sep 2017 07:00:40 +0000 Received: from mail-pg0-f71.google.com ([74.125.83.71]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1dqDHM-00039f-FL for kernel-team@lists.canonical.com; Fri, 08 Sep 2017 07:00:40 +0000 Received: by mail-pg0-f71.google.com with SMTP id 6so3680370pgh.0 for ; Fri, 08 Sep 2017 00:00:40 -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=ZKkU74er4YHs7Awyazs/slBZ/mZx8/vxdMaODP+rZ1c=; b=bu6TzAl1G2fPbcdC/f1DFAkzzQ+v8IUI4VEIZQHde7RKUDmjIEGFxqfFw9v1lbyxmz iGDRt61fAiGSwQ5B2KqnEJrj2reDxRXCS+PrDLb4pItBD4maaLi3i56qIPbjtPWiD857 6odeCvIMeb/pxv0fKrU7NOHrPeYfgad1iVyk4PA7dyJhKxADxQEBByuh7ZmqZSGCBs1F wA9PvEJ45bKb2UQteKvzB9uukRZdxHZo14pW6xkjasWhVdsYcYEk9Uy/Rprbqd1TQ/ER v1eggzqDfmbUXdGKwGdGV1VHSel/4WfDIMIatf31JdCPp0hqdVkuaRo2XJKnRkQseYll t6FA== X-Gm-Message-State: AHPjjUh+I9hivzV7EFbzWvSpvjAouJX/E53KVr9J9+KwsnpothwZNDcU pBnZBuu9iAXw4q4+KinQ2W3mls9DHqycHaNhJdqnhcB4Ww7/BlxDsXF6iwQNccBU06O2HcjQKZR Msl7MxHPlL1+2ypaSKSc5TeZgLvd+zkpRP8Qk+Ls= X-Received: by 10.84.236.69 with SMTP id h5mr2293149pln.338.1504854038828; Fri, 08 Sep 2017 00:00:38 -0700 (PDT) X-Google-Smtp-Source: ADKCNb4yfylNkDcZtWbRyr6sQaSAXhclflwKZHZJrNmeQxu+FjYozJBwFcVRZHWR9NxMf71/X0i7Gw== X-Received: by 10.84.236.69 with SMTP id h5mr2293137pln.338.1504854038589; Fri, 08 Sep 2017 00:00:38 -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 125sm2138129pff.5.2017.09.08.00.00.36 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 Sep 2017 00:00:38 -0700 (PDT) From: Daniel Axtens To: kernel-team@lists.canonical.com Subject: [SRU][Zesty][PATCH 5/7] net: add confirm_neigh method to dst_ops Date: Fri, 8 Sep 2017 17:00:16 +1000 Message-Id: <20170908070018.4141-6-daniel.axtens@canonical.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170908070018.4141-1-daniel.axtens@canonical.com> References: <20170908070018.4141-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 Add confirm_neigh method to dst_ops and use it from IPv4 and IPv6 to lookup and confirm the neighbour. Its usage via the new helper dst_confirm_neigh() should be restricted to MSG_PROBE users for performance reasons. For XFRM prefer the last tunnel address, if present. With help from Steffen Klassert. Signed-off-by: Julian Anastasov Acked-by: Steffen Klassert Signed-off-by: David S. Miller (cherry picked from commit 63fca65d08632fbec9d9b655f671cf08aa1aeeb8) Signed-off-by: Daniel Axtens --- include/net/arp.h | 16 ++++++++++++++++ include/net/dst.h | 7 +++++++ include/net/dst_ops.h | 2 ++ include/net/ndisc.h | 17 +++++++++++++++++ net/ipv4/route.c | 19 +++++++++++++++++++ net/ipv6/route.c | 16 ++++++++++++++++ net/xfrm/xfrm_policy.c | 19 +++++++++++++++++++ 7 files changed, 96 insertions(+) diff --git a/include/net/arp.h b/include/net/arp.h index 5e0f891d476c..65619a2de6f4 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -35,6 +35,22 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 return n; } +static inline void __ipv4_confirm_neigh(struct net_device *dev, u32 key) +{ + struct neighbour *n; + + rcu_read_lock_bh(); + n = __ipv4_neigh_lookup_noref(dev, key); + if (n) { + unsigned long now = jiffies; + + /* avoid dirtying neighbour */ + if (n->confirmed != now) + n->confirmed = now; + } + rcu_read_unlock_bh(); +} + void arp_init(void); int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg); void arp_send(int type, int ptype, __be32 dest_ip, diff --git a/include/net/dst.h b/include/net/dst.h index 6835d224d47b..3a3b34b83b00 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -477,6 +477,13 @@ static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst return IS_ERR(n) ? NULL : n; } +static inline void dst_confirm_neigh(const struct dst_entry *dst, + const void *daddr) +{ + if (dst->ops->confirm_neigh) + dst->ops->confirm_neigh(dst, daddr); +} + static inline void dst_link_failure(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index a0d443ca16fc..0d0481827098 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -33,6 +33,8 @@ struct dst_ops { struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, struct sk_buff *skb, const void *daddr); + void (*confirm_neigh)(const struct dst_entry *dst, + const void *daddr); struct kmem_cache *kmem_cachep; diff --git a/include/net/ndisc.h b/include/net/ndisc.h index d562a2fe4860..8a0214654b6b 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -391,6 +391,23 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons return n; } +static inline void __ipv6_confirm_neigh(struct net_device *dev, + const void *pkey) +{ + struct neighbour *n; + + rcu_read_lock_bh(); + n = __ipv6_neigh_lookup_noref(dev, pkey); + if (n) { + unsigned long now = jiffies; + + /* avoid dirtying neighbour */ + if (n->confirmed != now) + n->confirmed = now; + } + rcu_read_unlock_bh(); +} + int ndisc_init(void); int ndisc_late_init(void); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6263af2f6ce8..e8b00e9df87f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -154,6 +154,7 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, struct sk_buff *skb, const void *daddr); +static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr); static struct dst_ops ipv4_dst_ops = { .family = AF_INET, @@ -168,6 +169,7 @@ static struct dst_ops ipv4_dst_ops = { .redirect = ip_do_redirect, .local_out = __ip_local_out, .neigh_lookup = ipv4_neigh_lookup, + .confirm_neigh = ipv4_confirm_neigh, }; #define ECN_OR_COST(class) TC_PRIO_##class @@ -461,6 +463,23 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, return neigh_create(&arp_tbl, pkey, dev); } +static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr) +{ + struct net_device *dev = dst->dev; + const __be32 *pkey = daddr; + const struct rtable *rt; + + rt = (const struct rtable *)dst; + if (rt->rt_gateway) + pkey = (const __be32 *)&rt->rt_gateway; + else if (!daddr || + (rt->rt_flags & + (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL))) + return; + + __ipv4_confirm_neigh(dev, *(__force u32 *)pkey); +} + #define IP_IDENTS_SZ 2048u static atomic_t *ip_idents __read_mostly; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d5c2e35c4e26..9737526aefdf 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -217,6 +217,21 @@ static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, return neigh_create(&nd_tbl, daddr, dst->dev); } +static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr) +{ + struct net_device *dev = dst->dev; + struct rt6_info *rt = (struct rt6_info *)dst; + + daddr = choose_neigh_daddr(rt, NULL, daddr); + if (!daddr) + return; + if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) + return; + if (ipv6_addr_is_multicast((const struct in6_addr *)daddr)) + return; + __ipv6_confirm_neigh(dev, daddr); +} + static struct dst_ops ip6_dst_ops_template = { .family = AF_INET6, .gc = ip6_dst_gc, @@ -233,6 +248,7 @@ static struct dst_ops ip6_dst_ops_template = { .redirect = rt6_do_redirect, .local_out = __ip6_local_out, .neigh_lookup = ip6_neigh_lookup, + .confirm_neigh = ip6_confirm_neigh, }; static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 3c8f5b70abf8..a484c24a2a54 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2856,6 +2856,23 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, return dst->path->ops->neigh_lookup(dst, skb, daddr); } +static void xfrm_confirm_neigh(const struct dst_entry *dst, const void *daddr) +{ + const struct dst_entry *path = dst->path; + + for (; dst != path; dst = dst->child) { + const struct xfrm_state *xfrm = dst->xfrm; + + if (xfrm->props.mode == XFRM_MODE_TRANSPORT) + continue; + if (xfrm->type->flags & XFRM_TYPE_REMOTE_COADDR) + daddr = xfrm->coaddr; + else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR)) + daddr = &xfrm->id.daddr; + } + path->ops->confirm_neigh(path, daddr); +} + int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) { int err = 0; @@ -2882,6 +2899,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) dst_ops->link_failure = xfrm_link_failure; if (likely(dst_ops->neigh_lookup == NULL)) dst_ops->neigh_lookup = xfrm_neigh_lookup; + if (likely(!dst_ops->confirm_neigh)) + dst_ops->confirm_neigh = xfrm_confirm_neigh; if (likely(afinfo->garbage_collect == NULL)) afinfo->garbage_collect = xfrm_garbage_collect_deferred; rcu_assign_pointer(xfrm_policy_afinfo[afinfo->family], afinfo);