|
@@ -284,10 +284,10 @@ static const u32 ip6_template_metrics[RTAX_MAX] = {
|
|
|
};
|
|
|
|
|
|
static const struct fib6_info fib6_null_entry_template = {
|
|
|
- .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
|
|
- .rt6i_protocol = RTPROT_KERNEL,
|
|
|
- .rt6i_metric = ~(u32)0,
|
|
|
- .rt6i_ref = ATOMIC_INIT(1),
|
|
|
+ .fib6_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
|
|
+ .fib6_protocol = RTPROT_KERNEL,
|
|
|
+ .fib6_metric = ~(u32)0,
|
|
|
+ .fib6_ref = ATOMIC_INIT(1),
|
|
|
.fib6_type = RTN_UNREACHABLE,
|
|
|
.fib6_metrics = (struct dst_metrics *)&dst_default_metrics,
|
|
|
};
|
|
@@ -429,8 +429,8 @@ static struct fib6_info *rt6_multipath_select(const struct net *net,
|
|
|
if (fl6->mp_hash <= atomic_read(&match->fib6_nh.nh_upper_bound))
|
|
|
return match;
|
|
|
|
|
|
- list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
|
|
|
- rt6i_siblings) {
|
|
|
+ list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings,
|
|
|
+ fib6_siblings) {
|
|
|
int nh_upper_bound;
|
|
|
|
|
|
nh_upper_bound = atomic_read(&sibling->fib6_nh.nh_upper_bound);
|
|
@@ -455,7 +455,6 @@ static inline struct fib6_info *rt6_device_match(struct net *net,
|
|
|
int oif,
|
|
|
int flags)
|
|
|
{
|
|
|
- struct fib6_info *local = NULL;
|
|
|
struct fib6_info *sprt;
|
|
|
|
|
|
if (!oif && ipv6_addr_any(saddr) &&
|
|
@@ -471,17 +470,6 @@ static inline struct fib6_info *rt6_device_match(struct net *net,
|
|
|
if (oif) {
|
|
|
if (dev->ifindex == oif)
|
|
|
return sprt;
|
|
|
- if (dev->flags & IFF_LOOPBACK) {
|
|
|
- if (!sprt->rt6i_idev ||
|
|
|
- sprt->rt6i_idev->dev->ifindex != oif) {
|
|
|
- if (flags & RT6_LOOKUP_F_IFACE)
|
|
|
- continue;
|
|
|
- if (local &&
|
|
|
- local->rt6i_idev->dev->ifindex == oif)
|
|
|
- continue;
|
|
|
- }
|
|
|
- local = sprt;
|
|
|
- }
|
|
|
} else {
|
|
|
if (ipv6_chk_addr(net, saddr, dev,
|
|
|
flags & RT6_LOOKUP_F_IFACE))
|
|
@@ -489,13 +477,8 @@ static inline struct fib6_info *rt6_device_match(struct net *net,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (oif) {
|
|
|
- if (local)
|
|
|
- return local;
|
|
|
-
|
|
|
- if (flags & RT6_LOOKUP_F_IFACE)
|
|
|
- return net->ipv6.fib6_null_entry;
|
|
|
- }
|
|
|
+ if (oif && flags & RT6_LOOKUP_F_IFACE)
|
|
|
+ return net->ipv6.fib6_null_entry;
|
|
|
|
|
|
return rt->fib6_nh.nh_flags & RTNH_F_DEAD ? net->ipv6.fib6_null_entry : rt;
|
|
|
}
|
|
@@ -534,7 +517,7 @@ static void rt6_probe(struct fib6_info *rt)
|
|
|
* Router Reachability Probe MUST be rate-limited
|
|
|
* to no more than one per minute.
|
|
|
*/
|
|
|
- if (!rt || !(rt->rt6i_flags & RTF_GATEWAY))
|
|
|
+ if (!rt || !(rt->fib6_flags & RTF_GATEWAY))
|
|
|
return;
|
|
|
|
|
|
nh_gw = &rt->fib6_nh.nh_gw;
|
|
@@ -542,15 +525,17 @@ static void rt6_probe(struct fib6_info *rt)
|
|
|
rcu_read_lock_bh();
|
|
|
neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
|
|
|
if (neigh) {
|
|
|
+ struct inet6_dev *idev;
|
|
|
+
|
|
|
if (neigh->nud_state & NUD_VALID)
|
|
|
goto out;
|
|
|
|
|
|
+ idev = __in6_dev_get(dev);
|
|
|
work = NULL;
|
|
|
write_lock(&neigh->lock);
|
|
|
if (!(neigh->nud_state & NUD_VALID) &&
|
|
|
time_after(jiffies,
|
|
|
- neigh->updated +
|
|
|
- rt->rt6i_idev->cnf.rtr_probe_interval)) {
|
|
|
+ neigh->updated + idev->cnf.rtr_probe_interval)) {
|
|
|
work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
|
|
if (work)
|
|
|
__neigh_set_probe_once(neigh);
|
|
@@ -586,9 +571,6 @@ static inline int rt6_check_dev(struct fib6_info *rt, int oif)
|
|
|
|
|
|
if (!oif || dev->ifindex == oif)
|
|
|
return 2;
|
|
|
- if ((dev->flags & IFF_LOOPBACK) &&
|
|
|
- rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
|
|
|
- return 1;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -597,8 +579,8 @@ static inline enum rt6_nud_state rt6_check_neigh(struct fib6_info *rt)
|
|
|
enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
|
|
|
struct neighbour *neigh;
|
|
|
|
|
|
- if (rt->rt6i_flags & RTF_NONEXTHOP ||
|
|
|
- !(rt->rt6i_flags & RTF_GATEWAY))
|
|
|
+ if (rt->fib6_flags & RTF_NONEXTHOP ||
|
|
|
+ !(rt->fib6_flags & RTF_GATEWAY))
|
|
|
return RT6_NUD_SUCCEED;
|
|
|
|
|
|
rcu_read_lock_bh();
|
|
@@ -632,7 +614,7 @@ static int rt6_score_route(struct fib6_info *rt, int oif, int strict)
|
|
|
if (!m && (strict & RT6_LOOKUP_F_IFACE))
|
|
|
return RT6_NUD_FAIL_HARD;
|
|
|
#ifdef CONFIG_IPV6_ROUTER_PREF
|
|
|
- m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
|
|
|
+ m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->fib6_flags)) << 2;
|
|
|
#endif
|
|
|
if (strict & RT6_LOOKUP_F_REACHABLE) {
|
|
|
int n = rt6_check_neigh(rt);
|
|
@@ -642,18 +624,32 @@ static int rt6_score_route(struct fib6_info *rt, int oif, int strict)
|
|
|
return m;
|
|
|
}
|
|
|
|
|
|
+/* called with rc_read_lock held */
|
|
|
+static inline bool fib6_ignore_linkdown(const struct fib6_info *f6i)
|
|
|
+{
|
|
|
+ const struct net_device *dev = fib6_info_nh_dev(f6i);
|
|
|
+ bool rc = false;
|
|
|
+
|
|
|
+ if (dev) {
|
|
|
+ const struct inet6_dev *idev = __in6_dev_get(dev);
|
|
|
+
|
|
|
+ rc = !!idev->cnf.ignore_routes_with_linkdown;
|
|
|
+ }
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
static struct fib6_info *find_match(struct fib6_info *rt, int oif, int strict,
|
|
|
int *mpri, struct fib6_info *match,
|
|
|
bool *do_rr)
|
|
|
{
|
|
|
int m;
|
|
|
bool match_do_rr = false;
|
|
|
- struct inet6_dev *idev = rt->rt6i_idev;
|
|
|
|
|
|
if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
|
|
|
goto out;
|
|
|
|
|
|
- if (idev->cnf.ignore_routes_with_linkdown &&
|
|
|
+ if (fib6_ignore_linkdown(rt) &&
|
|
|
rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
|
|
|
!(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
|
|
|
goto out;
|
|
@@ -694,7 +690,7 @@ static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
|
|
|
match = NULL;
|
|
|
cont = NULL;
|
|
|
for (rt = rr_head; rt; rt = rcu_dereference(rt->rt6_next)) {
|
|
|
- if (rt->rt6i_metric != metric) {
|
|
|
+ if (rt->fib6_metric != metric) {
|
|
|
cont = rt;
|
|
|
break;
|
|
|
}
|
|
@@ -704,7 +700,7 @@ static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
|
|
|
|
|
|
for (rt = leaf; rt && rt != rr_head;
|
|
|
rt = rcu_dereference(rt->rt6_next)) {
|
|
|
- if (rt->rt6i_metric != metric) {
|
|
|
+ if (rt->fib6_metric != metric) {
|
|
|
cont = rt;
|
|
|
break;
|
|
|
}
|
|
@@ -741,30 +737,30 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
|
|
|
* (This might happen if all routes under fn are deleted from
|
|
|
* the tree and fib6_repair_tree() is called on the node.)
|
|
|
*/
|
|
|
- key_plen = rt0->rt6i_dst.plen;
|
|
|
+ key_plen = rt0->fib6_dst.plen;
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
|
- if (rt0->rt6i_src.plen)
|
|
|
- key_plen = rt0->rt6i_src.plen;
|
|
|
+ if (rt0->fib6_src.plen)
|
|
|
+ key_plen = rt0->fib6_src.plen;
|
|
|
#endif
|
|
|
if (fn->fn_bit != key_plen)
|
|
|
return net->ipv6.fib6_null_entry;
|
|
|
|
|
|
- match = find_rr_leaf(fn, leaf, rt0, rt0->rt6i_metric, oif, strict,
|
|
|
+ match = find_rr_leaf(fn, leaf, rt0, rt0->fib6_metric, oif, strict,
|
|
|
&do_rr);
|
|
|
|
|
|
if (do_rr) {
|
|
|
struct fib6_info *next = rcu_dereference(rt0->rt6_next);
|
|
|
|
|
|
/* no entries matched; do round-robin */
|
|
|
- if (!next || next->rt6i_metric != rt0->rt6i_metric)
|
|
|
+ if (!next || next->fib6_metric != rt0->fib6_metric)
|
|
|
next = leaf;
|
|
|
|
|
|
if (next != rt0) {
|
|
|
- spin_lock_bh(&leaf->rt6i_table->tb6_lock);
|
|
|
+ spin_lock_bh(&leaf->fib6_table->tb6_lock);
|
|
|
/* make sure next is not being deleted from the tree */
|
|
|
- if (next->rt6i_node)
|
|
|
+ if (next->fib6_node)
|
|
|
rcu_assign_pointer(fn->rr_ptr, next);
|
|
|
- spin_unlock_bh(&leaf->rt6i_table->tb6_lock);
|
|
|
+ spin_unlock_bh(&leaf->fib6_table->tb6_lock);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -773,7 +769,7 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
|
|
|
|
|
|
static bool rt6_is_gw_or_nonexthop(const struct fib6_info *rt)
|
|
|
{
|
|
|
- return (rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY));
|
|
|
+ return (rt->fib6_flags & (RTF_NONEXTHOP | RTF_GATEWAY));
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_IPV6_ROUTE_INFO
|
|
@@ -837,8 +833,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
|
|
|
rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr,
|
|
|
dev, pref);
|
|
|
else if (rt)
|
|
|
- rt->rt6i_flags = RTF_ROUTEINFO |
|
|
|
- (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
|
|
|
+ rt->fib6_flags = RTF_ROUTEINFO |
|
|
|
+ (rt->fib6_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
|
|
|
|
|
|
if (rt) {
|
|
|
if (!addrconf_finite_timeout(lifetime))
|
|
@@ -861,13 +857,13 @@ static struct net_device *ip6_rt_get_dev_rcu(struct fib6_info *rt)
|
|
|
{
|
|
|
struct net_device *dev = rt->fib6_nh.nh_dev;
|
|
|
|
|
|
- if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) {
|
|
|
+ if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
|
|
|
/* for copies of local routes, dst->dev needs to be the
|
|
|
* device if it is a master device, the master device if
|
|
|
* device is enslaved, and the loopback as the default
|
|
|
*/
|
|
|
if (netif_is_l3_slave(dev) &&
|
|
|
- !rt6_need_strict(&rt->rt6i_dst.addr))
|
|
|
+ !rt6_need_strict(&rt->fib6_dst.addr))
|
|
|
dev = l3mdev_master_dev_rcu(dev);
|
|
|
else if (!netif_is_l3_master(dev))
|
|
|
dev = dev_net(dev)->loopback_dev;
|
|
@@ -939,7 +935,7 @@ static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
|
|
|
{
|
|
|
rt->dst.flags |= fib6_info_dst_flags(ort);
|
|
|
|
|
|
- if (ort->rt6i_flags & RTF_REJECT) {
|
|
|
+ if (ort->fib6_flags & RTF_REJECT) {
|
|
|
ip6_rt_init_dst_reject(rt, ort);
|
|
|
return;
|
|
|
}
|
|
@@ -949,7 +945,7 @@ static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
|
|
|
|
|
|
if (ort->fib6_type == RTN_LOCAL) {
|
|
|
rt->dst.input = ip6_input;
|
|
|
- } else if (ipv6_addr_type(&ort->rt6i_dst.addr) & IPV6_ADDR_MULTICAST) {
|
|
|
+ } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) {
|
|
|
rt->dst.input = ip6_mc_input;
|
|
|
} else {
|
|
|
rt->dst.input = ip6_forward;
|
|
@@ -977,19 +973,19 @@ static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
|
|
|
|
|
|
static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort)
|
|
|
{
|
|
|
+ struct net_device *dev = fib6_info_nh_dev(ort);
|
|
|
+
|
|
|
ip6_rt_init_dst(rt, ort);
|
|
|
|
|
|
- rt->rt6i_dst = ort->rt6i_dst;
|
|
|
- rt->rt6i_idev = ort->rt6i_idev;
|
|
|
- if (rt->rt6i_idev)
|
|
|
- in6_dev_hold(rt->rt6i_idev);
|
|
|
+ rt->rt6i_dst = ort->fib6_dst;
|
|
|
+ rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
|
|
|
rt->rt6i_gateway = ort->fib6_nh.nh_gw;
|
|
|
- rt->rt6i_flags = ort->rt6i_flags;
|
|
|
+ rt->rt6i_flags = ort->fib6_flags;
|
|
|
rt6_set_from(rt, ort);
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
|
- rt->rt6i_src = ort->rt6i_src;
|
|
|
+ rt->rt6i_src = ort->fib6_src;
|
|
|
#endif
|
|
|
- rt->rt6i_prefsrc = ort->rt6i_prefsrc;
|
|
|
+ rt->rt6i_prefsrc = ort->fib6_prefsrc;
|
|
|
rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.nh_lwtstate);
|
|
|
}
|
|
|
|
|
@@ -1064,7 +1060,7 @@ restart:
|
|
|
} else {
|
|
|
f6i = rt6_device_match(net, f6i, &fl6->saddr,
|
|
|
fl6->flowi6_oif, flags);
|
|
|
- if (f6i->rt6i_nsiblings && fl6->flowi6_oif == 0)
|
|
|
+ if (f6i->fib6_nsiblings && fl6->flowi6_oif == 0)
|
|
|
f6i = rt6_multipath_select(net, f6i, fl6,
|
|
|
fl6->flowi6_oif, skb, flags);
|
|
|
}
|
|
@@ -1142,7 +1138,7 @@ static int __ip6_ins_rt(struct fib6_info *rt, struct nl_info *info,
|
|
|
int err;
|
|
|
struct fib6_table *table;
|
|
|
|
|
|
- table = rt->rt6i_table;
|
|
|
+ table = rt->fib6_table;
|
|
|
spin_lock_bh(&table->tb6_lock);
|
|
|
err = fib6_add(&table->tb6_root, rt, info, extack);
|
|
|
spin_unlock_bh(&table->tb6_lock);
|
|
@@ -1182,8 +1178,8 @@ static struct rt6_info *ip6_rt_cache_alloc(struct fib6_info *ort,
|
|
|
rt->rt6i_dst.plen = 128;
|
|
|
|
|
|
if (!rt6_is_gw_or_nonexthop(ort)) {
|
|
|
- if (ort->rt6i_dst.plen != 128 &&
|
|
|
- ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
|
|
|
+ if (ort->fib6_dst.plen != 128 &&
|
|
|
+ ipv6_addr_equal(&ort->fib6_dst.addr, daddr))
|
|
|
rt->rt6i_flags |= RTF_ANYCAST;
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
|
if (rt->rt6i_src.plen && saddr) {
|
|
@@ -1375,7 +1371,18 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
|
|
|
{
|
|
|
unsigned int mtu;
|
|
|
|
|
|
- mtu = rt->fib6_pmtu ? : rt->rt6i_idev->cnf.mtu6;
|
|
|
+ if (rt->fib6_pmtu) {
|
|
|
+ mtu = rt->fib6_pmtu;
|
|
|
+ } else {
|
|
|
+ struct net_device *dev = fib6_info_nh_dev(rt);
|
|
|
+ struct inet6_dev *idev;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ idev = __in6_dev_get(dev);
|
|
|
+ mtu = idev->cnf.mtu6;
|
|
|
+ rcu_read_unlock();
|
|
|
+ }
|
|
|
+
|
|
|
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
|
|
|
|
|
|
return mtu - lwtunnel_headroom(rt->fib6_nh.nh_lwtstate, mtu);
|
|
@@ -1416,14 +1423,14 @@ static int rt6_insert_exception(struct rt6_info *nrt,
|
|
|
* Otherwise, the exception table is indexed by
|
|
|
* a hash of only rt6i_dst.
|
|
|
*/
|
|
|
- if (ort->rt6i_src.plen)
|
|
|
+ if (ort->fib6_src.plen)
|
|
|
src_key = &nrt->rt6i_src.addr;
|
|
|
#endif
|
|
|
|
|
|
/* Update rt6i_prefsrc as it could be changed
|
|
|
* in rt6_remove_prefsrc()
|
|
|
*/
|
|
|
- nrt->rt6i_prefsrc = ort->rt6i_prefsrc;
|
|
|
+ nrt->rt6i_prefsrc = ort->fib6_prefsrc;
|
|
|
/* rt6_mtu_change() might lower mtu on ort.
|
|
|
* Only insert this exception route if its mtu
|
|
|
* is less than ort's mtu value.
|
|
@@ -1457,9 +1464,9 @@ out:
|
|
|
|
|
|
/* Update fn->fn_sernum to invalidate all cached dst */
|
|
|
if (!err) {
|
|
|
- spin_lock_bh(&ort->rt6i_table->tb6_lock);
|
|
|
+ spin_lock_bh(&ort->fib6_table->tb6_lock);
|
|
|
fib6_update_sernum(net, ort);
|
|
|
- spin_unlock_bh(&ort->rt6i_table->tb6_lock);
|
|
|
+ spin_unlock_bh(&ort->fib6_table->tb6_lock);
|
|
|
fib6_force_start_gc(net);
|
|
|
}
|
|
|
|
|
@@ -1514,7 +1521,7 @@ static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt,
|
|
|
* Otherwise, the exception table is indexed by
|
|
|
* a hash of only rt6i_dst.
|
|
|
*/
|
|
|
- if (rt->rt6i_src.plen)
|
|
|
+ if (rt->fib6_src.plen)
|
|
|
src_key = saddr;
|
|
|
#endif
|
|
|
rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key);
|
|
@@ -1551,7 +1558,7 @@ static int rt6_remove_exception_rt(struct rt6_info *rt)
|
|
|
* Otherwise, the exception table is indexed by
|
|
|
* a hash of only rt6i_dst.
|
|
|
*/
|
|
|
- if (from->rt6i_src.plen)
|
|
|
+ if (from->fib6_src.plen)
|
|
|
src_key = &rt->rt6i_src.addr;
|
|
|
#endif
|
|
|
rt6_ex = __rt6_find_exception_spinlock(&bucket,
|
|
@@ -1592,7 +1599,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
|
|
|
* Otherwise, the exception table is indexed by
|
|
|
* a hash of only rt6i_dst.
|
|
|
*/
|
|
|
- if (from->rt6i_src.plen)
|
|
|
+ if (from->fib6_src.plen)
|
|
|
src_key = &rt->rt6i_src.addr;
|
|
|
#endif
|
|
|
rt6_ex = __rt6_find_exception_rcu(&bucket,
|
|
@@ -1810,7 +1817,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
|
|
|
|
|
redo_rt6_select:
|
|
|
f6i = rt6_select(net, fn, oif, strict);
|
|
|
- if (f6i->rt6i_nsiblings)
|
|
|
+ if (f6i->fib6_nsiblings)
|
|
|
f6i = rt6_multipath_select(net, f6i, fl6, oif, skb, strict);
|
|
|
if (f6i == net->ipv6.fib6_null_entry) {
|
|
|
fn = fib6_backtrack(fn, &fl6->saddr);
|
|
@@ -1842,7 +1849,7 @@ redo_rt6_select:
|
|
|
trace_fib6_table_lookup(net, rt, table, fl6);
|
|
|
return rt;
|
|
|
} else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) &&
|
|
|
- !(f6i->rt6i_flags & RTF_GATEWAY))) {
|
|
|
+ !(f6i->fib6_flags & RTF_GATEWAY))) {
|
|
|
/* Create a RTF_CACHE clone which will not be
|
|
|
* owned by the fib6 tree. It is for the special case where
|
|
|
* the daddr in the skb during the neighbor look-up is different
|
|
@@ -2206,7 +2213,7 @@ static void ip6_link_failure(struct sk_buff *skb)
|
|
|
struct fib6_node *fn;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
- fn = rcu_dereference(rt->from->rt6i_node);
|
|
|
+ fn = rcu_dereference(rt->from->fib6_node);
|
|
|
if (fn && (rt->rt6i_flags & RTF_DEFAULT))
|
|
|
fn->fn_sernum = -1;
|
|
|
rcu_read_unlock();
|
|
@@ -2372,9 +2379,9 @@ restart:
|
|
|
continue;
|
|
|
if (fib6_check_expired(rt))
|
|
|
continue;
|
|
|
- if (rt->rt6i_flags & RTF_REJECT)
|
|
|
+ if (rt->fib6_flags & RTF_REJECT)
|
|
|
break;
|
|
|
- if (!(rt->rt6i_flags & RTF_GATEWAY))
|
|
|
+ if (!(rt->fib6_flags & RTF_GATEWAY))
|
|
|
continue;
|
|
|
if (fl6->flowi6_oif != rt->fib6_nh.nh_dev->ifindex)
|
|
|
continue;
|
|
@@ -2400,7 +2407,7 @@ restart:
|
|
|
|
|
|
if (!rt)
|
|
|
rt = net->ipv6.fib6_null_entry;
|
|
|
- else if (rt->rt6i_flags & RTF_REJECT) {
|
|
|
+ else if (rt->fib6_flags & RTF_REJECT) {
|
|
|
ret = net->ipv6.ip6_null_entry;
|
|
|
goto out;
|
|
|
}
|
|
@@ -2907,7 +2914,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
|
|
|
|
|
if (cfg->fc_protocol == RTPROT_UNSPEC)
|
|
|
cfg->fc_protocol = RTPROT_BOOT;
|
|
|
- rt->rt6i_protocol = cfg->fc_protocol;
|
|
|
+ rt->fib6_protocol = cfg->fc_protocol;
|
|
|
|
|
|
addr_type = ipv6_addr_type(&cfg->fc_dst);
|
|
|
|
|
@@ -2922,17 +2929,17 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
|
|
rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate);
|
|
|
}
|
|
|
|
|
|
- ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
|
|
|
- rt->rt6i_dst.plen = cfg->fc_dst_len;
|
|
|
- if (rt->rt6i_dst.plen == 128)
|
|
|
+ ipv6_addr_prefix(&rt->fib6_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
|
|
|
+ rt->fib6_dst.plen = cfg->fc_dst_len;
|
|
|
+ if (rt->fib6_dst.plen == 128)
|
|
|
rt->dst_host = true;
|
|
|
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
|
- ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
|
|
- rt->rt6i_src.plen = cfg->fc_src_len;
|
|
|
+ ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
|
|
+ rt->fib6_src.plen = cfg->fc_src_len;
|
|
|
#endif
|
|
|
|
|
|
- rt->rt6i_metric = cfg->fc_metric;
|
|
|
+ rt->fib6_metric = cfg->fc_metric;
|
|
|
rt->fib6_nh.nh_weight = 1;
|
|
|
|
|
|
rt->fib6_type = cfg->fc_type;
|
|
@@ -2958,7 +2965,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
|
- rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
|
|
|
+ rt->fib6_flags = RTF_REJECT|RTF_NONEXTHOP;
|
|
|
goto install_route;
|
|
|
}
|
|
|
|
|
@@ -2992,24 +2999,26 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
|
|
err = -EINVAL;
|
|
|
goto out;
|
|
|
}
|
|
|
- rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
|
|
|
- rt->rt6i_prefsrc.plen = 128;
|
|
|
+ rt->fib6_prefsrc.addr = cfg->fc_prefsrc;
|
|
|
+ rt->fib6_prefsrc.plen = 128;
|
|
|
} else
|
|
|
- rt->rt6i_prefsrc.plen = 0;
|
|
|
+ rt->fib6_prefsrc.plen = 0;
|
|
|
|
|
|
- rt->rt6i_flags = cfg->fc_flags;
|
|
|
+ rt->fib6_flags = cfg->fc_flags;
|
|
|
|
|
|
install_route:
|
|
|
- if (!(rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
|
|
|
+ if (!(rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
|
|
|
!netif_carrier_ok(dev))
|
|
|
rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN;
|
|
|
rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
|
|
|
rt->fib6_nh.nh_dev = dev;
|
|
|
- rt->rt6i_idev = idev;
|
|
|
- rt->rt6i_table = table;
|
|
|
+ rt->fib6_table = table;
|
|
|
|
|
|
cfg->fc_nlinfo.nl_net = dev_net(dev);
|
|
|
|
|
|
+ if (idev)
|
|
|
+ in6_dev_put(idev);
|
|
|
+
|
|
|
return rt;
|
|
|
out:
|
|
|
if (dev)
|
|
@@ -3048,7 +3057,7 @@ static int __ip6_del_rt(struct fib6_info *rt, struct nl_info *info)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- table = rt->rt6i_table;
|
|
|
+ table = rt->fib6_table;
|
|
|
spin_lock_bh(&table->tb6_lock);
|
|
|
err = fib6_del(rt, info);
|
|
|
spin_unlock_bh(&table->tb6_lock);
|
|
@@ -3075,10 +3084,10 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
|
|
|
|
|
|
if (rt == net->ipv6.fib6_null_entry)
|
|
|
goto out_put;
|
|
|
- table = rt->rt6i_table;
|
|
|
+ table = rt->fib6_table;
|
|
|
spin_lock_bh(&table->tb6_lock);
|
|
|
|
|
|
- if (rt->rt6i_nsiblings && cfg->fc_delete_all_nh) {
|
|
|
+ if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) {
|
|
|
struct fib6_info *sibling, *next_sibling;
|
|
|
|
|
|
/* prefer to send a single notification with all hops */
|
|
@@ -3096,8 +3105,8 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
|
|
|
}
|
|
|
|
|
|
list_for_each_entry_safe(sibling, next_sibling,
|
|
|
- &rt->rt6i_siblings,
|
|
|
- rt6i_siblings) {
|
|
|
+ &rt->fib6_siblings,
|
|
|
+ fib6_siblings) {
|
|
|
err = fib6_del(sibling, info);
|
|
|
if (err)
|
|
|
goto out_unlock;
|
|
@@ -3176,9 +3185,9 @@ static int ip6_route_del(struct fib6_config *cfg,
|
|
|
if (cfg->fc_flags & RTF_GATEWAY &&
|
|
|
!ipv6_addr_equal(&cfg->fc_gateway, &rt->fib6_nh.nh_gw))
|
|
|
continue;
|
|
|
- if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
|
|
|
+ if (cfg->fc_metric && cfg->fc_metric != rt->fib6_metric)
|
|
|
continue;
|
|
|
- if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol)
|
|
|
+ if (cfg->fc_protocol && cfg->fc_protocol != rt->fib6_protocol)
|
|
|
continue;
|
|
|
fib6_info_hold(rt);
|
|
|
rcu_read_unlock();
|
|
@@ -3336,7 +3345,7 @@ static struct fib6_info *rt6_get_route_info(struct net *net,
|
|
|
for_each_fib6_node_rt_rcu(fn) {
|
|
|
if (rt->fib6_nh.nh_dev->ifindex != ifindex)
|
|
|
continue;
|
|
|
- if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
|
|
|
+ if ((rt->fib6_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
|
|
|
continue;
|
|
|
if (!ipv6_addr_equal(&rt->fib6_nh.nh_gw, gwaddr))
|
|
|
continue;
|
|
@@ -3396,7 +3405,7 @@ struct fib6_info *rt6_get_dflt_router(struct net *net,
|
|
|
rcu_read_lock();
|
|
|
for_each_fib6_node_rt_rcu(&table->tb6_root) {
|
|
|
if (dev == rt->fib6_nh.nh_dev &&
|
|
|
- ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
|
|
|
+ ((rt->fib6_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
|
|
|
ipv6_addr_equal(&rt->fib6_nh.nh_gw, addr))
|
|
|
break;
|
|
|
}
|
|
@@ -3445,8 +3454,11 @@ static void __rt6_purge_dflt_routers(struct net *net,
|
|
|
restart:
|
|
|
rcu_read_lock();
|
|
|
for_each_fib6_node_rt_rcu(&table->tb6_root) {
|
|
|
- if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
|
|
|
- (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
|
|
|
+ struct net_device *dev = fib6_info_nh_dev(rt);
|
|
|
+ struct inet6_dev *idev = dev ? __in6_dev_get(dev) : NULL;
|
|
|
+
|
|
|
+ if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
|
|
|
+ (!idev || idev->cnf.accept_ra != 2)) {
|
|
|
fib6_info_hold(rt);
|
|
|
rcu_read_unlock();
|
|
|
ip6_del_rt(net, rt);
|
|
@@ -3591,44 +3603,40 @@ static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff
|
|
|
* Allocate a dst for local (unicast / anycast) address.
|
|
|
*/
|
|
|
|
|
|
-struct fib6_info *addrconf_dst_alloc(struct net *net,
|
|
|
- struct inet6_dev *idev,
|
|
|
- const struct in6_addr *addr,
|
|
|
- bool anycast, gfp_t gfp_flags)
|
|
|
+struct fib6_info *addrconf_f6i_alloc(struct net *net,
|
|
|
+ struct inet6_dev *idev,
|
|
|
+ const struct in6_addr *addr,
|
|
|
+ bool anycast, gfp_t gfp_flags)
|
|
|
{
|
|
|
u32 tb_id;
|
|
|
struct net_device *dev = idev->dev;
|
|
|
- struct fib6_info *rt;
|
|
|
+ struct fib6_info *f6i;
|
|
|
|
|
|
- rt = fib6_info_alloc(gfp_flags);
|
|
|
- if (!rt)
|
|
|
+ f6i = fib6_info_alloc(gfp_flags);
|
|
|
+ if (!f6i)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
- rt->dst_nocount = true;
|
|
|
-
|
|
|
- in6_dev_hold(idev);
|
|
|
- rt->rt6i_idev = idev;
|
|
|
-
|
|
|
- rt->dst_host = true;
|
|
|
- rt->rt6i_protocol = RTPROT_KERNEL;
|
|
|
- rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
|
|
|
+ f6i->dst_nocount = true;
|
|
|
+ f6i->dst_host = true;
|
|
|
+ f6i->fib6_protocol = RTPROT_KERNEL;
|
|
|
+ f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP;
|
|
|
if (anycast) {
|
|
|
- rt->fib6_type = RTN_ANYCAST;
|
|
|
- rt->rt6i_flags |= RTF_ANYCAST;
|
|
|
+ f6i->fib6_type = RTN_ANYCAST;
|
|
|
+ f6i->fib6_flags |= RTF_ANYCAST;
|
|
|
} else {
|
|
|
- rt->fib6_type = RTN_LOCAL;
|
|
|
- rt->rt6i_flags |= RTF_LOCAL;
|
|
|
+ f6i->fib6_type = RTN_LOCAL;
|
|
|
+ f6i->fib6_flags |= RTF_LOCAL;
|
|
|
}
|
|
|
|
|
|
- rt->fib6_nh.nh_gw = *addr;
|
|
|
+ f6i->fib6_nh.nh_gw = *addr;
|
|
|
dev_hold(dev);
|
|
|
- rt->fib6_nh.nh_dev = dev;
|
|
|
- rt->rt6i_dst.addr = *addr;
|
|
|
- rt->rt6i_dst.plen = 128;
|
|
|
+ f6i->fib6_nh.nh_dev = dev;
|
|
|
+ f6i->fib6_dst.addr = *addr;
|
|
|
+ f6i->fib6_dst.plen = 128;
|
|
|
tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL;
|
|
|
- rt->rt6i_table = fib6_get_table(net, tb_id);
|
|
|
+ f6i->fib6_table = fib6_get_table(net, tb_id);
|
|
|
|
|
|
- return rt;
|
|
|
+ return f6i;
|
|
|
}
|
|
|
|
|
|
/* remove deleted ip from prefsrc entries */
|
|
@@ -3646,10 +3654,10 @@ static int fib6_remove_prefsrc(struct fib6_info *rt, void *arg)
|
|
|
|
|
|
if (((void *)rt->fib6_nh.nh_dev == dev || !dev) &&
|
|
|
rt != net->ipv6.fib6_null_entry &&
|
|
|
- ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
|
|
|
+ ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) {
|
|
|
spin_lock_bh(&rt6_exception_lock);
|
|
|
/* remove prefsrc entry */
|
|
|
- rt->rt6i_prefsrc.plen = 0;
|
|
|
+ rt->fib6_prefsrc.plen = 0;
|
|
|
/* need to update cache as well */
|
|
|
rt6_exceptions_remove_prefsrc(rt);
|
|
|
spin_unlock_bh(&rt6_exception_lock);
|
|
@@ -3675,7 +3683,7 @@ static int fib6_clean_tohost(struct fib6_info *rt, void *arg)
|
|
|
{
|
|
|
struct in6_addr *gateway = (struct in6_addr *)arg;
|
|
|
|
|
|
- if (((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) &&
|
|
|
+ if (((rt->fib6_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) &&
|
|
|
ipv6_addr_equal(gateway, &rt->fib6_nh.nh_gw)) {
|
|
|
return -1;
|
|
|
}
|
|
@@ -3707,16 +3715,16 @@ static struct fib6_info *rt6_multipath_first_sibling(const struct fib6_info *rt)
|
|
|
struct fib6_info *iter;
|
|
|
struct fib6_node *fn;
|
|
|
|
|
|
- fn = rcu_dereference_protected(rt->rt6i_node,
|
|
|
- lockdep_is_held(&rt->rt6i_table->tb6_lock));
|
|
|
+ fn = rcu_dereference_protected(rt->fib6_node,
|
|
|
+ lockdep_is_held(&rt->fib6_table->tb6_lock));
|
|
|
iter = rcu_dereference_protected(fn->leaf,
|
|
|
- lockdep_is_held(&rt->rt6i_table->tb6_lock));
|
|
|
+ lockdep_is_held(&rt->fib6_table->tb6_lock));
|
|
|
while (iter) {
|
|
|
- if (iter->rt6i_metric == rt->rt6i_metric &&
|
|
|
+ if (iter->fib6_metric == rt->fib6_metric &&
|
|
|
rt6_qualify_for_ecmp(iter))
|
|
|
return iter;
|
|
|
iter = rcu_dereference_protected(iter->rt6_next,
|
|
|
- lockdep_is_held(&rt->rt6i_table->tb6_lock));
|
|
|
+ lockdep_is_held(&rt->fib6_table->tb6_lock));
|
|
|
}
|
|
|
|
|
|
return NULL;
|
|
@@ -3726,7 +3734,7 @@ static bool rt6_is_dead(const struct fib6_info *rt)
|
|
|
{
|
|
|
if (rt->fib6_nh.nh_flags & RTNH_F_DEAD ||
|
|
|
(rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
|
|
|
- rt->rt6i_idev->cnf.ignore_routes_with_linkdown))
|
|
|
+ fib6_ignore_linkdown(rt)))
|
|
|
return true;
|
|
|
|
|
|
return false;
|
|
@@ -3740,7 +3748,7 @@ static int rt6_multipath_total_weight(const struct fib6_info *rt)
|
|
|
if (!rt6_is_dead(rt))
|
|
|
total += rt->fib6_nh.nh_weight;
|
|
|
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
|
|
|
if (!rt6_is_dead(iter))
|
|
|
total += iter->fib6_nh.nh_weight;
|
|
|
}
|
|
@@ -3767,7 +3775,7 @@ static void rt6_multipath_upper_bound_set(struct fib6_info *rt, int total)
|
|
|
|
|
|
rt6_upper_bound_set(rt, &weight, total);
|
|
|
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
|
|
|
rt6_upper_bound_set(iter, &weight, total);
|
|
|
}
|
|
|
|
|
@@ -3780,7 +3788,7 @@ void rt6_multipath_rebalance(struct fib6_info *rt)
|
|
|
* then there is no need to rebalance upon the removal of every
|
|
|
* sibling route.
|
|
|
*/
|
|
|
- if (!rt->rt6i_nsiblings || rt->should_flush)
|
|
|
+ if (!rt->fib6_nsiblings || rt->should_flush)
|
|
|
return;
|
|
|
|
|
|
/* During lookup routes are evaluated in order, so we need to
|
|
@@ -3831,7 +3839,7 @@ static bool rt6_multipath_uses_dev(const struct fib6_info *rt,
|
|
|
|
|
|
if (rt->fib6_nh.nh_dev == dev)
|
|
|
return true;
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
|
|
|
if (iter->fib6_nh.nh_dev == dev)
|
|
|
return true;
|
|
|
|
|
@@ -3843,7 +3851,7 @@ static void rt6_multipath_flush(struct fib6_info *rt)
|
|
|
struct fib6_info *iter;
|
|
|
|
|
|
rt->should_flush = 1;
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
|
|
|
iter->should_flush = 1;
|
|
|
}
|
|
|
|
|
@@ -3856,7 +3864,7 @@ static unsigned int rt6_multipath_dead_count(const struct fib6_info *rt,
|
|
|
if (rt->fib6_nh.nh_dev == down_dev ||
|
|
|
rt->fib6_nh.nh_flags & RTNH_F_DEAD)
|
|
|
dead++;
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
|
|
|
if (iter->fib6_nh.nh_dev == down_dev ||
|
|
|
iter->fib6_nh.nh_flags & RTNH_F_DEAD)
|
|
|
dead++;
|
|
@@ -3872,7 +3880,7 @@ static void rt6_multipath_nh_flags_set(struct fib6_info *rt,
|
|
|
|
|
|
if (rt->fib6_nh.nh_dev == dev)
|
|
|
rt->fib6_nh.nh_flags |= nh_flags;
|
|
|
- list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings)
|
|
|
+ list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings)
|
|
|
if (iter->fib6_nh.nh_dev == dev)
|
|
|
iter->fib6_nh.nh_flags |= nh_flags;
|
|
|
}
|
|
@@ -3893,13 +3901,13 @@ static int fib6_ifdown(struct fib6_info *rt, void *p_arg)
|
|
|
case NETDEV_DOWN:
|
|
|
if (rt->should_flush)
|
|
|
return -1;
|
|
|
- if (!rt->rt6i_nsiblings)
|
|
|
+ if (!rt->fib6_nsiblings)
|
|
|
return rt->fib6_nh.nh_dev == dev ? -1 : 0;
|
|
|
if (rt6_multipath_uses_dev(rt, dev)) {
|
|
|
unsigned int count;
|
|
|
|
|
|
count = rt6_multipath_dead_count(rt, dev);
|
|
|
- if (rt->rt6i_nsiblings + 1 == count) {
|
|
|
+ if (rt->fib6_nsiblings + 1 == count) {
|
|
|
rt6_multipath_flush(rt);
|
|
|
return -1;
|
|
|
}
|
|
@@ -3911,7 +3919,7 @@ static int fib6_ifdown(struct fib6_info *rt, void *p_arg)
|
|
|
return -2;
|
|
|
case NETDEV_CHANGE:
|
|
|
if (rt->fib6_nh.nh_dev != dev ||
|
|
|
- rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
|
|
|
+ rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
|
|
|
break;
|
|
|
rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN;
|
|
|
rt6_multipath_rebalance(rt);
|
|
@@ -4188,10 +4196,10 @@ static void ip6_route_mpath_notify(struct fib6_info *rt,
|
|
|
* nexthop. Since sibling routes are always added at the end of
|
|
|
* the list, find the first sibling of the last route appended
|
|
|
*/
|
|
|
- if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->rt6i_nsiblings) {
|
|
|
- rt = list_first_entry(&rt_last->rt6i_siblings,
|
|
|
+ if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->fib6_nsiblings) {
|
|
|
+ rt = list_first_entry(&rt_last->fib6_siblings,
|
|
|
struct fib6_info,
|
|
|
- rt6i_siblings);
|
|
|
+ fib6_siblings);
|
|
|
}
|
|
|
|
|
|
if (rt)
|
|
@@ -4410,13 +4418,13 @@ static size_t rt6_nlmsg_size(struct fib6_info *rt)
|
|
|
{
|
|
|
int nexthop_len = 0;
|
|
|
|
|
|
- if (rt->rt6i_nsiblings) {
|
|
|
+ if (rt->fib6_nsiblings) {
|
|
|
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.nh_lwtstate);
|
|
|
|
|
|
- nexthop_len *= rt->rt6i_nsiblings;
|
|
|
+ nexthop_len *= rt->fib6_nsiblings;
|
|
|
}
|
|
|
|
|
|
return NLMSG_ALIGN(sizeof(struct rtmsg))
|
|
@@ -4444,11 +4452,14 @@ static int rt6_nexthop_info(struct sk_buff *skb, struct fib6_info *rt,
|
|
|
|
|
|
if (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN) {
|
|
|
*flags |= RTNH_F_LINKDOWN;
|
|
|
- if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ if (fib6_ignore_linkdown(rt))
|
|
|
*flags |= RTNH_F_DEAD;
|
|
|
+ rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
- if (rt->rt6i_flags & RTF_GATEWAY) {
|
|
|
+ if (rt->fib6_flags & RTF_GATEWAY) {
|
|
|
if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->fib6_nh.nh_gw) < 0)
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
@@ -4518,11 +4529,11 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
|
|
|
rtm = nlmsg_data(nlh);
|
|
|
rtm->rtm_family = AF_INET6;
|
|
|
- rtm->rtm_dst_len = rt->rt6i_dst.plen;
|
|
|
- rtm->rtm_src_len = rt->rt6i_src.plen;
|
|
|
+ rtm->rtm_dst_len = rt->fib6_dst.plen;
|
|
|
+ rtm->rtm_src_len = rt->fib6_src.plen;
|
|
|
rtm->rtm_tos = 0;
|
|
|
- if (rt->rt6i_table)
|
|
|
- table = rt->rt6i_table->tb6_id;
|
|
|
+ if (rt->fib6_table)
|
|
|
+ table = rt->fib6_table->tb6_id;
|
|
|
else
|
|
|
table = RT6_TABLE_UNSPEC;
|
|
|
rtm->rtm_table = table;
|
|
@@ -4532,9 +4543,9 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
rtm->rtm_type = rt->fib6_type;
|
|
|
rtm->rtm_flags = 0;
|
|
|
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
|
|
|
- rtm->rtm_protocol = rt->rt6i_protocol;
|
|
|
+ rtm->rtm_protocol = rt->fib6_protocol;
|
|
|
|
|
|
- if (rt->rt6i_flags & RTF_CACHE)
|
|
|
+ if (rt->fib6_flags & RTF_CACHE)
|
|
|
rtm->rtm_flags |= RTM_F_CLONED;
|
|
|
|
|
|
if (dest) {
|
|
@@ -4542,7 +4553,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
goto nla_put_failure;
|
|
|
rtm->rtm_dst_len = 128;
|
|
|
} else if (rtm->rtm_dst_len)
|
|
|
- if (nla_put_in6_addr(skb, RTA_DST, &rt->rt6i_dst.addr))
|
|
|
+ if (nla_put_in6_addr(skb, RTA_DST, &rt->fib6_dst.addr))
|
|
|
goto nla_put_failure;
|
|
|
#ifdef CONFIG_IPV6_SUBTREES
|
|
|
if (src) {
|
|
@@ -4550,12 +4561,12 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
goto nla_put_failure;
|
|
|
rtm->rtm_src_len = 128;
|
|
|
} else if (rtm->rtm_src_len &&
|
|
|
- nla_put_in6_addr(skb, RTA_SRC, &rt->rt6i_src.addr))
|
|
|
+ nla_put_in6_addr(skb, RTA_SRC, &rt->fib6_src.addr))
|
|
|
goto nla_put_failure;
|
|
|
#endif
|
|
|
if (iif) {
|
|
|
#ifdef CONFIG_IPV6_MROUTE
|
|
|
- if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
|
|
|
+ if (ipv6_addr_is_multicast(&rt->fib6_dst.addr)) {
|
|
|
int err = ip6mr_get_route(net, skb, rtm, portid);
|
|
|
|
|
|
if (err == 0)
|
|
@@ -4573,9 +4584,9 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
|
|
|
|
- if (rt->rt6i_prefsrc.plen) {
|
|
|
+ if (rt->fib6_prefsrc.plen) {
|
|
|
struct in6_addr saddr_buf;
|
|
|
- saddr_buf = rt->rt6i_prefsrc.addr;
|
|
|
+ saddr_buf = rt->fib6_prefsrc.addr;
|
|
|
if (nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
@@ -4584,13 +4595,13 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
if (rtnetlink_put_metrics(skb, pmetrics) < 0)
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
- if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric))
|
|
|
+ if (nla_put_u32(skb, RTA_PRIORITY, rt->fib6_metric))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
/* For multipath routes, walk the siblings list and add
|
|
|
* each as a nexthop within RTA_MULTIPATH.
|
|
|
*/
|
|
|
- if (rt->rt6i_nsiblings) {
|
|
|
+ if (rt->fib6_nsiblings) {
|
|
|
struct fib6_info *sibling, *next_sibling;
|
|
|
struct nlattr *mp;
|
|
|
|
|
@@ -4602,7 +4613,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
list_for_each_entry_safe(sibling, next_sibling,
|
|
|
- &rt->rt6i_siblings, rt6i_siblings) {
|
|
|
+ &rt->fib6_siblings, fib6_siblings) {
|
|
|
if (rt6_add_nexthop(skb, sibling) < 0)
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
@@ -4613,7 +4624,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
|
|
|
|
- if (rt->rt6i_flags & RTF_EXPIRES) {
|
|
|
+ if (rt->fib6_flags & RTF_EXPIRES) {
|
|
|
expires = dst ? dst->expires : rt->expires;
|
|
|
expires -= jiffies;
|
|
|
}
|
|
@@ -4621,7 +4632,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
|
if (rtnl_put_cacheinfo(skb, dst, 0, expires, dst ? dst->error : 0) < 0)
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
- if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
|
|
|
+ if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->fib6_flags)))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
@@ -4646,7 +4657,7 @@ int rt6_dump_route(struct fib6_info *rt, void *p_arg)
|
|
|
|
|
|
/* user wants prefix routes only */
|
|
|
if (rtm->rtm_flags & RTM_F_PREFIX &&
|
|
|
- !(rt->rt6i_flags & RTF_PREFIX_RT)) {
|
|
|
+ !(rt->fib6_flags & RTF_PREFIX_RT)) {
|
|
|
/* success since this is not a prefix route */
|
|
|
return 1;
|
|
|
}
|
|
@@ -4820,7 +4831,6 @@ static int ip6_route_dev_notify(struct notifier_block *this,
|
|
|
|
|
|
if (event == NETDEV_REGISTER) {
|
|
|
net->ipv6.fib6_null_entry->fib6_nh.nh_dev = dev;
|
|
|
- net->ipv6.fib6_null_entry->rt6i_idev = in6_dev_get(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
|
|
@@ -4834,7 +4844,6 @@ static int ip6_route_dev_notify(struct notifier_block *this,
|
|
|
/* NETDEV_UNREGISTER could be fired for multiple times by
|
|
|
* netdev_wait_allrefs(). Make sure we only call this once.
|
|
|
*/
|
|
|
- in6_dev_put_clear(&net->ipv6.fib6_null_entry->rt6i_idev);
|
|
|
in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
|
|
|
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
|
in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
|
|
@@ -5157,7 +5166,6 @@ void __init ip6_route_init_special_entries(void)
|
|
|
* the loopback reference in rt6_info will not be taken, do it
|
|
|
* manually for init_net */
|
|
|
init_net.ipv6.fib6_null_entry->fib6_nh.nh_dev = init_net.loopback_dev;
|
|
|
- init_net.ipv6.fib6_null_entry->rt6i_idev = in6_dev_get(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
|