fib6_nh
if (!fi->fib6_nh->nh_common.nhc_gw_family)
return &fen6_info->rt->fib6_nh->nh_common;
return &iter->fib6_nh->nh_common;
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
ifindex = fib6_nh->fib_nh_dev->ifindex;
weight = fib6_nh->fib_nh_weight;
gw = &fib6_nh->fib_nh_gw6;
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
struct net_device *dev = fib6_nh->fib_nh_dev;
struct in6_addr *gw = &fib6_nh->fib_nh_gw6;
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
if (dev && dev == rt->fib6_nh->fib_nh_dev &&
&rt->fib6_nh->fib_nh_gw6))
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
return rt->fib6_nh->fib_nh_dev &&
mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
struct net_device *dev = rt->fib6_nh->fib_nh_dev;
nh->nh_weight = rt->fib6_nh->fib_nh_weight;
memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
return rt->fib6_nh->fib_nh_gw_family ||
struct fib6_nh fib6_nh[];
struct fib6_nh *nh;
int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
void fib6_nh_release(struct fib6_nh *fib6_nh);
void fib6_nh_release_dsts(struct fib6_nh *fib6_nh);
struct fib6_nh *nha, *nhb;
nha = a->fib6_nh;
nhb = b->fib6_nh;
f6i->fib6_nh->fib_nh_gw_family;
struct fib6_nh;
int (*fib6_nh_init)(struct net *net, struct fib6_nh *fib6_nh,
void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh);
BUILD_BUG_ON(offsetof(struct fib6_nh, nh_common) != 0);
static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh)
return &nhi->fib6_nh;
struct fib6_nh *fib6_nh;
fib6_nh = f6i->nh ? nexthop_fib6_nh(f6i->nh) : f6i->fib6_nh;
return fib6_nh->fib_nh_dev;
res->nh = &nhi->fib6_nh;
int (*cb)(struct fib6_nh *nh, void *arg),
struct fib6_nh fib6_nh;
struct fib6_nh fib6_nh = {};
err = ipv6_stub->fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
nh->fib_nh_dev = fib6_nh.fib_nh_dev;
ipv6_stub->fib6_nh_release(&fib6_nh);
if (nhi->fib6_nh.fib_nh_gw_family)
static bool ipv6_good_nh(const struct fib6_nh *nh)
return ipv6_good_nh(&nhi->fib6_nh);
int (*cb)(struct fib6_nh *nh, void *arg),
err = cb(&nhi->fib6_nh, arg);
err = cb(&nhi->fib6_nh, arg);
ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh);
struct fib6_nh *fib6_nh = &nhi->fib6_nh;
err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL,
ipv6_stub->fib6_nh_release(fib6_nh);
nh->nh_flags = fib6_nh->fib_nh_flags;
ipv6_stub->fib6_nh_release(&nhi->fib6_nh);
struct fib6_nh *fib6_nh;
fib6_nh = &nhi->fib6_nh;
if (fib6_nh->fib_nh_gw_family &&
nla_put_in6_addr(skb, NHA_GATEWAY, &fib6_nh->fib_nh_gw6))
if (rt->fib6_nh->fib_nh_dev->ifindex != dev->ifindex)
if (no_gw && rt->fib6_nh->fib_nh_gw_family)
struct fib6_nh *nh = ifa->rt->fib6_nh;
static int eafnosupport_fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
static int fib6_nh_drop_pcpu_from(struct fib6_nh *nh, void *_arg)
struct fib6_nh *fib6_nh;
fib6_nh = f6i->fib6_nh;
__fib6_drop_pcpu_from(fib6_nh, f6i);
(iter->nh || !iter->fib6_nh->fib_nh_gw_family)) {
sz += sizeof(struct fib6_nh);
fib6_nh_release(f6i->fib6_nh);
struct fib6_nh *fib6_nh = rt->fib6_nh;
fib6_nh = nexthop_fib6_nh(rt->nh);
if (fib6_nh->fib_nh_gw_family) {
seq_printf(seq, "%pi6", &fib6_nh->fib_nh_gw6);
dev = fib6_nh->fib_nh_dev;
static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,
if (!fib6_nh->rt6i_pcpu)
ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu);
neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
rt->fib6_nh->fib_nh_dev, NULL,
neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
rt->fib6_nh->fib_nh_dev, NULL,
static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
const struct fib6_nh *nh = res->nh;
const struct fib6_nh *nh = res->nh;
struct rt6_exception_bucket *fib6_nh_get_excptn_bucket(const struct fib6_nh *nh,
static void fib6_nh_excptn_bucket_set_flushed(struct fib6_nh *nh,
struct fib6_nh *nh = res->nh;
static void fib6_nh_flush_exceptions(struct fib6_nh *nh, struct fib6_info *from)
static int rt6_nh_flush_exceptions(struct fib6_nh *nh, void *arg)
fib6_nh_flush_exceptions(f6i->fib6_nh, f6i);
static int fib6_nh_remove_exception(const struct fib6_nh *nh, int plen,
static int rt6_nh_remove_exception_rt(struct fib6_nh *nh, void *_arg)
return fib6_nh_remove_exception(from->fib6_nh,
static void fib6_nh_update_exception(const struct fib6_nh *nh, int plen,
struct fib6_nh *match;
static int fib6_nh_find_match(struct fib6_nh *nh, void *_arg)
struct fib6_nh *fib6_nh;
fib6_nh = arg.match;
fib6_nh = from->fib6_nh;
fib6_nh_update_exception(fib6_nh, from->fib6_src.plen, rt);
const struct fib6_nh *nh, int mtu)
static void fib6_nh_exceptions_clean_tohost(const struct fib6_nh *nh,
static void fib6_nh_age_exceptions(const struct fib6_nh *nh,
static int rt6_nh_age_exceptions(struct fib6_nh *nh, void *_arg)
fib6_nh_age_exceptions(f6i->fib6_nh, gc_args, now);
res.nh = res.f6i->fib6_nh;
const struct fib6_nh *nh = res->nh;
static int fib6_nh_redirect_match(struct fib6_nh *nh, void *_arg)
res.nh = rt->fib6_nh;
res.nh = rt->fib6_nh;
const struct fib6_nh *nh = res->nh;
int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
netdevice_tracker *dev_tracker = &fib6_nh->fib_nh_dev_tracker;
fib6_nh->fib_nh_family = AF_INET6;
fib6_nh->last_probe = jiffies;
fib6_nh->fib_nh_gw6 = cfg->fc_gateway;
fib6_nh->fib_nh_gw_family = AF_INET6;
fib6_nh->fib_nh_flags |= RTNH_F_ONLINK;
fib6_nh->fib_nh_weight = 1;
fib6_nh->fib_nh_gw6 = cfg->fc_gateway;
fib6_nh->fib_nh_gw_family = AF_INET6;
fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
err = fib_nh_common_init(net, &fib6_nh->nh_common, cfg->fc_encap,
fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags);
if (!fib6_nh->rt6i_pcpu) {
fib6_nh->fib_nh_dev = dev;
fib6_nh->fib_nh_oif = dev->ifindex;
fib_nh_common_release(&fib6_nh->nh_common);
fib6_nh->nh_common.nhc_pcpu_rth_output = NULL;
fib6_nh->fib_nh_lws = NULL;
void fib6_nh_release(struct fib6_nh *fib6_nh)
fib6_nh_flush_exceptions(fib6_nh, NULL);
bucket = fib6_nh_get_excptn_bucket(fib6_nh, NULL);
rcu_assign_pointer(fib6_nh->rt6i_exception_bucket, NULL);
fib6_nh_release_dsts(fib6_nh);
free_percpu(fib6_nh->rt6i_pcpu);
fib_nh_common_release(&fib6_nh->nh_common);
void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
if (!fib6_nh->rt6i_pcpu)
ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu);
struct fib6_nh *fib6_nh;
fib6_nh = nexthop_fib6_nh(rt->nh);
err = fib6_nh_init(net, rt->fib6_nh, cfg, gfp_flags, extack);
fib6_nh = rt->fib6_nh;
if (fib6_is_reject(cfg->fc_flags, rt->fib6_nh->fib_nh_dev,
struct net_device *dev = fib6_nh->fib_nh_dev;
struct fib6_nh *nh)
static int fib6_nh_del_cached_rt(struct fib6_nh *nh, void *_arg)
struct fib6_nh *nh;
nh = rt->fib6_nh;
nh = rt->fib6_nh;
res.nh = res.f6i->fib6_nh;
if (rt->fib6_nh->fib_nh_dev->ifindex != ifindex)
!rt->fib6_nh->fib_nh_gw_family)
if (!ipv6_addr_equal(&rt->fib6_nh->fib_nh_gw6, gwaddr))
struct fib6_nh *nh;
nh = rt->fib6_nh;
!ipv6_chk_addr(net, addr, rt->fib6_nh->fib_nh_dev, 0)) {
if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound)) {
if (rt6_score_route(first->fib6_nh, first->fib6_flags, oif,
struct fib6_nh *nh;
nh = rt->fib6_nh;
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)))
const struct fib6_nh *nh = sibling->fib6_nh;
total += rt->fib6_nh->fib_nh_weight;
total += iter->fib6_nh->fib_nh_weight;
*weight += rt->fib6_nh->fib_nh_weight;
atomic_set(&rt->fib6_nh->fib_nh_upper_bound, upper_bound);
rt->fib6_nh->fib_nh_dev == arg->dev) {
rt->fib6_nh->fib_nh_flags &= ~arg->nh_flags;
if (rt->fib6_nh->fib_nh_dev == dev)
if (iter->fib6_nh->fib_nh_dev == dev)
if (rt->fib6_nh->fib_nh_dev == down_dev ||
rt->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)
if (rt->fib6_nh->fib_nh_dev == dev)
rt->fib6_nh->fib_nh_flags |= nh_flags;
res->nh = match->fib6_nh;
if (iter->fib6_nh->fib_nh_dev == dev)
iter->fib6_nh->fib_nh_flags |= nh_flags;
return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0;
return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0;
if (rt->fib6_nh->fib_nh_dev != dev ||
rt->fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
static bool __rt6_device_match(struct net *net, const struct fib6_nh *nh,
static int fib6_nh_mtu_change(struct fib6_nh *nh, void *_arg)
return fib6_nh_mtu_change(f6i->fib6_nh, arg);
struct fib6_nh *nh;
static int __rt6_nh_dev_match(struct fib6_nh *nh, void *_arg)
static struct fib6_nh *rt6_nh_dev_match(struct net *net, struct nexthop *nh,
rt->fib6_nh->fib_nh_weight = rtnh->rtnh_hops + 1;
static int rt6_nh_nlmsg_size(struct fib6_nh *nh, void *arg)
struct fib6_nh *nh;
struct fib6_nh *nh;
nh = f6i->fib6_nh;
rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len);
struct fib6_nh *fib6_nh;
fib6_nh = nexthop_fib6_nh(nh);
if (fib_nexthop_info(skb, &fib6_nh->nh_common, AF_INET6,
nh = f6i->fib6_nh;
if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common,
rt->fib6_nh->fib_nh_weight, AF_INET6,
if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common,
sibling->fib6_nh->fib_nh_weight,
nh = spf6i->fib6_nh;
if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common, AF_INET6,
static int fib6_info_nh_uses_dev(struct fib6_nh *nh, void *arg)
if (f6i->fib6_nh->fib_nh_dev == dev)
if (sibling->fib6_nh->fib_nh_dev == dev) {
static int rt6_nh_dump_exceptions(struct fib6_nh *nh, void *arg)
nh = res->f6i->fib6_nh;
err = rt6_nh_dump_exceptions(rt->fib6_nh, &w);
nh = f6i->fib6_nh;
nh = res->f6i->fib6_nh;
net->ipv6.fib6_null_entry->fib6_nh->fib_nh_dev = dev;
static void rt6_probe(struct fib6_nh *fib6_nh)
if (!fib6_nh->fib_nh_gw_family)
nh_gw = &fib6_nh->fib_nh_gw6;
dev = fib6_nh->fib_nh_dev;
last_probe = READ_ONCE(fib6_nh->last_probe);
init_net.ipv6.fib6_null_entry->fib6_nh->fib_nh_dev = init_net.loopback_dev;
if (!work || cmpxchg(&fib6_nh->last_probe,
static inline void rt6_probe(struct fib6_nh *fib6_nh)
static enum rt6_nud_state rt6_check_neigh(const struct fib6_nh *fib6_nh)
neigh = __ipv6_neigh_lookup_noref(fib6_nh->fib_nh_dev,
&fib6_nh->fib_nh_gw6);
static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
struct fib6_nh *nh;
static int rt6_nh_find_match(struct fib6_nh *nh, void *_arg)
struct fib6_nh *nh;
nh = f6i->fib6_nh;
res->nh = res->f6i->fib6_nh;
struct fib6_nh *fib6_nh;
fib6_nh = &rt->fib6_nh[0];
fib6_nh = &nh->nh_info->fib6_nh;
if (fib6_nh->fib_nh_gw_family) {
BPF_SEQ_PRINTF(seq, "%pi6 ", &fib6_nh->fib_nh_gw6);
dev = fib6_nh->fib_nh_dev;