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 <ros...@gmail.com>
---
 .../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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <ros...@gmail.com>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+---
+ 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 <linux/sched.h>
+ #include <linux/prefetch.h>
+ #include <net/lwtunnel.h>
++#include <net/xfrm.h>
+ 
+ #include <net/dst.h>
+ #include <net/dst_metadata.h>
+@@ -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 <ros...@gmail.com>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <da...@davemloft.net>
+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 <da...@davemloft.net>
+Reviewed-by: Eric Dumazet <eduma...@google.com>
+---
+ 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 <j...@openwrt.org>
                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 <j...@openwrt.org>
 +                      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);
-- 
2.16.2


_______________________________________________
Lede-dev mailing list
Lede-dev@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/lede-dev

Reply via email to