u32                             rt6i_flags;
        struct rt6key                   rt6i_src;
        struct rt6key                   rt6i_prefsrc;
-       u32                             rt6i_metric;
 
        struct inet6_dev                *rt6i_idev;
        unsigned long                   _rt6i_peer;
 
-       u32                             rt6i_genid;
-
+       u32                             rt6i_metric;
        /* more non-fragment space at head required */
        unsigned short                  rt6i_nfheader_len;
-
        u8                              rt6i_protocol;
 };
 
 
        atomic_inc(&net->ipv4.rt_genid);
 }
 
-#if IS_ENABLED(CONFIG_IPV6)
-static inline int rt_genid_ipv6(struct net *net)
-{
-       return atomic_read(&net->ipv6.rt_genid);
-}
-
-static inline void rt_genid_bump_ipv6(struct net *net)
-{
-       atomic_inc(&net->ipv6.rt_genid);
-}
-#else
-static inline int rt_genid_ipv6(struct net *net)
-{
-       return 0;
-}
-
+extern void (*__fib6_flush_trees)(struct net *net);
 static inline void rt_genid_bump_ipv6(struct net *net)
 {
+       if (__fib6_flush_trees)
+               __fib6_flush_trees(net);
 }
-#endif
 
 #if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
 static inline struct netns_ieee802154_lowpan *
 
 
                if (ip6_del_rt(ifp->rt))
                        dst_free(&ifp->rt->dst);
+
+               rt_genid_bump_ipv6(net);
                break;
        }
        atomic_inc(&net->ipv6.dev_addr_genid);
-       rt_genid_bump_ipv6(net);
 }
 
 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
 #include <net/addrconf.h>
 #include <net/ip.h>
 
+/* if ipv6 module registers this function is used by xfrm to force all
+ * sockets to relookup their nodes - this is fairly expensive, be
+ * careful
+ */
+void (*__fib6_flush_trees)(struct net *);
+EXPORT_SYMBOL(__fib6_flush_trees);
+
 #define IPV6_ADDR_SCOPE_TYPE(scope)    ((scope) << 16)
 
 static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
 
        fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL);
 }
 
+static int fib6_update_sernum(struct rt6_info *rt, void *arg)
+{
+       __u32 sernum = *(__u32 *)arg;
+
+       if (rt->rt6i_node &&
+           rt->rt6i_node->fn_sernum != sernum)
+               rt->rt6i_node->fn_sernum = sernum;
+
+       return 0;
+}
+
+static void fib6_flush_trees(struct net *net)
+{
+       __u32 new_sernum = fib6_new_sernum();
+
+       fib6_clean_all(net, fib6_update_sernum, &new_sernum);
+}
+
 /*
  *     Garbage collection
  */
                              NULL);
        if (ret)
                goto out_unregister_subsys;
+
+       __fib6_flush_trees = fib6_flush_trees;
 out:
        return ret;
 
 
 
                memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
                rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
-               rt->rt6i_genid = rt_genid_ipv6(net);
                INIT_LIST_HEAD(&rt->rt6i_siblings);
        }
        return rt;
         * DST_OBSOLETE_FORCE_CHK which forces validation calls down
         * into this function always.
         */
-       if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
-               return NULL;
-
        if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
                return NULL;