return false;
 
        list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
-               struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh;
+               struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
                struct in6_addr *gw;
                int ifindex, weight;
 
        struct net_device *dev;
 
        list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
-               dev = mlxsw_sp_rt6->rt->fib6_nh.fib_nh_dev;
+               dev = mlxsw_sp_rt6->rt->fib6_nh->fib_nh_dev;
                val ^= dev->ifindex;
        }
 
                struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
                struct fib6_info *rt = mlxsw_sp_rt6->rt;
 
-               if (nh->rif && nh->rif->dev == rt->fib6_nh.fib_nh_dev &&
+               if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
                    ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
-                                   &rt->fib6_nh.fib_nh_gw6))
+                                   &rt->fib6_nh->fib_nh_gw6))
                        return nh;
                continue;
        }
        if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
            fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) {
                list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
-                                list)->rt->fib6_nh.fib_nh_flags |= RTNH_F_OFFLOAD;
+                                list)->rt->fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
                return;
        }
 
        list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
                struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
-               struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh;
+               struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
                struct mlxsw_sp_nexthop *nh;
 
                nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
        list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
                struct fib6_info *rt = mlxsw_sp_rt6->rt;
 
-               rt->fib6_nh.fib_nh_flags &= ~RTNH_F_OFFLOAD;
+               rt->fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
        }
 }
 
 static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
 {
        /* RTF_CACHE routes are ignored */
-       return !(rt->fib6_flags & RTF_ADDRCONF) && rt->fib6_nh.fib_nh_gw_family;
+       return !(rt->fib6_flags & RTF_ADDRCONF) &&
+               rt->fib6_nh->fib_nh_gw_family;
 }
 
 static struct fib6_info *
                                        const struct fib6_info *rt,
                                        enum mlxsw_sp_ipip_type *ret)
 {
-       return rt->fib6_nh.fib_nh_dev &&
-              mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh.fib_nh_dev, ret);
+       return rt->fib6_nh->fib_nh_dev &&
+              mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
 }
 
 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
 {
        const struct mlxsw_sp_ipip_ops *ipip_ops;
        struct mlxsw_sp_ipip_entry *ipip_entry;
-       struct net_device *dev = rt->fib6_nh.fib_nh_dev;
+       struct net_device *dev = rt->fib6_nh->fib_nh_dev;
        struct mlxsw_sp_rif *rif;
        int err;
 
                                  struct mlxsw_sp_nexthop *nh,
                                  const struct fib6_info *rt)
 {
-       struct net_device *dev = rt->fib6_nh.fib_nh_dev;
+       struct net_device *dev = rt->fib6_nh->fib_nh_dev;
 
        nh->nh_grp = nh_grp;
-       nh->nh_weight = rt->fib6_nh.fib_nh_weight;
-       memcpy(&nh->gw_addr, &rt->fib6_nh.fib_nh_gw6, sizeof(nh->gw_addr));
+       nh->nh_weight = rt->fib6_nh->fib_nh_weight;
+       memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
        mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
 
        list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
                                    const struct fib6_info *rt)
 {
-       return rt->fib6_nh.fib_nh_gw_family ||
+       return rt->fib6_nh->fib_nh_gw_family ||
               mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
 }
 
 
        if (!fl6->mp_hash)
                fl6->mp_hash = rt6_multipath_hash(net, fl6, skb, NULL);
 
