From patchwork Fri Mar 23 18:19:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rosen Penev X-Patchwork-Id: 890097 X-Patchwork-Delegate: openwrt@kresin.me 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.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="LqPNObRW"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="p1K3fsSM"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 407Bdp6RF4z9s08 for ; Sat, 24 Mar 2018 05:19:42 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Subject:Message-Id: Date:To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=b3+Oq2Lz5TQeyjfSj8KXaz239MnJ+Ca2OUWOPEKba8k=; b=LqPNObRWq9qx8N CEsZus43HDs8T8+uW14RJeSMfGuABycTtFCKawEAzDMJ0+W4ETqeQTGBqsNh1fsGQlESiHinRohMA FwEqNLFslP71Ws9gzLhvtSnR2bddJPVxfbpLNN/pUaeCzQMWPZyyOPZORD2mQE6F4hXV4cUSlcXla mdQ5BrG1IUNQCpNQ6uRvo29njGw0LOmOBqeNDXEVYsuYLt6cPD1YFkH0yA1RuMlUkvHd7j3l+fuzj S5cJttJATJNfllbXkkH54MeYAX/lnyUpj8hr8wwP9dBZSsIXjGoO9wlz4+y6WtHYUl5fPOc/+InlH 7HOln5QRIz3nKvqERayA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1ezRHm-0005ek-VS; Fri, 23 Mar 2018 18:19:30 +0000 Received: from mail-pg0-x229.google.com ([2607:f8b0:400e:c05::229]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1ezRHg-0005d1-5E for lede-dev@lists.infradead.org; Fri, 23 Mar 2018 18:19:29 +0000 Received: by mail-pg0-x229.google.com with SMTP id a19so4877812pgw.6 for ; Fri, 23 Mar 2018 11:19:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=/KMZNXUj5mfspTYkeQjLsikr2eEJ71ykXkvEKjrhZ/Y=; b=p1K3fsSM1NkfuYIDjPg9mxcA0siOmWi0xuKF3tEM+Aa6rdbp0+uz+ByyXif6S4Trmi +JDzE3oOMOL6LYQncHa46I5n6V4oEKJICKXPFuLGbg8yC5qdDM1EDPrGe+o0KjDZFNz5 SZaxxV7HdE8jRFj9aD08phYbpqSzZyqriHE/Av7ALG2yFhQqyMOqI27laZ0HaddDQqHP S/2wedF0BhAj9nBKekn4emfYW4tSyP7Hum6ux8z7vLuU4CxeGQpjknqqN3SVOAsRX2fQ 8V2V2ReDl6YokWkjbmKj5DmYz4y75eiiAbUczL8+YUwS0NQSzyIx2MGEFsdH+Rt8DsP5 daHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=/KMZNXUj5mfspTYkeQjLsikr2eEJ71ykXkvEKjrhZ/Y=; b=d7DUrv/zMuy4jmbySGbn+42l2zlksPfYNy0ijUK3BRVLYQO+0IEhSvAkhEU6K57iu3 I+lNHtUDkecRDzNyjJM+4pH71300TuwVjI6Ni3M6PVE/1V71NoAVmuN6kxsqbRENL1Wy gqhPX1J6ahu9Ney3bs6et79CuHAdU4W5UFEGIZrVxdR6tpEcwgSM9Fhxlv3ewugyHJZ2 AYZ25ZyOUieRKh7X8VAYaqW39DX25EOpqHW/5MnbTjksNhFTgNVZ4R92KEDwxkm2icg9 hsabv7/17uah+HJfRIyybZtZHEIJI7PCUBHs/mGf0wcKcxRn/bLlVQ2GHYUht2wDmvxz xt7Q== X-Gm-Message-State: AElRT7GvMpOZjXY3Y4mSZ4d4HxKGZkNmaqsBXe4pQ6c23ziey0oOdW0i QCVgIyhp+UsuhweANU2xW/fS1mB3 X-Google-Smtp-Source: AG47ELskFFKhEggfqVGtMvD9Az+QUQYjpUPw/0gppjNL++2WJWLndwmCKprCkMO1ZWpl0st4jM0qXw== X-Received: by 10.99.124.68 with SMTP id l4mr21666293pgn.225.1521829150953; Fri, 23 Mar 2018 11:19:10 -0700 (PDT) Received: from desktop.lan (astound-69-42-5-101.ca.astound.net. [69.42.5.101]) by smtp.gmail.com with ESMTPSA id m18sm16090687pgu.51.2018.03.23.11.19.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Mar 2018 11:19:10 -0700 (PDT) From: Rosen Penev To: lede-dev@lists.infradead.org Date: Fri, 23 Mar 2018 11:19:07 -0700 Message-Id: <20180323181907.18342-1-rosenp@gmail.com> X-Mailer: git-send-email 2.16.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180323_111924_340946_01727649 X-CRM114-Status: GOOD ( 23.68 ) X-Spam-Score: -0.1 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:400e:c05:0:0:0:229 listed in] [list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (rosenp[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain Subject: [LEDE-DEV] [PATCH] kernel: Backport net struct reduction from 4.16. X-BeenThere: lede-dev@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Rosen Penev MIME-Version: 1.0 Sender: "Lede-dev" Errors-To: lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This patch series shrinks the networking structs in order to reduce cache misses. This has performance benefits in routing. Full details here: https://www.netdevconf.org/2.2/slides/miller-datastructurebloat-keynote.pdf I'm keeping this for kernel 4.14 as it's easier to port. I have tested this on mvebu for several days with no issues to report. mvebu is powerful enough for gigabit routing though. Signed-off-by: Rosen Penev --- .../400-net-dst-rt_next-is-unused.patch | 28 ++ ...-Move-dn_next-into-decnet-route-structure.patch | 161 +++++++++++ ...t6_next-from-dst_entry-into-ipv6-route-st.patch | 304 ++++++++++++++++++++ ...-Create-and-use-new-helper-xfrm_dst_child.patch | 197 +++++++++++++ ...e-and-use-new-helpers-for-dst-child-acces.patch | 142 ++++++++++ ...rm-Move-child-route-linkage-into-xfrm_dst.patch | 216 ++++++++++++++ ...6-ipv6-Move-dst-from-into-struct-rt6_info.patch | 211 ++++++++++++++ ...7-xfrm-Move-dst-path-into-struct-xfrm_dst.patch | 310 +++++++++++++++++++++ ...ge-dst_entry-layout-to-avoid-useless-padd.patch | 96 +++++++ ...top-using-dst-next-in-bundle-construction.patch | 197 +++++++++++++ .../backport-4.14/410-net-Remove-dst-next.patch | 44 +++ ...jecting-with-source-address-failed-policy.patch | 4 +- 12 files changed, 1907 insertions(+), 3 deletions(-) create mode 100644 target/linux/generic/backport-4.14/400-net-dst-rt_next-is-unused.patch create mode 100644 target/linux/generic/backport-4.14/401-decnet-Move-dn_next-into-decnet-route-structure.patch create mode 100644 target/linux/generic/backport-4.14/402-ipv6-Move-rt6_next-from-dst_entry-into-ipv6-route-st.patch create mode 100644 target/linux/generic/backport-4.14/403-net-Create-and-use-new-helper-xfrm_dst_child.patch create mode 100644 target/linux/generic/backport-4.14/404-ipsec-Create-and-use-new-helpers-for-dst-child-acces.patch create mode 100644 target/linux/generic/backport-4.14/405-xfrm-Move-child-route-linkage-into-xfrm_dst.patch create mode 100644 target/linux/generic/backport-4.14/406-ipv6-Move-dst-from-into-struct-rt6_info.patch create mode 100644 target/linux/generic/backport-4.14/407-xfrm-Move-dst-path-into-struct-xfrm_dst.patch create mode 100644 target/linux/generic/backport-4.14/408-net-Rearrange-dst_entry-layout-to-avoid-useless-padd.patch create mode 100644 target/linux/generic/backport-4.14/409-xfrm-Stop-using-dst-next-in-bundle-construction.patch create mode 100644 target/linux/generic/backport-4.14/410-net-Remove-dst-next.patch diff --git a/target/linux/generic/backport-4.14/400-net-dst-rt_next-is-unused.patch b/target/linux/generic/backport-4.14/400-net-dst-rt_next-is-unused.patch new file mode 100644 index 0000000000..7355d0af91 --- /dev/null +++ b/target/linux/generic/backport-4.14/400-net-dst-rt_next-is-unused.patch @@ -0,0 +1,28 @@ +From bf1b3d8dada83c08d7bb101665a30404bcc855c9 Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:39:59 -0500 +Subject: [PATCH 01/11] net: dst->rt_next is unused. + +Delete it. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 694c2e6ae618..fe67595b0846 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -101,7 +101,6 @@ struct dst_entry { + struct lwtunnel_state *lwtstate; + union { + struct dst_entry *next; +- struct rtable __rcu *rt_next; + struct rt6_info *rt6_next; + struct dn_route __rcu *dn_next; + }; +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/401-decnet-Move-dn_next-into-decnet-route-structure.patch b/target/linux/generic/backport-4.14/401-decnet-Move-dn_next-into-decnet-route-structure.patch new file mode 100644 index 0000000000..58c30b43a1 --- /dev/null +++ b/target/linux/generic/backport-4.14/401-decnet-Move-dn_next-into-decnet-route-structure.patch @@ -0,0 +1,161 @@ +From afd979df91ffb73588a9aa73a1fe0afa4537067f Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:40:08 -0500 +Subject: [PATCH 02/11] decnet: Move dn_next into decnet route structure. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dn_route.h | 1 + + include/net/dst.h | 1 - + net/decnet/dn_route.c | 34 ++++++++++++++++++---------------- + 3 files changed, 19 insertions(+), 17 deletions(-) + +diff --git a/include/net/dn_route.h b/include/net/dn_route.h +index 55df9939bca2..342d2503cba5 100644 +--- a/include/net/dn_route.h ++++ b/include/net/dn_route.h +@@ -69,6 +69,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, + */ + struct dn_route { + struct dst_entry dst; ++ struct dn_route __rcu *dn_next; + + struct neighbour *n; + +diff --git a/include/net/dst.h b/include/net/dst.h +index fe67595b0846..9fda03dcc527 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -102,7 +102,6 @@ struct dst_entry { + union { + struct dst_entry *next; + struct rt6_info *rt6_next; +- struct dn_route __rcu *dn_next; + }; + }; + +diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c +index 0bd3afd01dd2..79744425d333 100644 +--- a/net/decnet/dn_route.c ++++ b/net/decnet/dn_route.c +@@ -199,11 +199,11 @@ static void dn_dst_check_expire(unsigned long dummy) + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { + if (atomic_read(&rt->dst.__refcnt) > 1 || + (now - rt->dst.lastuse) < expire) { +- rtp = &rt->dst.dn_next; ++ rtp = &rt->dn_next; + continue; + } +- *rtp = rt->dst.dn_next; +- rt->dst.dn_next = NULL; ++ *rtp = rt->dn_next; ++ rt->dn_next = NULL; + dst_dev_put(&rt->dst); + dst_release(&rt->dst); + } +@@ -233,11 +233,11 @@ static int dn_dst_gc(struct dst_ops *ops) + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { + if (atomic_read(&rt->dst.__refcnt) > 1 || + (now - rt->dst.lastuse) < expire) { +- rtp = &rt->dst.dn_next; ++ rtp = &rt->dn_next; + continue; + } +- *rtp = rt->dst.dn_next; +- rt->dst.dn_next = NULL; ++ *rtp = rt->dn_next; ++ rt->dn_next = NULL; + dst_dev_put(&rt->dst); + dst_release(&rt->dst); + break; +@@ -333,8 +333,8 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou + lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) { + if (compare_keys(&rth->fld, &rt->fld)) { + /* Put it first */ +- *rthp = rth->dst.dn_next; +- rcu_assign_pointer(rth->dst.dn_next, ++ *rthp = rth->dn_next; ++ rcu_assign_pointer(rth->dn_next, + dn_rt_hash_table[hash].chain); + rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth); + +@@ -345,10 +345,10 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou + *rp = rth; + return 0; + } +- rthp = &rth->dst.dn_next; ++ rthp = &rth->dn_next; + } + +- rcu_assign_pointer(rt->dst.dn_next, dn_rt_hash_table[hash].chain); ++ rcu_assign_pointer(rt->dn_next, dn_rt_hash_table[hash].chain); + rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt); + + dst_use(&rt->dst, now); +@@ -369,8 +369,8 @@ static void dn_run_flush(unsigned long dummy) + goto nothing_to_declare; + + for(; rt; rt = next) { +- next = rcu_dereference_raw(rt->dst.dn_next); +- RCU_INIT_POINTER(rt->dst.dn_next, NULL); ++ next = rcu_dereference_raw(rt->dn_next); ++ RCU_INIT_POINTER(rt->dn_next, NULL); + dst_dev_put(&rt->dst); + dst_release(&rt->dst); + } +@@ -1183,6 +1183,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o + if (rt == NULL) + goto e_nobufs; + ++ rt->dn_next = NULL; + memset(&rt->fld, 0, sizeof(rt->fld)); + rt->fld.saddr = oldflp->saddr; + rt->fld.daddr = oldflp->daddr; +@@ -1252,7 +1253,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowidn * + if (!(flags & MSG_TRYHARD)) { + rcu_read_lock_bh(); + for (rt = rcu_dereference_bh(dn_rt_hash_table[hash].chain); rt; +- rt = rcu_dereference_bh(rt->dst.dn_next)) { ++ rt = rcu_dereference_bh(rt->dn_next)) { + if ((flp->daddr == rt->fld.daddr) && + (flp->saddr == rt->fld.saddr) && + (flp->flowidn_mark == rt->fld.flowidn_mark) && +@@ -1448,6 +1449,7 @@ static int dn_route_input_slow(struct sk_buff *skb) + if (rt == NULL) + goto e_nobufs; + ++ rt->dn_next = NULL; + memset(&rt->fld, 0, sizeof(rt->fld)); + rt->rt_saddr = fld.saddr; + rt->rt_daddr = fld.daddr; +@@ -1529,7 +1531,7 @@ static int dn_route_input(struct sk_buff *skb) + + rcu_read_lock(); + for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL; +- rt = rcu_dereference(rt->dst.dn_next)) { ++ rt = rcu_dereference(rt->dn_next)) { + if ((rt->fld.saddr == cb->src) && + (rt->fld.daddr == cb->dst) && + (rt->fld.flowidn_oif == 0) && +@@ -1749,7 +1751,7 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb) + rcu_read_lock_bh(); + for(rt = rcu_dereference_bh(dn_rt_hash_table[h].chain), idx = 0; + rt; +- rt = rcu_dereference_bh(rt->dst.dn_next), idx++) { ++ rt = rcu_dereference_bh(rt->dn_next), idx++) { + if (idx < s_idx) + continue; + skb_dst_set(skb, dst_clone(&rt->dst)); +@@ -1795,7 +1797,7 @@ static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_rou + { + struct dn_rt_cache_iter_state *s = seq->private; + +- rt = rcu_dereference_bh(rt->dst.dn_next); ++ rt = rcu_dereference_bh(rt->dn_next); + while (!rt) { + rcu_read_unlock_bh(); + if (--s->bucket < 0) +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/402-ipv6-Move-rt6_next-from-dst_entry-into-ipv6-route-st.patch b/target/linux/generic/backport-4.14/402-ipv6-Move-rt6_next-from-dst_entry-into-ipv6-route-st.patch new file mode 100644 index 0000000000..76d5a32222 --- /dev/null +++ b/target/linux/generic/backport-4.14/402-ipv6-Move-rt6_next-from-dst_entry-into-ipv6-route-st.patch @@ -0,0 +1,304 @@ +From 826c34f94d78a3f1d6230672ecaeacb2db8b0640 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Mon, 19 Mar 2018 15:45:41 -0700 +Subject: [PATCH 03/11] ipv6: Move rt6_next from dst_entry into ipv6 route + structure. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 1 - + include/net/ip6_fib.h | 1 + + net/ipv6/addrconf.c | 2 +- + net/ipv6/ip6_fib.c | 34 +++++++++++++++++----------------- + net/ipv6/route.c | 20 ++++++++++---------- + 5 files changed, 29 insertions(+), 29 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 9fda03dcc527..90ea98549d83 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -101,7 +101,6 @@ struct dst_entry { + struct lwtunnel_state *lwtstate; + union { + struct dst_entry *next; +- struct rt6_info *rt6_next; + }; + }; + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index d060d711a624..f35a71ea4c82 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -100,6 +100,7 @@ struct fib6_table; + + struct rt6_info { + struct dst_entry dst; ++ struct rt6_info *rt6_next; + + /* + * Tail elements of dst_entry (__refcnt etc.) +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 6a76e41e6d51..f03367cd9700 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2328,7 +2328,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, + goto out; + + noflags |= RTF_CACHE; +- for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = fn->leaf; rt; rt = rt->rt6_next) { + if (rt->dst.dev->ifindex != dev->ifindex) + continue; + if ((rt->rt6i_flags & flags) != flags) +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index e5308d7cbd75..5d71585a5755 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -372,7 +372,7 @@ static int fib6_node_dump(struct fib6_walker *w) + { + struct rt6_info *rt; + +- for (rt = w->leaf; rt; rt = rt->dst.rt6_next) ++ for (rt = w->leaf; rt; rt = rt->rt6_next) + fib6_rt_dump(rt, w->args); + w->leaf = NULL; + return 0; +@@ -421,7 +421,7 @@ static int fib6_dump_node(struct fib6_walker *w) + int res; + struct rt6_info *rt; + +- for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = w->leaf; rt; rt = rt->rt6_next) { + res = rt6_dump_route(rt, w->args); + if (res < 0) { + /* Frame is full, suspend walking */ +@@ -874,7 +874,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + + ins = &fn->leaf; + +- for (iter = fn->leaf; iter; iter = iter->dst.rt6_next) { ++ for (iter = fn->leaf; iter; iter = iter->rt6_next) { + /* + * Search for duplicates + */ +@@ -930,7 +930,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + break; + + next_iter: +- ins = &iter->dst.rt6_next; ++ ins = &iter->rt6_next; + } + + if (fallback_ins && !found) { +@@ -958,7 +958,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + &sibling->rt6i_siblings); + break; + } +- sibling = sibling->dst.rt6_next; ++ sibling = sibling->rt6_next; + } + /* For each sibling in the list, increment the counter of + * siblings. BUG() if counters does not match, list of siblings +@@ -987,7 +987,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + if (err) + return err; + +- rt->dst.rt6_next = iter; ++ rt->rt6_next = iter; + *ins = rt; + rcu_assign_pointer(rt->rt6i_node, fn); + atomic_inc(&rt->rt6i_ref); +@@ -1018,7 +1018,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + + *ins = rt; + rcu_assign_pointer(rt->rt6i_node, fn); +- rt->dst.rt6_next = iter->dst.rt6_next; ++ rt->rt6_next = iter->rt6_next; + atomic_inc(&rt->rt6i_ref); + call_fib6_entry_notifiers(info->nl_net, FIB_EVENT_ENTRY_REPLACE, + rt); +@@ -1037,13 +1037,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + + if (nsiblings) { + /* Replacing an ECMP route, remove all siblings */ +- ins = &rt->dst.rt6_next; ++ ins = &rt->rt6_next; + iter = *ins; + while (iter) { + if (iter->rt6i_metric > rt->rt6i_metric) + break; + if (rt6_qualify_for_ecmp(iter)) { +- *ins = iter->dst.rt6_next; ++ *ins = iter->rt6_next; + iter->rt6i_node = NULL; + fib6_purge_rt(iter, fn, info->nl_net); + if (fn->rr_ptr == iter) +@@ -1051,7 +1051,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + rt6_release(iter); + nsiblings--; + } else { +- ins = &iter->dst.rt6_next; ++ ins = &iter->rt6_next; + } + iter = *ins; + } +@@ -1536,7 +1536,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, + RT6_TRACE("fib6_del_route\n"); + + /* Unlink it */ +- *rtp = rt->dst.rt6_next; ++ *rtp = rt->rt6_next; + rt->rt6i_node = NULL; + net->ipv6.rt6_stats->fib_rt_entries--; + net->ipv6.rt6_stats->fib_discarded_routes++; +@@ -1561,14 +1561,14 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, + FOR_WALKERS(net, w) { + if (w->state == FWS_C && w->leaf == rt) { + RT6_TRACE("walker %p adjusted by delroute\n", w); +- w->leaf = rt->dst.rt6_next; ++ w->leaf = rt->rt6_next; + if (!w->leaf) + w->state = FWS_U; + } + } + read_unlock(&net->ipv6.fib6_walker_lock); + +- rt->dst.rt6_next = NULL; ++ rt->rt6_next = NULL; + + /* If it was last route, expunge its radix tree node */ + if (!fn->leaf) { +@@ -1620,7 +1620,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) + * Walk the leaf entries looking for ourself + */ + +- for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) { ++ for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->rt6_next) { + if (*rtp == rt) { + fib6_del_route(fn, rtp, info); + return 0; +@@ -1770,7 +1770,7 @@ static int fib6_clean_node(struct fib6_walker *w) + return 0; + } + +- for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = w->leaf; rt; rt = rt->rt6_next) { + res = c->func(rt, c->arg); + if (res < 0) { + w->leaf = rt; +@@ -2134,7 +2134,7 @@ static int ipv6_route_yield(struct fib6_walker *w) + return 1; + + do { +- iter->w.leaf = iter->w.leaf->dst.rt6_next; ++ iter->w.leaf = iter->w.leaf->rt6_next; + iter->skip--; + if (!iter->skip && iter->w.leaf) + return 1; +@@ -2199,7 +2199,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) + if (!v) + goto iter_table; + +- n = ((struct rt6_info *)v)->dst.rt6_next; ++ n = ((struct rt6_info *)v)->rt6_next; + if (n) { + ++*pos; + return n; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index a4a865c8a23c..c1b6148ebba1 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -493,7 +493,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, + if (!oif && ipv6_addr_any(saddr)) + goto out; + +- for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { ++ for (sprt = rt; sprt; sprt = sprt->rt6_next) { + struct net_device *dev = sprt->dst.dev; + + if (oif) { +@@ -711,7 +711,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, + + match = NULL; + cont = NULL; +- for (rt = rr_head; rt; rt = rt->dst.rt6_next) { ++ for (rt = rr_head; rt; rt = rt->rt6_next) { + if (rt->rt6i_metric != metric) { + cont = rt; + break; +@@ -720,7 +720,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, + match = find_match(rt, oif, strict, &mpri, match, do_rr); + } + +- for (rt = fn->leaf; rt && rt != rr_head; rt = rt->dst.rt6_next) { ++ for (rt = fn->leaf; rt && rt != rr_head; rt = rt->rt6_next) { + if (rt->rt6i_metric != metric) { + cont = rt; + break; +@@ -732,7 +732,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, + if (match || !cont) + return match; + +- for (rt = cont; rt; rt = rt->dst.rt6_next) ++ for (rt = cont; rt; rt = rt->rt6_next) + match = find_match(rt, oif, strict, &mpri, match, do_rr); + + return match; +@@ -752,7 +752,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) + &do_rr); + + if (do_rr) { +- struct rt6_info *next = rt0->dst.rt6_next; ++ struct rt6_info *next = rt0->rt6_next; + + /* no entries matched; do round-robin */ + if (!next || next->rt6i_metric != rt0->rt6i_metric) +@@ -1587,7 +1587,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, + read_lock_bh(&table->tb6_lock); + fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); + restart: +- for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = fn->leaf; rt; rt = rt->rt6_next) { + if (rt6_check_expired(rt)) + continue; + if (rt->dst.error) +@@ -2307,7 +2307,7 @@ static int ip6_route_del(struct fib6_config *cfg, + &cfg->fc_src, cfg->fc_src_len); + + if (fn) { +- for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = fn->leaf; rt; rt = rt->rt6_next) { + if ((rt->rt6i_flags & RTF_CACHE) && + !(cfg->fc_flags & RTF_CACHE)) + continue; +@@ -2517,7 +2517,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, + if (!fn) + goto out; + +- for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = fn->leaf; rt; rt = rt->rt6_next) { + if (rt->dst.dev->ifindex != ifindex) + continue; + if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) +@@ -2575,7 +2575,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev + return NULL; + + read_lock_bh(&table->tb6_lock); +- for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = table->tb6_root.leaf; rt; rt = rt->rt6_next) { + if (dev == rt->dst.dev && + ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && + ipv6_addr_equal(&rt->rt6i_gateway, addr)) +@@ -2622,7 +2622,7 @@ static void __rt6_purge_dflt_routers(struct fib6_table *table) + + restart: + read_lock_bh(&table->tb6_lock); +- for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { ++ for (rt = table->tb6_root.leaf; rt; rt = rt->rt6_next) { + if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && + (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) { + dst_hold(&rt->dst); +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/403-net-Create-and-use-new-helper-xfrm_dst_child.patch b/target/linux/generic/backport-4.14/403-net-Create-and-use-new-helper-xfrm_dst_child.patch new file mode 100644 index 0000000000..ab94384eb9 --- /dev/null +++ b/target/linux/generic/backport-4.14/403-net-Create-and-use-new-helper-xfrm_dst_child.patch @@ -0,0 +1,197 @@ +From 7f635fe85dd9d3bbd8e0de42eeec820ad1894c60 Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:40:22 -0500 +Subject: [PATCH 04/11] net: Create and use new helper xfrm_dst_child(). + +Only IPSEC routes have a non-NULL dst->child pointer. And IPSEC +routes are identified by a non-NULL dst->xfrm pointer. + +Signed-off-by: David S. Miller +--- + include/net/xfrm.h | 9 +++++++++ + net/core/dst.c | 8 +++++--- + net/ipv4/xfrm4_mode_tunnel.c | 2 +- + net/ipv6/xfrm6_mode_tunnel.c | 2 +- + net/ipv6/xfrm6_policy.c | 2 +- + net/xfrm/xfrm_output.c | 2 +- + net/xfrm/xfrm_policy.c | 14 +++++++------- + security/selinux/xfrm.c | 2 +- + 8 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index db99efb2d1d0..ba329f691831 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -994,6 +994,15 @@ struct xfrm_dst { + u32 path_cookie; + }; + ++static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst) ++{ ++#ifdef CONFIG_XFRM ++ if (dst->xfrm) ++ return dst->child; ++#endif ++ return NULL; ++} ++ + #ifdef CONFIG_XFRM + static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) + { +diff --git a/net/core/dst.c b/net/core/dst.c +index a6c47da7d0f8..d1d1cdaefbf8 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -116,12 +116,14 @@ EXPORT_SYMBOL(dst_alloc); + + struct dst_entry *dst_destroy(struct dst_entry * dst) + { +- struct dst_entry *child; ++ struct dst_entry *child = NULL; + + smp_rmb(); + +- child = dst->child; +- ++#ifdef CONFIG_XFRM ++ if (dst->xfrm) ++ child = dst->child; ++#endif + if (!(dst->flags & DST_NOCOUNT)) + dst_entries_add(dst->ops, -1); + +diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c +index e6265e2c274e..7d885a44dc9d 100644 +--- a/net/ipv4/xfrm4_mode_tunnel.c ++++ b/net/ipv4/xfrm4_mode_tunnel.c +@@ -62,7 +62,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) + top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? + 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); + +- top_iph->ttl = ip4_dst_hoplimit(dst->child); ++ top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst)); + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; +diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c +index 02556e356f87..e66b94f46532 100644 +--- a/net/ipv6/xfrm6_mode_tunnel.c ++++ b/net/ipv6/xfrm6_mode_tunnel.c +@@ -59,7 +59,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) + if (x->props.flags & XFRM_STATE_NOECN) + dsfield &= ~INET_ECN_MASK; + ipv6_change_dsfield(top_iph, 0, dsfield); +- top_iph->hop_limit = ip6_dst_hoplimit(dst->child); ++ top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst)); + top_iph->saddr = *(struct in6_addr *)&x->props.saddr; + top_iph->daddr = *(struct in6_addr *)&x->id.daddr; + return 0; +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 17e95a0386b3..e38d0b27fa2c 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -264,7 +264,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, + in6_dev_put(xdst->u.rt6.rt6i_idev); + xdst->u.rt6.rt6i_idev = loopback_idev; + in6_dev_hold(loopback_idev); +- xdst = (struct xfrm_dst *)xdst->u.dst.child; ++ xdst = (struct xfrm_dst *)xfrm_dst_child(&xdst->u.dst); + } while (xdst->u.dst.xfrm); + + __in6_dev_put(loopback_idev); +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 73ad8c8ef344..23468672a767 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -44,7 +44,7 @@ static int xfrm_skb_check_space(struct sk_buff *skb) + + static struct dst_entry *skb_dst_pop(struct sk_buff *skb) + { +- struct dst_entry *child = dst_clone(skb_dst(skb)->child); ++ struct dst_entry *child = dst_clone(xfrm_dst_child(skb_dst(skb))); + + skb_dst_drop(skb); + return child; +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 7d17c207fc8a..10ee664e6a89 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1642,7 +1642,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len); + xfrm_init_pmtu(dst_prev); + +- for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) { ++ for (dst_prev = dst0; dst_prev != dst; dst_prev = xfrm_dst_child(dst_prev)) { + struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; + + err = xfrm_fill_dst(xdst, dev, fl); +@@ -1808,7 +1808,7 @@ static bool xfrm_xdst_can_reuse(struct xfrm_dst *xdst, + for (i = 0; i < num; i++) { + if (!dst || dst->xfrm != xfrm[i]) + return false; +- dst = dst->child; ++ dst = xfrm_dst_child(dst); + } + + return xfrm_bundle_ok(xdst); +@@ -2590,7 +2590,7 @@ static int stale_bundle(struct dst_entry *dst) + + void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) + { +- while ((dst = dst->child) && dst->xfrm && dst->dev == dev) { ++ while ((dst = xfrm_dst_child(dst)) && dst->xfrm && dst->dev == dev) { + dst->dev = dev_net(dev)->loopback_dev; + dev_hold(dst->dev); + dev_put(dev); +@@ -2620,7 +2620,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst) + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + u32 pmtu, route_mtu_cached; + +- pmtu = dst_mtu(dst->child); ++ pmtu = dst_mtu(xfrm_dst_child(dst)); + xdst->child_mtu_cached = pmtu; + + pmtu = xfrm_state_mtu(dst->xfrm, pmtu); +@@ -2665,7 +2665,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) + return 0; + +- mtu = dst_mtu(dst->child); ++ mtu = dst_mtu(xfrm_dst_child(dst)); + if (xdst->child_mtu_cached != mtu) { + last = xdst; + xdst->child_mtu_cached = mtu; +@@ -2679,7 +2679,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + xdst->route_mtu_cached = mtu; + } + +- dst = dst->child; ++ dst = xfrm_dst_child(dst); + } while (dst->xfrm); + + if (likely(!last)) +@@ -2721,7 +2721,7 @@ static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst, + { + const struct dst_entry *path = dst->path; + +- for (; dst != path; dst = dst->child) { ++ for (; dst != path; dst = xfrm_dst_child(dst)) { + const struct xfrm_state *xfrm = dst->xfrm; + + if (xfrm->props.mode == XFRM_MODE_TRANSPORT) +diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c +index 56e354fcdfc6..928188902901 100644 +--- a/security/selinux/xfrm.c ++++ b/security/selinux/xfrm.c +@@ -452,7 +452,7 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, + if (dst) { + struct dst_entry *iter; + +- for (iter = dst; iter != NULL; iter = iter->child) { ++ for (iter = dst; iter != NULL; iter = xfrm_dst_child(iter)) { + struct xfrm_state *x = iter->xfrm; + + if (x && selinux_authorizable_xfrm(x)) +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/404-ipsec-Create-and-use-new-helpers-for-dst-child-acces.patch b/target/linux/generic/backport-4.14/404-ipsec-Create-and-use-new-helpers-for-dst-child-acces.patch new file mode 100644 index 0000000000..7a56288c5a --- /dev/null +++ b/target/linux/generic/backport-4.14/404-ipsec-Create-and-use-new-helpers-for-dst-child-acces.patch @@ -0,0 +1,142 @@ +From 855c6661c65e5680c21303a8984b918ac8bd96b5 Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:40:28 -0500 +Subject: [PATCH 05/11] ipsec: Create and use new helpers for dst child access. + +This will make a future change moving the dst->child pointer less +invasive. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/xfrm.h | 5 +++++ + net/xfrm/xfrm_policy.c | 47 +++++++++++++++++++++++------------------------ + 2 files changed, 28 insertions(+), 24 deletions(-) + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index ba329f691831..56c8f461e904 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -1004,6 +1004,11 @@ static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst) + } + + #ifdef CONFIG_XFRM ++static inline void xfrm_dst_set_child(struct xfrm_dst *xdst, struct dst_entry *child) ++{ ++ xdst->u.dst.child = child; ++} ++ + static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) + { + xfrm_pols_put(xdst->pols, xdst->num_pols); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 10ee664e6a89..98d45fb616fb 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1552,8 +1552,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + unsigned long now = jiffies; + struct net_device *dev; + struct xfrm_mode *inner_mode; +- struct dst_entry *dst_prev = NULL; +- struct dst_entry *dst0 = NULL; ++ struct xfrm_dst *xdst_prev = NULL; ++ struct xfrm_dst *xdst0 = NULL; + int i = 0; + int err; + int header_len = 0; +@@ -1579,13 +1579,13 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + goto put_states; + } + +- if (!dst_prev) +- dst0 = dst1; ++ if (!xdst_prev) ++ xdst0 = xdst; + else + /* Ref count is taken during xfrm_alloc_dst() + * No need to do dst_clone() on dst1 + */ +- dst_prev->child = dst1; ++ xfrm_dst_set_child(xdst_prev, &xdst->u.dst); + + if (xfrm[i]->sel.family == AF_UNSPEC) { + inner_mode = xfrm_ip2inner_mode(xfrm[i], +@@ -1622,8 +1622,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + dst1->input = dst_discard; + dst1->output = inner_mode->afinfo->output; + +- dst1->next = dst_prev; +- dst_prev = dst1; ++ dst1->next = &xdst_prev->u.dst; ++ xdst_prev = xdst; + + header_len += xfrm[i]->props.header_len; + if (xfrm[i]->type->flags & XFRM_TYPE_NON_FRAGMENT) +@@ -1631,40 +1631,39 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + trailer_len += xfrm[i]->props.trailer_len; + } + +- dst_prev->child = dst; +- dst0->path = dst; ++ xfrm_dst_set_child(xdst_prev, dst); ++ xdst0->u.dst.path = dst; + + err = -ENODEV; + dev = dst->dev; + if (!dev) + goto free_dst; + +- xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len); +- xfrm_init_pmtu(dst_prev); ++ xfrm_init_path(xdst0, dst, nfheader_len); ++ xfrm_init_pmtu(&xdst_prev->u.dst); + +- for (dst_prev = dst0; dst_prev != dst; dst_prev = xfrm_dst_child(dst_prev)) { +- struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; +- +- err = xfrm_fill_dst(xdst, dev, fl); ++ for (xdst_prev = xdst0; xdst_prev != (struct xfrm_dst *)dst; ++ xdst_prev = (struct xfrm_dst *) xfrm_dst_child(&xdst_prev->u.dst)) { ++ err = xfrm_fill_dst(xdst_prev, dev, fl); + if (err) + goto free_dst; + +- dst_prev->header_len = header_len; +- dst_prev->trailer_len = trailer_len; +- header_len -= xdst->u.dst.xfrm->props.header_len; +- trailer_len -= xdst->u.dst.xfrm->props.trailer_len; ++ xdst_prev->u.dst.header_len = header_len; ++ xdst_prev->u.dst.trailer_len = trailer_len; ++ header_len -= xdst_prev->u.dst.xfrm->props.header_len; ++ trailer_len -= xdst_prev->u.dst.xfrm->props.trailer_len; + } + + out: +- return dst0; ++ return &xdst0->u.dst; + + put_states: + for (; i < nx; i++) + xfrm_state_put(xfrm[i]); + free_dst: +- if (dst0) +- dst_release_immediate(dst0); +- dst0 = ERR_PTR(err); ++ if (xdst0) ++ dst_release_immediate(&xdst0->u.dst); ++ xdst0 = ERR_PTR(err); + goto out; + } + +@@ -2020,7 +2019,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, + dst1->output = xdst_queue_output; + + dst_hold(dst); +- dst1->child = dst; ++ xfrm_dst_set_child(xdst, dst); + dst1->path = dst; + + xfrm_init_path((struct xfrm_dst *)dst1, dst, 0); +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/405-xfrm-Move-child-route-linkage-into-xfrm_dst.patch b/target/linux/generic/backport-4.14/405-xfrm-Move-child-route-linkage-into-xfrm_dst.patch new file mode 100644 index 0000000000..a691b67bb8 --- /dev/null +++ b/target/linux/generic/backport-4.14/405-xfrm-Move-child-route-linkage-into-xfrm_dst.patch @@ -0,0 +1,216 @@ +From 89de70e2c4dba7f1911a91817349099eee14389e Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:45:44 -0500 +Subject: [PATCH 06/11] xfrm: Move child route linkage into xfrm_dst. + +XFRM bundle child chains look like this: + + xdst1 --> xdst2 --> xdst3 --> path_dst + +All of xdstN are xfrm_dst objects and xdst->u.dst.xfrm is non-NULL. +The final child pointer in the chain, here called 'path_dst', is some +other kind of route such as an ipv4 or ipv6 one. + +The xfrm output path pops routes, one at a time, via the child +pointer, until we hit one which has a dst->xfrm pointer which +is NULL. + +We can easily preserve the above mechanisms with child sitting +only in the xfrm_dst structure. All children in the chain +before we break out of the xfrm_output() loop have dst->xfrm +non-NULL and are therefore xfrm_dst objects. + +Since we break out of the loop when we find dst->xfrm NULL, we +will not try to dereference 'dst' as if it were an xfrm_dst. + +Signed-off-by: David S. Miller +--- + include/net/dst.h | 3 +-- + include/net/xfrm.h | 15 ++++++++++----- + net/core/dst.c | 9 ++++++--- + net/core/pktgen.c | 12 ++++++------ + net/netfilter/xt_policy.c | 3 ++- + net/xfrm/xfrm_device.c | 2 +- + 6 files changed, 26 insertions(+), 18 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 90ea98549d83..fdd99f90d3c5 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -35,7 +35,6 @@ struct sk_buff; + struct dst_entry { + struct net_device *dev; + struct rcu_head rcu_head; +- struct dst_entry *child; + struct dst_ops *ops; + unsigned long _metrics; + unsigned long expires; +@@ -89,7 +88,7 @@ struct dst_entry { + * Align __refcnt to a 64 bytes alignment + * (L1_CACHE_SIZE would be too much) + */ +- long __pad_to_align_refcnt[2]; ++ long __pad_to_align_refcnt[3]; + #endif + /* + * __refcnt wants to be on a different cache line from +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index 56c8f461e904..e76770544d11 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -968,7 +968,7 @@ static inline bool xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_c + + /* A struct encoding bundle of transformations to apply to some set of flow. + * +- * dst->child points to the next element of bundle. ++ * xdst->child points to the next element of bundle. + * dst->xfrm points to an instanse of transformer. + * + * Due to unfortunate limitations of current routing cache, which we +@@ -984,6 +984,7 @@ struct xfrm_dst { + struct rt6_info rt6; + } u; + struct dst_entry *route; ++ struct dst_entry *child; + struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; + int num_pols, num_xfrms; + u32 xfrm_genid; +@@ -997,8 +998,10 @@ struct xfrm_dst { + static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst) + { + #ifdef CONFIG_XFRM +- if (dst->xfrm) +- return dst->child; ++ if (dst->xfrm) { ++ struct xfrm_dst *xdst = (struct xfrm_dst *) dst; ++ return xdst->child; ++ } + #endif + return NULL; + } +@@ -1006,7 +1009,7 @@ static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst) + #ifdef CONFIG_XFRM + static inline void xfrm_dst_set_child(struct xfrm_dst *xdst, struct dst_entry *child) + { +- xdst->u.dst.child = child; ++ xdst->child = child; + } + + static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) +@@ -1883,12 +1886,14 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x); + static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) + { + struct xfrm_state *x = dst->xfrm; ++ struct xfrm_dst *xdst; + + if (!x || !x->type_offload) + return false; + ++ xdst = (struct xfrm_dst *) dst; + if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) && +- !dst->child->xfrm) ++ !xdst->child->xfrm) + return true; + + return false; +diff --git a/net/core/dst.c b/net/core/dst.c +index d1d1cdaefbf8..1de656b77ed2 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -62,7 +63,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, + struct net_device *dev, int initial_ref, int initial_obsolete, + unsigned short flags) + { +- dst->child = NULL; + dst->dev = dev; + if (dev) + dev_hold(dev); +@@ -121,8 +121,11 @@ struct dst_entry *dst_destroy(struct dst_entry * dst) + smp_rmb(); + + #ifdef CONFIG_XFRM +- if (dst->xfrm) +- child = dst->child; ++ if (dst->xfrm) { ++ struct xfrm_dst *xdst = (struct xfrm_dst *) dst; ++ ++ child = xdst->child; ++ } + #endif + if (!(dst->flags & DST_NOCOUNT)) + dst_entries_add(dst->ops, -1); +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 6e1e10ff433a..099b0a2f6bb2 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -399,7 +399,7 @@ struct pktgen_dev { + __u8 ipsmode; /* IPSEC mode (config) */ + __u8 ipsproto; /* IPSEC type (config) */ + __u32 spi; +- struct dst_entry dst; ++ struct xfrm_dst xdst; + struct dst_ops dstops; + #endif + char result[512]; +@@ -2609,7 +2609,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) + * supports both transport/tunnel mode + ESP/AH type. + */ + if ((x->props.mode == XFRM_MODE_TUNNEL) && (pkt_dev->spi != 0)) +- skb->_skb_refdst = (unsigned long)&pkt_dev->dst | SKB_DST_NOREF; ++ skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF; + + rcu_read_lock_bh(); + err = x->outer_mode->output(x, skb); +@@ -3734,10 +3734,10 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) + * performance under such circumstance. + */ + pkt_dev->dstops.family = AF_INET; +- pkt_dev->dst.dev = pkt_dev->odev; +- dst_init_metrics(&pkt_dev->dst, pktgen_dst_metrics, false); +- pkt_dev->dst.child = &pkt_dev->dst; +- pkt_dev->dst.ops = &pkt_dev->dstops; ++ pkt_dev->xdst.u.dst.dev = pkt_dev->odev; ++ dst_init_metrics(&pkt_dev->xdst.u.dst, pktgen_dst_metrics, false); ++ pkt_dev->xdst.child = &pkt_dev->xdst.u.dst; ++ pkt_dev->xdst.u.dst.ops = &pkt_dev->dstops; + #endif + + return add_dev_to_thread(t, pkt_dev); +diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c +index 2b4ab189bba7..5639fb03bdd9 100644 +--- a/net/netfilter/xt_policy.c ++++ b/net/netfilter/xt_policy.c +@@ -93,7 +93,8 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, + if (dst->xfrm == NULL) + return -1; + +- for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { ++ for (i = 0; dst && dst->xfrm; ++ dst = ((struct xfrm_dst *)dst)->child, i++) { + pos = strict ? i : 0; + if (pos >= info->len) + return 0; +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 30e5746085b8..c5851ddddd2a 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -121,7 +121,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x) + return false; + + if ((x->xso.offload_handle && (dev == dst->path->dev)) && +- !dst->child->xfrm && x->type->get_mtu) { ++ !xdst->child->xfrm && x->type->get_mtu) { + mtu = x->type->get_mtu(x, xdst->child_mtu_cached); + + if (skb->len <= mtu) +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/406-ipv6-Move-dst-from-into-struct-rt6_info.patch b/target/linux/generic/backport-4.14/406-ipv6-Move-dst-from-into-struct-rt6_info.patch new file mode 100644 index 0000000000..4add309411 --- /dev/null +++ b/target/linux/generic/backport-4.14/406-ipv6-Move-dst-from-into-struct-rt6_info.patch @@ -0,0 +1,211 @@ +From cd598e3bd215a60a5cbf98b6af967157dfa52a49 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Mon, 19 Mar 2018 16:08:56 -0700 +Subject: [PATCH 07/11] ipv6: Move dst->from into struct rt6_info. + +Any time we clone or copy a core ipv6 route in the ipv6 routing +tables, we have the copy/clone's ->from point to the base route. + +This is used to handle route expiration properly. + +Only ipv6 uses this mechanism, and only ipv6 code references +it. So it is safe to move it into rt6_info. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 3 +-- + include/net/ip6_fib.h | 8 ++++---- + net/core/dst.c | 1 - + net/ipv6/route.c | 35 +++++++++++++++++------------------ + 4 files changed, 22 insertions(+), 25 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index fdd99f90d3c5..a43f37837c36 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -39,7 +39,6 @@ struct dst_entry { + unsigned long _metrics; + unsigned long expires; + struct dst_entry *path; +- struct dst_entry *from; + #ifdef CONFIG_XFRM + struct xfrm_state *xfrm; + #else +@@ -88,7 +87,7 @@ struct dst_entry { + * Align __refcnt to a 64 bytes alignment + * (L1_CACHE_SIZE would be too much) + */ +- long __pad_to_align_refcnt[3]; ++ long __pad_to_align_refcnt[4]; + #endif + /* + * __refcnt wants to be on a different cache line from +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index f35a71ea4c82..cdf3e1f1ca65 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -101,6 +101,7 @@ struct fib6_table; + struct rt6_info { + struct dst_entry dst; + struct rt6_info *rt6_next; ++ struct rt6_info *from; + + /* + * Tail elements of dst_entry (__refcnt etc.) +@@ -164,8 +165,7 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) + { + struct rt6_info *rt; + +- for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); +- rt = (struct rt6_info *)rt->dst.from); ++ for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); rt = rt->from); + if (rt && rt != rt0) + rt0->dst.expires = rt->dst.expires; + +@@ -201,8 +201,8 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt) + u32 cookie = 0; + + if (rt->rt6i_flags & RTF_PCPU || +- (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from)) +- rt = (struct rt6_info *)(rt->dst.from); ++ (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from)) ++ rt = rt->from; + + rt6_get_cookie_safe(rt, &cookie); + +diff --git a/net/core/dst.c b/net/core/dst.c +index 1de656b77ed2..d17d51b9ac9a 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -70,7 +70,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, + dst_init_metrics(dst, dst_default_metrics.metrics, true); + dst->expires = 0UL; + dst->path = dst; +- dst->from = NULL; + #ifdef CONFIG_XFRM + dst->xfrm = NULL; + #endif +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index c1b6148ebba1..4e8b24d5f9c6 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -180,7 +180,7 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev) + + static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt) + { +- return dst_metrics_write_ptr(rt->dst.from); ++ return dst_metrics_write_ptr(&rt->from->dst); + } + + static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) +@@ -392,7 +392,7 @@ EXPORT_SYMBOL(ip6_dst_alloc); + static void ip6_dst_destroy(struct dst_entry *dst) + { + struct rt6_info *rt = (struct rt6_info *)dst; +- struct dst_entry *from = dst->from; ++ struct rt6_info *from = rt->from; + struct inet6_dev *idev; + + dst_destroy_metrics_generic(dst); +@@ -405,8 +405,8 @@ static void ip6_dst_destroy(struct dst_entry *dst) + in6_dev_put(idev); + } + +- dst->from = NULL; +- dst_release(from); ++ rt->from = NULL; ++ dst_release(&from->dst); + } + + static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, +@@ -439,9 +439,9 @@ static bool rt6_check_expired(const struct rt6_info *rt) + if (rt->rt6i_flags & RTF_EXPIRES) { + if (time_after(jiffies, rt->dst.expires)) + return true; +- } else if (rt->dst.from) { ++ } else if (rt->from) { + return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK || +- rt6_check_expired((struct rt6_info *)rt->dst.from); ++ rt6_check_expired(rt->from); + } + return false; + } +@@ -990,7 +990,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort, + */ + + if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) +- ort = (struct rt6_info *)ort->dst.from; ++ ort = ort->from; + + rcu_read_lock(); + dev = ip6_rt_get_dev_rcu(ort); +@@ -1357,9 +1357,9 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori + + static void rt6_dst_from_metrics_check(struct rt6_info *rt) + { +- if (rt->dst.from && +- dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from)) +- dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true); ++ if (rt->from && ++ dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(&rt->from->dst)) ++ dst_init_metrics(&rt->dst, dst_metrics_ptr(&rt->from->dst), true);; + } + + static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie) +@@ -1379,7 +1379,7 @@ static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie) + { + if (!__rt6_check_expired(rt) && + rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && +- rt6_check((struct rt6_info *)(rt->dst.from), cookie)) ++ rt6_check(rt->from, cookie)) + return &rt->dst; + else + return NULL; +@@ -1399,7 +1399,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) + rt6_dst_from_metrics_check(rt); + + if (rt->rt6i_flags & RTF_PCPU || +- (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from)) ++ (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from)) + return rt6_dst_from_check(rt, cookie); + else + return rt6_check(rt, cookie); +@@ -2466,11 +2466,11 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu + + static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) + { +- BUG_ON(from->dst.from); ++ BUG_ON(from->from); + + rt->rt6i_flags &= ~RTF_EXPIRES; + dst_hold(&from->dst); +- rt->dst.from = &from->dst; ++ rt->from = from; + dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true); + } + +@@ -2930,7 +2930,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) + if (rt->rt6i_flags & RTF_CACHE) { + /* For RTF_CACHE with rt6i_pmtu == 0 + * (i.e. a redirected route), +- * the metrics of its rt->dst.from has already ++ * the metrics of its rt->from has already + * been updated. + */ + if (rt->rt6i_pmtu && rt->rt6i_pmtu > arg->mtu) +@@ -3724,9 +3724,8 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + goto errout; + } + +- if (fibmatch && rt->dst.from) { +- struct rt6_info *ort = container_of(rt->dst.from, +- struct rt6_info, dst); ++ if (fibmatch && rt->from) { ++ struct rt6_info *ort = container_of(&rt->from->dst, struct rt6_info, dst); + + dst_hold(&ort->dst); + ip6_rt_put(rt); +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/407-xfrm-Move-dst-path-into-struct-xfrm_dst.patch b/target/linux/generic/backport-4.14/407-xfrm-Move-dst-path-into-struct-xfrm_dst.patch new file mode 100644 index 0000000000..9c6dbbe1bc --- /dev/null +++ b/target/linux/generic/backport-4.14/407-xfrm-Move-dst-path-into-struct-xfrm_dst.patch @@ -0,0 +1,310 @@ +From aa6688e6c4509eebacbc7ad9de3b5e7775b55a21 Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:40:46 -0500 +Subject: [PATCH 08/11] xfrm: Move dst->path into struct xfrm_dst + +The first member of an IPSEC route bundle chain sets it's dst->path to +the underlying ipv4/ipv6 route that carries the bundle. + +Stated another way, if one were to follow the xfrm_dst->child chain of +the bundle, the final non-NULL pointer would be the path and point to +either an ipv4 or an ipv6 route. + +This is largely used to make sure that PMTU events propagate down to +the correct ipv4 or ipv6 route. + +When we don't have the top of an IPSEC bundle 'dst->path == dst'. + +Move it down into xfrm_dst and key off of dst->xfrm. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 3 +-- + include/net/xfrm.h | 15 ++++++++++++++- + net/bridge/br_nf_core.c | 1 - + net/core/dst.c | 1 - + net/ipv4/route.c | 2 +- + net/ipv6/ip6_output.c | 6 +++--- + net/ipv6/route.c | 6 ------ + net/xfrm/xfrm_device.c | 2 +- + net/xfrm/xfrm_policy.c | 28 ++++++++++++++-------------- + 9 files changed, 34 insertions(+), 30 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index a43f37837c36..05404fba2a5a 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -38,7 +38,6 @@ struct dst_entry { + struct dst_ops *ops; + unsigned long _metrics; + unsigned long expires; +- struct dst_entry *path; + #ifdef CONFIG_XFRM + struct xfrm_state *xfrm; + #else +@@ -87,7 +86,7 @@ struct dst_entry { + * Align __refcnt to a 64 bytes alignment + * (L1_CACHE_SIZE would be too much) + */ +- long __pad_to_align_refcnt[4]; ++ long __pad_to_align_refcnt[5]; + #endif + /* + * __refcnt wants to be on a different cache line from +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index e76770544d11..47ec8b68c208 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -985,6 +985,7 @@ struct xfrm_dst { + } u; + struct dst_entry *route; + struct dst_entry *child; ++ struct dst_entry *path; + struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; + int num_pols, num_xfrms; + u32 xfrm_genid; +@@ -995,6 +996,18 @@ struct xfrm_dst { + u32 path_cookie; + }; + ++static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst) ++{ ++#ifdef CONFIG_XFRM ++ if (dst->xfrm) { ++ const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst; ++ ++ return xdst->path; ++ } ++#endif ++ return (struct dst_entry *) dst; ++} ++ + static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst) + { + #ifdef CONFIG_XFRM +@@ -1892,7 +1905,7 @@ static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) + return false; + + xdst = (struct xfrm_dst *) dst; +- if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) && ++ if (x->xso.offload_handle && (x->xso.dev == xfrm_dst_path(dst)->dev) && + !xdst->child->xfrm) + return true; + +diff --git a/net/bridge/br_nf_core.c b/net/bridge/br_nf_core.c +index 20cbb727df4d..8e2d7cfa4e16 100644 +--- a/net/bridge/br_nf_core.c ++++ b/net/bridge/br_nf_core.c +@@ -78,7 +78,6 @@ void br_netfilter_rtable_init(struct net_bridge *br) + + atomic_set(&rt->dst.__refcnt, 1); + rt->dst.dev = br->dev; +- rt->dst.path = &rt->dst; + dst_init_metrics(&rt->dst, br_dst_default_metrics, true); + rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE; + rt->dst.ops = &fake_dst_ops; +diff --git a/net/core/dst.c b/net/core/dst.c +index d17d51b9ac9a..6ef9285319e9 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -69,7 +69,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, + dst->ops = ops; + dst_init_metrics(dst, dst_default_metrics.metrics, true); + dst->expires = 0UL; +- dst->path = dst; + #ifdef CONFIG_XFRM + dst->xfrm = NULL; + #endif +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 9ff06c5051ae..fdd12d6a536b 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1109,7 +1109,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + new = true; + } + +- __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); ++ __ip_rt_update_pmtu((struct rtable *) xfrm_dst_path(&rt->dst), &fl4, mtu); + + if (!dst_check(&rt->dst, 0)) { + if (new) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 3763dc01e374..a9ac19ff8683 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1185,10 +1185,10 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, + v6_cork->tclass = ipc6->tclass; + if (rt->dst.flags & DST_XFRM_TUNNEL) + mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? +- READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); ++ READ_ONCE(rt->dst.dev->mtu) : dst_mtu(xfrm_dst_path(&rt->dst)); + else + mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? +- READ_ONCE(rt->dst.dev->mtu) : dst_mtu(rt->dst.path); ++ READ_ONCE(rt->dst.dev->mtu) : dst_mtu(xfrm_dst_path(&rt->dst)); + if (np->frag_size < mtu) { + if (np->frag_size) + mtu = np->frag_size; +@@ -1196,7 +1196,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, + if (mtu < IPV6_MIN_MTU) + return -EINVAL; + cork->base.fragsize = mtu; +- if (dst_allfrag(rt->dst.path)) ++ if (dst_allfrag(xfrm_dst_path(&rt->dst))) + cork->base.flags |= IPCORK_ALLFRAG; + cork->base.length = 0; + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 4e8b24d5f9c6..b6487ccd2a08 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -4002,8 +4002,6 @@ static int __net_init ip6_route_net_init(struct net *net) + GFP_KERNEL); + if (!net->ipv6.ip6_null_entry) + goto out_ip6_dst_entries; +- net->ipv6.ip6_null_entry->dst.path = +- (struct dst_entry *)net->ipv6.ip6_null_entry; + net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_null_entry->dst, + ip6_template_metrics, true); +@@ -4015,8 +4013,6 @@ static int __net_init ip6_route_net_init(struct net *net) + GFP_KERNEL); + if (!net->ipv6.ip6_prohibit_entry) + goto out_ip6_null_entry; +- net->ipv6.ip6_prohibit_entry->dst.path = +- (struct dst_entry *)net->ipv6.ip6_prohibit_entry; + net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst, + ip6_template_metrics, true); +@@ -4026,8 +4022,6 @@ static int __net_init ip6_route_net_init(struct net *net) + GFP_KERNEL); + if (!net->ipv6.ip6_blk_hole_entry) + goto out_ip6_prohibit_entry; +- net->ipv6.ip6_blk_hole_entry->dst.path = +- (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; + net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, + ip6_template_metrics, true); +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index c5851ddddd2a..c61a7d46b412 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -120,7 +120,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x) + if (!x->type_offload || x->encap) + return false; + +- if ((x->xso.offload_handle && (dev == dst->path->dev)) && ++ if ((x->xso.offload_handle && (dev == xfrm_dst_path(dst)->dev)) && + !xdst->child->xfrm && x->type->get_mtu) { + mtu = x->type->get_mtu(x, xdst->child_mtu_cached); + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 98d45fb616fb..e0cd3a8e7d3e 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1632,7 +1632,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + } + + xfrm_dst_set_child(xdst_prev, dst); +- xdst0->u.dst.path = dst; ++ xdst0->path = dst; + + err = -ENODEV; + dev = dst->dev; +@@ -1887,8 +1887,8 @@ static void xfrm_policy_queue_process(unsigned long arg) + xfrm_decode_session(skb, &fl, dst->ops->family); + spin_unlock(&pq->hold_queue.lock); + +- dst_hold(dst->path); +- dst = xfrm_lookup(net, dst->path, &fl, sk, 0); ++ dst_hold(xfrm_dst_path(dst)); ++ dst = xfrm_lookup(net, xfrm_dst_path(dst), &fl, sk, 0); + if (IS_ERR(dst)) + goto purge_queue; + +@@ -1917,8 +1917,8 @@ static void xfrm_policy_queue_process(unsigned long arg) + skb = __skb_dequeue(&list); + + xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family); +- dst_hold(skb_dst(skb)->path); +- dst = xfrm_lookup(net, skb_dst(skb)->path, &fl, skb->sk, 0); ++ dst_hold(xfrm_dst_path(skb_dst(skb))); ++ dst = xfrm_lookup(net, xfrm_dst_path(skb_dst(skb)), &fl, skb->sk, 0); + if (IS_ERR(dst)) { + kfree_skb(skb); + continue; +@@ -2020,7 +2020,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, + + dst_hold(dst); + xfrm_dst_set_child(xdst, dst); +- dst1->path = dst; ++ xdst->path = dst; + + xfrm_init_path((struct xfrm_dst *)dst1, dst, 0); + +@@ -2644,7 +2644,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + struct xfrm_dst *last; + u32 mtu; + +- if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || ++ if (!dst_check(xfrm_dst_path(dst), ((struct xfrm_dst *)dst)->path_cookie) || + (dst->dev && !netif_running(dst->dev))) + return 0; + +@@ -2705,22 +2705,20 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + + static unsigned int xfrm_default_advmss(const struct dst_entry *dst) + { +- return dst_metric_advmss(dst->path); ++ return dst_metric_advmss(xfrm_dst_path(dst)); + } + + static unsigned int xfrm_mtu(const struct dst_entry *dst) + { + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + +- return mtu ? : dst_mtu(dst->path); ++ return mtu ? : dst_mtu(xfrm_dst_path(dst)); + } + + static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst, + const void *daddr) + { +- const struct dst_entry *path = dst->path; +- +- for (; dst != path; dst = xfrm_dst_child(dst)) { ++ while (dst->xfrm) { + const struct xfrm_state *xfrm = dst->xfrm; + + if (xfrm->props.mode == XFRM_MODE_TRANSPORT) +@@ -2729,6 +2727,8 @@ static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst, + daddr = xfrm->coaddr; + else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR)) + daddr = &xfrm->id.daddr; ++ ++ dst = xfrm_dst_child(dst); + } + return daddr; + } +@@ -2737,7 +2737,7 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, + struct sk_buff *skb, + const void *daddr) + { +- const struct dst_entry *path = dst->path; ++ const struct dst_entry *path = xfrm_dst_path(dst); + + if (!skb) + daddr = xfrm_get_dst_nexthop(dst, daddr); +@@ -2746,7 +2746,7 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, + + static void xfrm_confirm_neigh(const struct dst_entry *dst, const void *daddr) + { +- const struct dst_entry *path = dst->path; ++ const struct dst_entry *path = xfrm_dst_path(dst); + + daddr = xfrm_get_dst_nexthop(dst, daddr); + path->ops->confirm_neigh(path, daddr); +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/408-net-Rearrange-dst_entry-layout-to-avoid-useless-padd.patch b/target/linux/generic/backport-4.14/408-net-Rearrange-dst_entry-layout-to-avoid-useless-padd.patch new file mode 100644 index 0000000000..cdd30273e6 --- /dev/null +++ b/target/linux/generic/backport-4.14/408-net-Rearrange-dst_entry-layout-to-avoid-useless-padd.patch @@ -0,0 +1,96 @@ +From 42f6089f469fb2e1fbe093eab06260381feabdff Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:40:53 -0500 +Subject: [PATCH 09/11] net: Rearrange dst_entry layout to avoid useless + padding. + +We have padding to try and align the refcount on a separate cache +line. But after several simplifications the padding has increased +substantially. + +So now it's easy to change the layout to get rid of the padding +entirely. + +We group the write-heavy __refcnt and __use with less often used +items such as the rcu_head and the error code. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 31 ++++++++++++------------------- + 1 file changed, 12 insertions(+), 19 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 05404fba2a5a..5c54c2e97f1b 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -34,7 +34,6 @@ struct sk_buff; + + struct dst_entry { + struct net_device *dev; +- struct rcu_head rcu_head; + struct dst_ops *ops; + unsigned long _metrics; + unsigned long expires; +@@ -56,8 +55,6 @@ struct dst_entry { + #define DST_XFRM_QUEUE 0x0040 + #define DST_METADATA 0x0080 + +- short error; +- + /* A non-zero value of dst->obsolete forces by-hand validation + * of the route entry. Positive values are set by the generic + * dst layer to indicate that the entry has been forcefully +@@ -73,29 +70,25 @@ struct dst_entry { + #define DST_OBSOLETE_KILL -2 + unsigned short header_len; /* more space at head required */ + unsigned short trailer_len; /* space to reserve at tail */ +- unsigned short __pad3; +- +-#ifdef CONFIG_IP_ROUTE_CLASSID +- __u32 tclassid; +-#else +- __u32 __pad2; +-#endif + +-#ifdef CONFIG_64BIT +- /* +- * Align __refcnt to a 64 bytes alignment +- * (L1_CACHE_SIZE would be too much) +- */ +- long __pad_to_align_refcnt[5]; +-#endif + /* + * __refcnt wants to be on a different cache line from + * input/output/ops or performance tanks badly + */ +- atomic_t __refcnt; /* client references */ ++#ifdef CONFIG_64BIT ++ atomic_t __refcnt; /* 64-bit offset 64 */ ++#endif + int __use; + unsigned long lastuse; + struct lwtunnel_state *lwtstate; ++ struct rcu_head rcu_head; ++ short error; ++ short __pad; ++ __u32 tclassid; ++#ifndef CONFIG_64BIT ++ atomic_t __refcnt; /* 32-bit offset 64 */ ++#endif ++ + union { + struct dst_entry *next; + }; +@@ -244,7 +237,7 @@ static inline void dst_hold(struct dst_entry *dst) + { + /* + * If your kernel compilation stops here, please check +- * __pad_to_align_refcnt declaration in struct dst_entry ++ * the placement of __refcnt in struct dst_entry + */ + BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63); + WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0); +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/409-xfrm-Stop-using-dst-next-in-bundle-construction.patch b/target/linux/generic/backport-4.14/409-xfrm-Stop-using-dst-next-in-bundle-construction.patch new file mode 100644 index 0000000000..620895ff45 --- /dev/null +++ b/target/linux/generic/backport-4.14/409-xfrm-Stop-using-dst-next-in-bundle-construction.patch @@ -0,0 +1,197 @@ +From e22f80e4d546bd11ffe6886c6a79203964a86d6b Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:41:01 -0500 +Subject: [PATCH 10/11] xfrm: Stop using dst->next in bundle construction. + +While building ipsec bundles, blocks of xfrm dsts are linked together +using dst->next from bottom to the top. + +The only thing this is used for is initializing the pmtu values of the +xfrm stack, and for updating the mtu values at xfrm_bundle_ok() time. + +The bundle pmtu entries must be processed in this order so that pmtu +values lower in the stack of routes can propagate up to the higher +ones. + +Avoid using dst->next by simply maintaining an array of dst pointers +as we already do for the xfrm_state objects when building the bundle. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + net/xfrm/xfrm_policy.c | 56 ++++++++++++++++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index e0cd3a8e7d3e..62ddc4b643c9 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -54,7 +54,7 @@ static struct xfrm_policy_afinfo const __rcu *xfrm_policy_afinfo[AF_INET6 + 1] + static struct kmem_cache *xfrm_dst_cache __read_mostly; + static __read_mostly seqcount_t xfrm_policy_hash_generation; + +-static void xfrm_init_pmtu(struct dst_entry *dst); ++static void xfrm_init_pmtu(struct xfrm_dst **bundle, int nr); + static int stale_bundle(struct dst_entry *dst); + static int xfrm_bundle_ok(struct xfrm_dst *xdst); + static void xfrm_policy_queue_process(unsigned long arg); +@@ -1544,7 +1544,9 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + */ + + static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, +- struct xfrm_state **xfrm, int nx, ++ struct xfrm_state **xfrm, ++ struct xfrm_dst **bundle, ++ int nx, + const struct flowi *fl, + struct dst_entry *dst) + { +@@ -1579,6 +1581,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + goto put_states; + } + ++ bundle[i] = xdst; + if (!xdst_prev) + xdst0 = xdst; + else +@@ -1622,7 +1625,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + dst1->input = dst_discard; + dst1->output = inner_mode->afinfo->output; + +- dst1->next = &xdst_prev->u.dst; + xdst_prev = xdst; + + header_len += xfrm[i]->props.header_len; +@@ -1640,7 +1642,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, + goto free_dst; + + xfrm_init_path(xdst0, dst, nfheader_len); +- xfrm_init_pmtu(&xdst_prev->u.dst); ++ xfrm_init_pmtu(bundle, nx); + + for (xdst_prev = xdst0; xdst_prev != (struct xfrm_dst *)dst; + xdst_prev = (struct xfrm_dst *) xfrm_dst_child(&xdst_prev->u.dst)) { +@@ -1820,6 +1822,7 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, + { + struct net *net = xp_net(pols[0]); + struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; ++ struct xfrm_dst *bundle[XFRM_MAX_DEPTH]; + struct xfrm_dst *xdst, *old; + struct dst_entry *dst; + int err; +@@ -1847,7 +1850,7 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, + + old = xdst; + +- dst = xfrm_bundle_create(pols[0], xfrm, err, fl, dst_orig); ++ dst = xfrm_bundle_create(pols[0], xfrm, bundle, err, fl, dst_orig); + if (IS_ERR(dst)) { + XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); + return ERR_CAST(dst); +@@ -2613,12 +2616,14 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) + return dst; + } + +-static void xfrm_init_pmtu(struct dst_entry *dst) ++static void xfrm_init_pmtu(struct xfrm_dst **bundle, int nr) + { +- do { +- struct xfrm_dst *xdst = (struct xfrm_dst *)dst; ++ while (nr--) { ++ struct xfrm_dst *xdst = bundle[nr]; + u32 pmtu, route_mtu_cached; ++ struct dst_entry *dst; + ++ dst = &xdst->u.dst; + pmtu = dst_mtu(xfrm_dst_child(dst)); + xdst->child_mtu_cached = pmtu; + +@@ -2631,7 +2636,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst) + pmtu = route_mtu_cached; + + dst_metric_set(dst, RTAX_MTU, pmtu); +- } while ((dst = dst->next)); ++ } + } + + /* Check that the bundle accepts the flow and its components are +@@ -2640,8 +2645,10 @@ static void xfrm_init_pmtu(struct dst_entry *dst) + + static int xfrm_bundle_ok(struct xfrm_dst *first) + { ++ struct xfrm_dst *bundle[XFRM_MAX_DEPTH]; + struct dst_entry *dst = &first->u.dst; +- struct xfrm_dst *last; ++ struct xfrm_dst *xdst; ++ int start_from, nr; + u32 mtu; + + if (!dst_check(xfrm_dst_path(dst), ((struct xfrm_dst *)dst)->path_cookie) || +@@ -2651,8 +2658,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + if (dst->flags & DST_XFRM_QUEUE) + return 1; + +- last = NULL; +- ++ start_from = nr = 0; + do { + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + +@@ -2664,9 +2670,11 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) + return 0; + ++ bundle[nr++] = xdst; ++ + mtu = dst_mtu(xfrm_dst_child(dst)); + if (xdst->child_mtu_cached != mtu) { +- last = xdst; ++ start_from = nr; + xdst->child_mtu_cached = mtu; + } + +@@ -2674,30 +2682,30 @@ static int xfrm_bundle_ok(struct xfrm_dst *first) + return 0; + mtu = dst_mtu(xdst->route); + if (xdst->route_mtu_cached != mtu) { +- last = xdst; ++ start_from = nr; + xdst->route_mtu_cached = mtu; + } + + dst = xfrm_dst_child(dst); + } while (dst->xfrm); + +- if (likely(!last)) ++ if (likely(!start_from)) + return 1; + +- mtu = last->child_mtu_cached; +- for (;;) { +- dst = &last->u.dst; ++ xdst = bundle[start_from - 1]; ++ mtu = xdst->child_mtu_cached; ++ while (start_from--) { ++ dst = &xdst->u.dst; + + mtu = xfrm_state_mtu(dst->xfrm, mtu); +- if (mtu > last->route_mtu_cached) +- mtu = last->route_mtu_cached; ++ if (mtu > xdst->route_mtu_cached) ++ mtu = xdst->route_mtu_cached; + dst_metric_set(dst, RTAX_MTU, mtu); +- +- if (last == first) ++ if (!start_from) + break; + +- last = (struct xfrm_dst *)last->u.dst.next; +- last->child_mtu_cached = mtu; ++ xdst = bundle[start_from - 1]; ++ xdst->child_mtu_cached = mtu; + } + + return 1; +-- +2.16.2 + diff --git a/target/linux/generic/backport-4.14/410-net-Remove-dst-next.patch b/target/linux/generic/backport-4.14/410-net-Remove-dst-next.patch new file mode 100644 index 0000000000..f854fef7f6 --- /dev/null +++ b/target/linux/generic/backport-4.14/410-net-Remove-dst-next.patch @@ -0,0 +1,44 @@ +From a7c83c86e21b6a0f8083e7397861433c472c3c9b Mon Sep 17 00:00:00 2001 +From: David Miller +Date: Tue, 28 Nov 2017 15:41:07 -0500 +Subject: [PATCH 11/11] net: Remove dst->next + +There are no more users. + +Signed-off-by: David S. Miller +Reviewed-by: Eric Dumazet +--- + include/net/dst.h | 4 ---- + net/core/dst.c | 1 - + 2 files changed, 5 deletions(-) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 5c54c2e97f1b..b039f394c1af 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -88,10 +88,6 @@ struct dst_entry { + #ifndef CONFIG_64BIT + atomic_t __refcnt; /* 32-bit offset 64 */ + #endif +- +- union { +- struct dst_entry *next; +- }; + }; + + struct dst_metrics { +diff --git a/net/core/dst.c b/net/core/dst.c +index 6ef9285319e9..20ded1e491a5 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -86,7 +86,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, + dst->__use = 0; + dst->lastuse = jiffies; + dst->flags = flags; +- dst->next = NULL; + if (!(flags & DST_NOCOUNT)) + dst_entries_add(ops, 1); + } +-- +2.16.2 + diff --git a/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 39346886ef..3d42366e7a 100644 --- a/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -200,7 +200,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -4032,6 +4071,17 @@ static int __net_init ip6_route_net_init +@@ -4032,6 +4069,15 @@ static int __net_init ip6_route_net_init net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); @@ -210,8 +210,6 @@ Signed-off-by: Jonas Gorski + sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL); + if (!net->ipv6.ip6_policy_failed_entry) + goto out_ip6_blk_hole_entry; -+ net->ipv6.ip6_policy_failed_entry->dst.path = -+ (struct dst_entry *)net->ipv6.ip6_policy_failed_entry; + net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, + ip6_template_metrics, true);