-       if (fl6->mp_hash <= atomic_read(&match->fib6_nh.fib_nh_upper_bound))
+       if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound))
                goto out;
 
        list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings,
                                 fib6_siblings) {
-               const struct fib6_nh *nh = &sibling->fib6_nh;
+               const struct fib6_nh *nh = sibling->fib6_nh;
                int nh_upper_bound;
 
                nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
 
 out:
        res->f6i = match;
-       res->nh = &match->fib6_nh;
+       res->nh = match->fib6_nh;
 }
 
 /*
        struct fib6_nh *nh;
 
        if (!oif && ipv6_addr_any(saddr)) {
-               nh = &f6i->fib6_nh;
+               nh = f6i->fib6_nh;
                if (!(nh->fib_nh_flags & RTNH_F_DEAD))
                        goto out;
        }
 
        for (spf6i = f6i; spf6i; spf6i = rcu_dereference(spf6i->fib6_next)) {
-               nh = &spf6i->fib6_nh;
+               nh = spf6i->fib6_nh;
                if (__rt6_device_match(net, nh, saddr, oif, flags)) {
                        res->f6i = spf6i;
                        goto out;
 
        if (oif && flags & RT6_LOOKUP_F_IFACE) {
                res->f6i = net->ipv6.fib6_null_entry;
-               nh = &res->f6i->fib6_nh;
+               nh = res->f6i->fib6_nh;
                goto out;
        }
 
-       nh = &f6i->fib6_nh;
+       nh = f6i->fib6_nh;
        if (nh->fib_nh_flags & RTNH_F_DEAD) {
                res->f6i = net->ipv6.fib6_null_entry;
-               nh = &res->f6i->fib6_nh;
+               nh = res->f6i->fib6_nh;
        }
 out:
        res->nh = nh;
                if (fib6_check_expired(f6i))
                        continue;
 
-               nh = &f6i->fib6_nh;
+               nh = f6i->fib6_nh;
                if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
                        res->f6i = f6i;
                        res->nh = nh;
 out:
        if (!res->f6i) {
                res->f6i = net->ipv6.fib6_null_entry;
-               res->nh = &res->f6i->fib6_nh;
+               res->nh = res->f6i->fib6_nh;
                res->fib6_flags = res->f6i->fib6_flags;
                res->fib6_type = res->f6i->fib6_type;
        }
 
 void rt6_flush_exceptions(struct fib6_info *f6i)
 {
-       fib6_nh_flush_exceptions(&f6i->fib6_nh, f6i);
+       fib6_nh_flush_exceptions(f6i->fib6_nh, f6i);
 }
 
 /* Find cached rt in the hash table inside passed in rt
        if (!from || !(rt->rt6i_flags & RTF_CACHE))
                return -EINVAL;
 
-       return fib6_nh_remove_exception(&from->fib6_nh,
+       return fib6_nh_remove_exception(from->fib6_nh,
                                        from->fib6_src.plen, rt);
 }
 
        if (!from || !(rt->rt6i_flags & RTF_CACHE))
                goto unlock;
 
-       fib6_nh_update_exception(&from->fib6_nh, from->fib6_src.plen, rt);
+       fib6_nh_update_exception(from->fib6_nh, from->fib6_src.plen, rt);
 unlock:
        rcu_read_unlock();
 }
                        struct fib6_gc_args *gc_args,
                        unsigned long now)
 {
-       fib6_nh_age_exceptions(&f6i->fib6_nh, gc_args, now);
+       fib6_nh_age_exceptions(f6i->fib6_nh, gc_args, now);
 }
 
 /* must be called with rcu lock held */
                        rcu_read_unlock();
                        return;
                }
-               res.nh = &res.f6i->fib6_nh;
+               res.nh = res.f6i->fib6_nh;
                res.fib6_flags = res.f6i->fib6_flags;
                res.fib6_type = res.f6i->fib6_type;
 
 restart:
        for_each_fib6_node_rt_rcu(fn) {
                res.f6i = rt;
-               res.nh = &rt->fib6_nh;
+               res.nh = rt->fib6_nh;
 
                if (fib6_check_expired(rt))
                        continue;
        }
 
        res.f6i = rt;
-       res.nh = &rt->fib6_nh;
+       res.nh = rt->fib6_nh;
 out:
        if (ret) {
                ip6_hold_safe(net, &ret);
                goto out;
 
        err = -ENOMEM;
-       rt = fib6_info_alloc(gfp_flags);
+       rt = fib6_info_alloc(gfp_flags, true);
        if (!rt)
                goto out;
 
        ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len);
        rt->fib6_src.plen = cfg->fc_src_len;
 #endif
-       err = fib6_nh_init(net, &rt->fib6_nh, cfg, gfp_flags, extack);
+       err = fib6_nh_init(net, rt->fib6_nh, cfg, gfp_flags, extack);
        if (err)
                goto out;
 
         * they would result in kernel looping; promote them to reject routes
         */
        addr_type = ipv6_addr_type(&cfg->fc_dst);
-       if (fib6_is_reject(cfg->fc_flags, rt->fib6_nh.fib_nh_dev, addr_type))
+       if (fib6_is_reject(cfg->fc_flags, rt->fib6_nh->fib_nh_dev, addr_type))
                rt->fib6_flags = RTF_REJECT | RTF_NONEXTHOP;
 
        if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
                for_each_fib6_node_rt_rcu(fn) {
                        struct fib6_nh *nh;
 
-                       nh = &rt->fib6_nh;
+                       nh = rt->fib6_nh;
                        if (cfg->fc_flags & RTF_CACHE) {
                                struct fib6_result res = {
                                        .f6i = rt,
        if (!res.f6i)
                goto out;
 
-       res.nh = &res.f6i->fib6_nh;
+       res.nh = res.f6i->fib6_nh;
        res.fib6_flags = res.f6i->fib6_flags;
        res.fib6_type = res.f6i->fib6_type;
        nrt = ip6_rt_cache_alloc(&res, &msg->dest, NULL);
                goto out;
 
        for_each_fib6_node_rt_rcu(fn) {
-               if (rt->fib6_nh.fib_nh_dev->ifindex != ifindex)
+               if (rt->fib6_nh->fib_nh_dev->ifindex != ifindex)
                        continue;
                if (!(rt->fib6_flags & RTF_ROUTEINFO) ||
-                   !rt->fib6_nh.fib_nh_gw_family)
+                   !rt->fib6_nh->fib_nh_gw_family)
                        continue;
-               if (!ipv6_addr_equal(&rt->fib6_nh.fib_nh_gw6, gwaddr))
+               if (!ipv6_addr_equal(&rt->fib6_nh->fib_nh_gw6, gwaddr))
                        continue;
                if (!fib6_info_hold_safe(rt))
                        continue;
 
        rcu_read_lock();
        for_each_fib6_node_rt_rcu(&table->tb6_root) {
-               struct fib6_nh *nh = &rt->fib6_nh;
+               struct fib6_nh *nh = rt->fib6_nh;
 
                if (dev == nh->fib_nh_dev &&
                    ((rt->fib6_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
        struct net *net = ((struct arg_dev_net_ip *)arg)->net;
        struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
 
-       if (((void *)rt->fib6_nh.fib_nh_dev == dev || !dev) &&
+       if (((void *)rt->fib6_nh->fib_nh_dev == dev || !dev) &&
            rt != net->ipv6.fib6_null_entry &&
            ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) {
                spin_lock_bh(&rt6_exception_lock);
 static int fib6_clean_tohost(struct fib6_info *rt, void *arg)
 {
        struct in6_addr *gateway = (struct in6_addr *)arg;
-       struct fib6_nh *nh = &rt->fib6_nh;
+       struct fib6_nh *nh = rt->fib6_nh;
 
        if (((rt->fib6_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) &&
            nh->fib_nh_gw_family && ipv6_addr_equal(gateway, &nh->fib_nh_gw6))
 
 static bool rt6_is_dead(const struct fib6_info *rt)
 {
-       if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD ||
-           (rt->fib6_nh.fib_nh_flags & RTNH_F_LINKDOWN &&
-            ip6_ignore_linkdown(rt->fib6_nh.fib_nh_dev)))
+       if (rt->fib6_nh->fib_nh_flags & RTNH_F_DEAD ||
+           (rt->fib6_nh->fib_nh_flags & RTNH_F_LINKDOWN &&
+            ip6_ignore_linkdown(rt->fib6_nh->fib_nh_dev)))
                return true;
 
        return false;
        int total = 0;
 
        if (!rt6_is_dead(rt))
-               total += rt->fib6_nh.fib_nh_weight;
+               total += rt->fib6_nh->fib_nh_weight;
 
        list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
                if (!rt6_is_dead(iter))
-                       total += iter->fib6_nh.fib_nh_weight;
+                       total += iter->fib6_nh->fib_nh_weight;
        }
 
        return total;
        int upper_bound = -1;
 
        if (!rt6_is_dead(rt)) {
-               *weight += rt->fib6_nh.fib_nh_weight;
+               *weight += rt->fib6_nh->fib_nh_weight;
                upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
                                                    total) - 1;
        }
-       atomic_set(&rt->fib6_nh.fib_nh_upper_bound, upper_bound);
+       atomic_set(&rt->fib6_nh->fib_nh_upper_bound, upper_bound);
 }
 
 static void rt6_multipath_upper_bound_set(struct fib6_info *rt, int total)
        struct net *net = dev_net(arg->dev);
 
        if (rt != net->ipv6.fib6_null_entry &&
-           rt->fib6_nh.fib_nh_dev == arg->dev) {
-               rt->fib6_nh.fib_nh_flags &= ~arg->nh_flags;
+           rt->fib6_nh->fib_nh_dev == arg->dev) {
+               rt->fib6_nh->fib_nh_flags &= ~arg->nh_flags;
                fib6_update_sernum_upto_root(net, rt);
                rt6_multipath_rebalance(rt);
        }
 {
        struct fib6_info *iter;
 
-       if (rt->fib6_nh.fib_nh_dev == dev)
+       if (rt->fib6_nh->fib_nh_dev == dev)
                return true;
        list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
-               if (iter->fib6_nh.fib_nh_dev == dev)
+               if (iter->fib6_nh->fib_nh_dev == dev)
                        return true;
 
        return false;
        struct fib6_info *iter;
        unsigned int dead = 0;
 
-       if (rt->fib6_nh.fib_nh_dev == down_dev ||
-           rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
+       if (rt->fib6_nh->fib_nh_dev == down_dev ||
+           rt->fib6_nh->fib_nh_flags & RTNH_F_DEAD)
                dead++;
        list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
-               if (iter->fib6_nh.fib_nh_dev == down_dev ||
-                   iter->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
+               if (iter->fib6_nh->fib_nh_dev == down_dev ||
+                   iter->fib6_nh->fib_nh_flags & RTNH_F_DEAD)
                        dead++;
 
        return dead;
 {
        struct fib6_info *iter;
 
-       if (rt->fib6_nh.fib_nh_dev == dev)
-               rt->fib6_nh.fib_nh_flags |= nh_flags;
+       if (rt->fib6_nh->fib_nh_dev == dev)
+               rt->fib6_nh->fib_nh_flags |= nh_flags;
        list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
-               if (iter->fib6_nh.fib_nh_dev == dev)
-                       iter->fib6_nh.fib_nh_flags |= nh_flags;
+               if (iter->fib6_nh->fib_nh_dev == dev)
+                       iter->fib6_nh->fib_nh_flags |= nh_flags;
 }
 
 /* called with write lock held for table with rt */
 
        switch (arg->event) {
        case NETDEV_UNREGISTER:
-               return rt->fib6_nh.fib_nh_dev == dev ? -1 : 0;
+               return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0;
        case NETDEV_DOWN:
                if (rt->should_flush)
                        return -1;
                if (!rt->fib6_nsiblings)
-                       return rt->fib6_nh.fib_nh_dev == dev ? -1 : 0;
+                       return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0;
                if (rt6_multipath_uses_dev(rt, dev)) {
                        unsigned int count;
 
                }
                return -2;
        case NETDEV_CHANGE:
-               if (rt->fib6_nh.fib_nh_dev != dev ||
+               if (rt->fib6_nh->fib_nh_dev != dev ||
                    rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
                        break;
-               rt->fib6_nh.fib_nh_flags |= RTNH_F_LINKDOWN;
+               rt->fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
                rt6_multipath_rebalance(rt);
                break;
        }
                return 0;
 
        arg->f6i = f6i;
-       return fib6_nh_mtu_change(&f6i->fib6_nh, arg);
+       return fib6_nh_mtu_change(f6i->fib6_nh, arg);
 }
 
 void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
                        goto cleanup;
                }
 
-               rt->fib6_nh.fib_nh_weight = rtnh->rtnh_hops + 1;
+               rt->fib6_nh->fib_nh_weight = rtnh->rtnh_hops + 1;
 
                err = ip6_route_info_append(info->nl_net, &rt6_nh_list,
                                            rt, &r_cfg);
                nexthop_len = nla_total_size(0)  /* RTA_MULTIPATH */
                            + NLA_ALIGN(sizeof(struct rtnexthop))
                            + nla_total_size(16) /* RTA_GATEWAY */
-                           + lwtunnel_get_encap_size(rt->fib6_nh.fib_nh_lws);
+                           + lwtunnel_get_encap_size(rt->fib6_nh->fib_nh_lws);
 
                nexthop_len *= rt->fib6_nsiblings;
        }
               + nla_total_size(sizeof(struct rta_cacheinfo))
               + nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
               + nla_total_size(1) /* RTA_PREF */
-              + lwtunnel_get_encap_size(rt->fib6_nh.fib_nh_lws)
+              + lwtunnel_get_encap_size(rt->fib6_nh->fib_nh_lws)
               + nexthop_len;
 }
 
                if (!mp)
                        goto nla_put_failure;
 
-               if (fib_add_nexthop(skb, &rt->fib6_nh.nh_common,
-                                   rt->fib6_nh.fib_nh_weight) < 0)
+               if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common,
+                                   rt->fib6_nh->fib_nh_weight) < 0)
                        goto nla_put_failure;
 
                list_for_each_entry_safe(sibling, next_sibling,
                                         &rt->fib6_siblings, fib6_siblings) {
-                       if (fib_add_nexthop(skb, &sibling->fib6_nh.nh_common,
-                                           sibling->fib6_nh.fib_nh_weight) < 0)
+                       if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common,
+                                           sibling->fib6_nh->fib_nh_weight) < 0)
                                goto nla_put_failure;
                }
 
        } else {
                unsigned char nh_flags = 0;
 
-               if (fib_nexthop_info(skb, &rt->fib6_nh.nh_common,
+               if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common,
                                     &nh_flags, false) < 0)
                        goto nla_put_failure;
 
 static bool fib6_info_uses_dev(const struct fib6_info *f6i,
                               const struct net_device *dev)
 {
-       if (f6i->fib6_nh.fib_nh_dev == dev)
+       if (f6i->fib6_nh->fib_nh_dev == dev)
                return true;
 
        if (f6i->fib6_nsiblings) {
 
                list_for_each_entry_safe(sibling, next_sibling,
                                         &f6i->fib6_siblings, fib6_siblings) {
-                       if (sibling->fib6_nh.fib_nh_dev == dev)
+                       if (sibling->fib6_nh->fib_nh_dev == dev)
                                return true;
                }
        }
                return NOTIFY_OK;
 
        if (event == NETDEV_REGISTER) {
-               net->ipv6.fib6_null_entry->fib6_nh.fib_nh_dev = dev;
+               net->ipv6.fib6_null_entry->fib6_nh->fib_nh_dev = dev;
                net->ipv6.ip6_null_entry->dst.dev = dev;
                net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
        if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
                goto out_ip6_dst_ops;
 
-       net->ipv6.fib6_null_entry = kmemdup(&fib6_null_entry_template,
-                                           sizeof(*net->ipv6.fib6_null_entry),
-                                           GFP_KERNEL);
+       net->ipv6.fib6_null_entry = fib6_info_alloc(GFP_KERNEL, true);
        if (!net->ipv6.fib6_null_entry)
                goto out_ip6_dst_entries;
+       memcpy(net->ipv6.fib6_null_entry, &fib6_null_entry_template,
+              sizeof(*net->ipv6.fib6_null_entry));
 
        net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
                                           sizeof(*net->ipv6.ip6_null_entry),
        /* Registering of the loopback is done before this portion of code,
         * the loopback reference in rt6_info will not be taken, do it
         * manually for init_net */
-       init_net.ipv6.fib6_null_entry->fib6_nh.fib_nh_dev = init_net.loopback_dev;
+       init_net.ipv6.fib6_null_entry->fib6_nh->fib_nh_dev = init_net.loopback_dev;
        init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
        init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
   #ifdef CONFIG_IPV6_MULTIPLE_TABLES