Lines Matching +full:route +full:- +full:ptp
3 * FIB front-end.
18 * - respect outgoing interface
19 * - select from (probably) reachable routers (i.e.
21 * - always select the same router if it is (probably)
22 * reachable. otherwise, round-robin the list.
37 #include <linux/route.h>
81 RT6_NUD_FAIL_HARD = -3,
82 RT6_NUD_FAIL_PROBE = -2,
83 RT6_NUD_FAIL_DO_RR = -1,
140 rt->rt6i_uncached_list = ul; in rt6_uncached_list_add()
142 spin_lock_bh(&ul->lock); in rt6_uncached_list_add()
143 list_add_tail(&rt->rt6i_uncached, &ul->head); in rt6_uncached_list_add()
144 spin_unlock_bh(&ul->lock); in rt6_uncached_list_add()
149 if (!list_empty(&rt->rt6i_uncached)) { in rt6_uncached_list_del()
150 struct uncached_list *ul = rt->rt6i_uncached_list; in rt6_uncached_list_del()
151 struct net *net = dev_net(rt->dst.dev); in rt6_uncached_list_del()
153 spin_lock_bh(&ul->lock); in rt6_uncached_list_del()
154 list_del(&rt->rt6i_uncached); in rt6_uncached_list_del()
155 atomic_dec(&net->ipv6.rt6_stats->fib_rt_uncache); in rt6_uncached_list_del()
156 spin_unlock_bh(&ul->lock); in rt6_uncached_list_del()
162 struct net_device *loopback_dev = net->loopback_dev; in rt6_uncached_list_flush_dev()
172 spin_lock_bh(&ul->lock); in rt6_uncached_list_flush_dev()
173 list_for_each_entry(rt, &ul->head, rt6i_uncached) { in rt6_uncached_list_flush_dev()
174 struct inet6_dev *rt_idev = rt->rt6i_idev; in rt6_uncached_list_flush_dev()
175 struct net_device *rt_dev = rt->dst.dev; in rt6_uncached_list_flush_dev()
177 if (rt_idev->dev == dev) { in rt6_uncached_list_flush_dev()
178 rt->rt6i_idev = in6_dev_get(loopback_dev); in rt6_uncached_list_flush_dev()
183 rt->dst.dev = loopback_dev; in rt6_uncached_list_flush_dev()
184 dev_hold(rt->dst.dev); in rt6_uncached_list_flush_dev()
188 spin_unlock_bh(&ul->lock); in rt6_uncached_list_flush_dev()
199 return &ipv6_hdr(skb)->daddr; in choose_neigh_daddr()
225 return ip6_neigh_lookup(&rt->rt6i_gateway, dst->dev, skb, daddr); in ip6_dst_neigh_lookup()
230 struct net_device *dev = dst->dev; in ip6_confirm_neigh()
233 daddr = choose_neigh_daddr(&rt->rt6i_gateway, NULL, daddr); in ip6_confirm_neigh()
236 if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) in ip6_confirm_neigh()
266 return mtu ? : dst->dev->mtu; in ip6_blackhole_mtu()
293 [RTAX_HOPLIMIT - 1] = 0,
310 .error = -ENETUNREACH,
324 .error = -EACCES,
336 .error = -EINVAL,
347 struct dst_entry *dst = &rt->dst; in rt6_info_init()
349 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); in rt6_info_init()
350 INIT_LIST_HEAD(&rt->rt6i_uncached); in rt6_info_init()
357 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, in ip6_dst_alloc()
362 atomic_inc(&net->ipv6.rt6_stats->fib_rt_alloc); in ip6_dst_alloc()
376 if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) in ip6_dst_destroy()
381 idev = rt->rt6i_idev; in ip6_dst_destroy()
383 rt->rt6i_idev = NULL; in ip6_dst_destroy()
387 from = xchg((__force struct fib6_info **)&rt->from, NULL); in ip6_dst_destroy()
395 struct inet6_dev *idev = rt->rt6i_idev; in ip6_dst_ifdown()
397 dev_net(dev)->loopback_dev; in ip6_dst_ifdown()
399 if (idev && idev->dev != loopback_dev) { in ip6_dst_ifdown()
402 rt->rt6i_idev = loopback_idev; in ip6_dst_ifdown()
410 if (rt->rt6i_flags & RTF_EXPIRES) in __rt6_check_expired()
411 return time_after(jiffies, rt->dst.expires); in __rt6_check_expired()
420 from = rcu_dereference(rt->from); in rt6_check_expired()
422 if (rt->rt6i_flags & RTF_EXPIRES) { in rt6_check_expired()
423 if (time_after(jiffies, rt->dst.expires)) in rt6_check_expired()
426 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK || in rt6_check_expired()
441 * case it will always be non-zero. Otherwise now is the time to do it. in fib6_multipath_select()
443 if (!fl6->mp_hash) in fib6_multipath_select()
444 fl6->mp_hash = rt6_multipath_hash(net, fl6, skb, NULL); in fib6_multipath_select()
446 if (fl6->mp_hash <= atomic_read(&match->fib6_nh.nh_upper_bound)) in fib6_multipath_select()
449 list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings, in fib6_multipath_select()
453 nh_upper_bound = atomic_read(&sibling->fib6_nh.nh_upper_bound); in fib6_multipath_select()
454 if (fl6->mp_hash > nh_upper_bound) in fib6_multipath_select()
466 * Route lookup. rcu_read_lock() should be held.
478 !(rt->fib6_nh.nh_flags & RTNH_F_DEAD)) in rt6_device_match()
481 for (sprt = rt; sprt; sprt = rcu_dereference(sprt->fib6_next)) { in rt6_device_match()
482 const struct net_device *dev = sprt->fib6_nh.nh_dev; in rt6_device_match()
484 if (sprt->fib6_nh.nh_flags & RTNH_F_DEAD) in rt6_device_match()
488 if (dev->ifindex == oif) in rt6_device_match()
498 return net->ipv6.fib6_null_entry; in rt6_device_match()
500 return rt->fib6_nh.nh_flags & RTNH_F_DEAD ? net->ipv6.fib6_null_entry : rt; in rt6_device_match()
516 addrconf_addr_solict_mult(&work->target, &mcaddr); in rt6_probe_deferred()
517 ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, 0); in rt6_probe_deferred()
518 dev_put(work->dev); in rt6_probe_deferred()
536 * Router Reachability Probe MUST be rate-limited in rt6_probe()
539 if (!rt || !(rt->fib6_flags & RTF_GATEWAY)) in rt6_probe()
542 nh_gw = &rt->fib6_nh.nh_gw; in rt6_probe()
543 dev = rt->fib6_nh.nh_dev; in rt6_probe()
545 last_probe = READ_ONCE(rt->last_probe); in rt6_probe()
549 if (neigh->nud_state & NUD_VALID) in rt6_probe()
552 write_lock(&neigh->lock); in rt6_probe()
553 if (!(neigh->nud_state & NUD_VALID) && in rt6_probe()
555 neigh->updated + idev->cnf.rtr_probe_interval)) { in rt6_probe()
560 write_unlock(&neigh->lock); in rt6_probe()
562 idev->cnf.rtr_probe_interval)) { in rt6_probe()
566 if (!work || cmpxchg(&rt->last_probe, in rt6_probe()
570 INIT_WORK(&work->work, rt6_probe_deferred); in rt6_probe()
571 work->target = *nh_gw; in rt6_probe()
573 work->dev = dev; in rt6_probe()
574 schedule_work(&work->work); in rt6_probe()
591 const struct net_device *dev = rt->fib6_nh.nh_dev; in rt6_check_dev()
593 if (!oif || dev->ifindex == oif) in rt6_check_dev()
603 if (rt->fib6_flags & RTF_NONEXTHOP || in rt6_check_neigh()
604 !(rt->fib6_flags & RTF_GATEWAY)) in rt6_check_neigh()
608 neigh = __ipv6_neigh_lookup_noref(rt->fib6_nh.nh_dev, in rt6_check_neigh()
609 &rt->fib6_nh.nh_gw); in rt6_check_neigh()
611 read_lock(&neigh->lock); in rt6_check_neigh()
612 if (neigh->nud_state & NUD_VALID) in rt6_check_neigh()
615 else if (!(neigh->nud_state & NUD_FAILED)) in rt6_check_neigh()
620 read_unlock(&neigh->lock); in rt6_check_neigh()
638 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->fib6_flags)) << 2; in rt6_score_route()
657 rc = !!idev->cnf.ignore_routes_with_linkdown; in fib6_ignore_linkdown()
670 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD) in find_match()
674 rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN && in find_match()
709 int mpri = -1; in find_rr_leaf()
713 for (rt = rr_head; rt; rt = rcu_dereference(rt->fib6_next)) { in find_rr_leaf()
714 if (rt->fib6_metric != metric) { in find_rr_leaf()
723 rt = rcu_dereference(rt->fib6_next)) { in find_rr_leaf()
724 if (rt->fib6_metric != metric) { in find_rr_leaf()
735 for (rt = cont; rt; rt = rcu_dereference(rt->fib6_next)) in find_rr_leaf()
744 struct fib6_info *leaf = rcu_dereference(fn->leaf); in rt6_select()
749 if (!leaf || leaf == net->ipv6.fib6_null_entry) in rt6_select()
750 return net->ipv6.fib6_null_entry; in rt6_select()
752 rt0 = rcu_dereference(fn->rr_ptr); in rt6_select()
757 * and fn->leaf does not points to its child's leaf in rt6_select()
761 key_plen = rt0->fib6_dst.plen; in rt6_select()
763 if (rt0->fib6_src.plen) in rt6_select()
764 key_plen = rt0->fib6_src.plen; in rt6_select()
766 if (fn->fn_bit != key_plen) in rt6_select()
767 return net->ipv6.fib6_null_entry; in rt6_select()
769 match = find_rr_leaf(fn, leaf, rt0, rt0->fib6_metric, oif, strict, in rt6_select()
773 struct fib6_info *next = rcu_dereference(rt0->fib6_next); in rt6_select()
775 /* no entries matched; do round-robin */ in rt6_select()
776 if (!next || next->fib6_metric != rt0->fib6_metric) in rt6_select()
780 spin_lock_bh(&leaf->fib6_table->tb6_lock); in rt6_select()
782 if (next->fib6_node) in rt6_select()
783 rcu_assign_pointer(fn->rr_ptr, next); in rt6_select()
784 spin_unlock_bh(&leaf->fib6_table->tb6_lock); in rt6_select()
788 return match ? match : net->ipv6.fib6_null_entry; in rt6_select()
793 return (rt->fib6_flags & (RTF_NONEXTHOP | RTF_GATEWAY)); in rt6_is_gw_or_nonexthop()
808 return -EINVAL; in rt6_route_rcv()
812 if (rinfo->length > 3) { in rt6_route_rcv()
813 return -EINVAL; in rt6_route_rcv()
814 } else if (rinfo->prefix_len > 128) { in rt6_route_rcv()
815 return -EINVAL; in rt6_route_rcv()
816 } else if (rinfo->prefix_len > 64) { in rt6_route_rcv()
817 if (rinfo->length < 2) { in rt6_route_rcv()
818 return -EINVAL; in rt6_route_rcv()
820 } else if (rinfo->prefix_len > 0) { in rt6_route_rcv()
821 if (rinfo->length < 1) { in rt6_route_rcv()
822 return -EINVAL; in rt6_route_rcv()
826 pref = rinfo->route_pref; in rt6_route_rcv()
828 return -EINVAL; in rt6_route_rcv()
830 lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ); in rt6_route_rcv()
832 if (rinfo->length == 3) in rt6_route_rcv()
833 prefix = (struct in6_addr *)rinfo->prefix; in rt6_route_rcv()
837 (struct in6_addr *)rinfo->prefix, in rt6_route_rcv()
838 rinfo->prefix_len); in rt6_route_rcv()
842 if (rinfo->prefix_len == 0) in rt6_route_rcv()
845 rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, in rt6_route_rcv()
854 rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, in rt6_route_rcv()
857 rt->fib6_flags = RTF_ROUTEINFO | in rt6_route_rcv()
858 (rt->fib6_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); in rt6_route_rcv()
879 struct net_device *dev = rt->fib6_nh.nh_dev; in ip6_rt_get_dev_rcu()
881 if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) { in ip6_rt_get_dev_rcu()
882 /* for copies of local routes, dst->dev needs to be the in ip6_rt_get_dev_rcu()
887 !rt6_need_strict(&rt->fib6_dst.addr)) in ip6_rt_get_dev_rcu()
890 dev = dev_net(dev)->loopback_dev; in ip6_rt_get_dev_rcu()
906 [RTN_BLACKHOLE] = -EINVAL,
907 [RTN_UNREACHABLE] = -EHOSTUNREACH,
908 [RTN_PROHIBIT] = -EACCES,
909 [RTN_THROW] = -EAGAIN,
910 [RTN_NAT] = -EINVAL,
911 [RTN_XRESOLVE] = -EINVAL,
923 if (rt->dst_nocount) in fib6_info_dst_flags()
925 if (rt->dst_nopolicy) in fib6_info_dst_flags()
927 if (rt->dst_host) in fib6_info_dst_flags()
935 rt->dst.error = ip6_rt_type_to_error(ort->fib6_type); in ip6_rt_init_dst_reject()
937 switch (ort->fib6_type) { in ip6_rt_init_dst_reject()
939 rt->dst.output = dst_discard_out; in ip6_rt_init_dst_reject()
940 rt->dst.input = dst_discard; in ip6_rt_init_dst_reject()
943 rt->dst.output = ip6_pkt_prohibit_out; in ip6_rt_init_dst_reject()
944 rt->dst.input = ip6_pkt_prohibit; in ip6_rt_init_dst_reject()
949 rt->dst.output = ip6_pkt_discard_out; in ip6_rt_init_dst_reject()
950 rt->dst.input = ip6_pkt_discard; in ip6_rt_init_dst_reject()
957 if (ort->fib6_flags & RTF_REJECT) { in ip6_rt_init_dst()
962 rt->dst.error = 0; in ip6_rt_init_dst()
963 rt->dst.output = ip6_output; in ip6_rt_init_dst()
965 if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) { in ip6_rt_init_dst()
966 rt->dst.input = ip6_input; in ip6_rt_init_dst()
967 } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) { in ip6_rt_init_dst()
968 rt->dst.input = ip6_mc_input; in ip6_rt_init_dst()
970 rt->dst.input = ip6_forward; in ip6_rt_init_dst()
973 if (ort->fib6_nh.nh_lwtstate) { in ip6_rt_init_dst()
974 rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.nh_lwtstate); in ip6_rt_init_dst()
975 lwtunnel_set_redirect(&rt->dst); in ip6_rt_init_dst()
978 rt->dst.lastuse = jiffies; in ip6_rt_init_dst()
984 rt->rt6i_flags &= ~RTF_EXPIRES; in rt6_set_from()
985 rcu_assign_pointer(rt->from, from); in rt6_set_from()
986 dst_init_metrics(&rt->dst, from->fib6_metrics->metrics, true); in rt6_set_from()
987 if (from->fib6_metrics != &dst_default_metrics) { in rt6_set_from()
988 rt->dst._metrics |= DST_METRICS_REFCOUNTED; in rt6_set_from()
989 refcount_inc(&from->fib6_metrics->refcnt); in rt6_set_from()
1000 rt->rt6i_dst = ort->fib6_dst; in ip6_rt_copy_init()
1001 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL; in ip6_rt_copy_init()
1002 rt->rt6i_gateway = ort->fib6_nh.nh_gw; in ip6_rt_copy_init()
1003 rt->rt6i_flags = ort->fib6_flags; in ip6_rt_copy_init()
1006 rt->rt6i_src = ort->fib6_src; in ip6_rt_copy_init()
1008 rt->rt6i_prefsrc = ort->fib6_prefsrc; in ip6_rt_copy_init()
1016 if (fn->fn_flags & RTN_TL_ROOT) in fib6_backtrack()
1018 pn = rcu_dereference(fn->parent); in fib6_backtrack()
1024 if (fn->fn_flags & RTN_RTINFO) in fib6_backtrack()
1034 if (dst_hold_safe(&rt->dst)) in ip6_hold_safe()
1037 rt = net->ipv6.ip6_null_entry; in ip6_hold_safe()
1038 dst_hold(&rt->dst); in ip6_hold_safe()
1050 struct net_device *dev = rt->fib6_nh.nh_dev; in ip6_create_rt_rcu()
1066 nrt = dev_net(dev)->ipv6.ip6_null_entry; in ip6_create_rt_rcu()
1067 dst_hold(&nrt->dst); in ip6_create_rt_rcu()
1081 if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) in ip6_pol_route_lookup()
1085 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); in ip6_pol_route_lookup()
1087 f6i = rcu_dereference(fn->leaf); in ip6_pol_route_lookup()
1089 f6i = net->ipv6.fib6_null_entry; in ip6_pol_route_lookup()
1091 f6i = rt6_device_match(net, f6i, &fl6->saddr, in ip6_pol_route_lookup()
1092 fl6->flowi6_oif, flags); in ip6_pol_route_lookup()
1093 if (f6i->fib6_nsiblings && fl6->flowi6_oif == 0) in ip6_pol_route_lookup()
1095 fl6->flowi6_oif, skb, in ip6_pol_route_lookup()
1098 if (f6i == net->ipv6.fib6_null_entry) { in ip6_pol_route_lookup()
1099 fn = fib6_backtrack(fn, &fl6->saddr); in ip6_pol_route_lookup()
1107 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr); in ip6_pol_route_lookup()
1110 dst_use_noref(&rt->dst, jiffies); in ip6_pol_route_lookup()
1111 } else if (f6i == net->ipv6.fib6_null_entry) { in ip6_pol_route_lookup()
1112 rt = net->ipv6.ip6_null_entry; in ip6_pol_route_lookup()
1113 dst_hold(&rt->dst); in ip6_pol_route_lookup()
1147 if (dst->error == 0) in rt6_lookup()
1156 /* ip6_ins_rt is called with FREE table->tb6_lock.
1157 * It takes new route entry, the addition fails by any reason the
1158 * route is released.
1168 table = rt->fib6_table; in __ip6_ins_rt()
1169 spin_lock_bh(&table->tb6_lock); in __ip6_ins_rt()
1170 err = fib6_add(&table->tb6_root, rt, info, extack); in __ip6_ins_rt()
1171 spin_unlock_bh(&table->tb6_lock); in __ip6_ins_rt()
1191 * Clone the route. in ip6_rt_cache_alloc()
1205 rt->rt6i_flags |= RTF_CACHE; in ip6_rt_cache_alloc()
1206 rt->dst.flags |= DST_HOST; in ip6_rt_cache_alloc()
1207 rt->rt6i_dst.addr = *daddr; in ip6_rt_cache_alloc()
1208 rt->rt6i_dst.plen = 128; in ip6_rt_cache_alloc()
1211 if (ort->fib6_dst.plen != 128 && in ip6_rt_cache_alloc()
1212 ipv6_addr_equal(&ort->fib6_dst.addr, daddr)) in ip6_rt_cache_alloc()
1213 rt->rt6i_flags |= RTF_ANYCAST; in ip6_rt_cache_alloc()
1215 if (rt->rt6i_src.plen && saddr) { in ip6_rt_cache_alloc()
1216 rt->rt6i_src.addr = *saddr; in ip6_rt_cache_alloc()
1217 rt->rt6i_src.plen = 128; in ip6_rt_cache_alloc()
1243 pcpu_rt->rt6i_flags |= RTF_PCPU; in ip6_rt_pcpu_alloc()
1252 p = this_cpu_ptr(rt->rt6i_pcpu); in rt6_get_pcpu_route()
1268 dst_hold(&net->ipv6.ip6_null_entry->dst); in rt6_make_pcpu_route()
1269 return net->ipv6.ip6_null_entry; in rt6_make_pcpu_route()
1272 dst_hold(&pcpu_rt->dst); in rt6_make_pcpu_route()
1273 p = this_cpu_ptr(rt->rt6i_pcpu); in rt6_make_pcpu_route()
1277 if (rt->fib6_destroying) { in rt6_make_pcpu_route()
1280 from = xchg((__force struct fib6_info **)&pcpu_rt->from, NULL); in rt6_make_pcpu_route()
1303 net = dev_net(rt6_ex->rt6i->dst.dev); in rt6_remove_exception()
1304 net->ipv6.rt6_stats->fib_rt_cache--; in rt6_remove_exception()
1309 from = xchg((__force struct fib6_info **)&rt6_ex->rt6i->from, NULL); in rt6_remove_exception()
1311 dst_dev_put(&rt6_ex->rt6i->dst); in rt6_remove_exception()
1313 hlist_del_rcu(&rt6_ex->hlist); in rt6_remove_exception()
1314 dst_release(&rt6_ex->rt6i->dst); in rt6_remove_exception()
1316 WARN_ON_ONCE(!bucket->depth); in rt6_remove_exception()
1317 bucket->depth--; in rt6_remove_exception()
1330 hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { in rt6_exception_remove_oldest()
1331 if (!oldest || time_before(rt6_ex->stamp, oldest->stamp)) in rt6_exception_remove_oldest()
1372 hlist_for_each_entry(rt6_ex, &(*bucket)->chain, hlist) { in __rt6_find_exception_spinlock()
1373 struct rt6_info *rt6 = rt6_ex->rt6i; in __rt6_find_exception_spinlock()
1374 bool matched = ipv6_addr_equal(daddr, &rt6->rt6i_dst.addr); in __rt6_find_exception_spinlock()
1378 matched = ipv6_addr_equal(saddr, &rt6->rt6i_src.addr); in __rt6_find_exception_spinlock()
1407 hlist_for_each_entry_rcu(rt6_ex, &(*bucket)->chain, hlist) { in __rt6_find_exception_rcu()
1408 struct rt6_info *rt6 = rt6_ex->rt6i; in __rt6_find_exception_rcu()
1409 bool matched = ipv6_addr_equal(daddr, &rt6->rt6i_dst.addr); in __rt6_find_exception_rcu()
1413 matched = ipv6_addr_equal(saddr, &rt6->rt6i_src.addr); in __rt6_find_exception_rcu()
1425 if (rt->fib6_pmtu) { in fib6_mtu()
1426 mtu = rt->fib6_pmtu; in fib6_mtu()
1433 mtu = idev->cnf.mtu6; in fib6_mtu()
1439 return mtu - lwtunnel_headroom(rt->fib6_nh.nh_lwtstate, mtu); in fib6_mtu()
1445 struct net *net = dev_net(nrt->dst.dev); in rt6_insert_exception()
1453 if (ort->exception_bucket_flushed) { in rt6_insert_exception()
1454 err = -EINVAL; in rt6_insert_exception()
1458 bucket = rcu_dereference_protected(ort->rt6i_exception_bucket, in rt6_insert_exception()
1464 err = -ENOMEM; in rt6_insert_exception()
1467 rcu_assign_pointer(ort->rt6i_exception_bucket, bucket); in rt6_insert_exception()
1477 if (ort->fib6_src.plen) in rt6_insert_exception()
1478 src_key = &nrt->rt6i_src.addr; in rt6_insert_exception()
1484 nrt->rt6i_prefsrc = ort->fib6_prefsrc; in rt6_insert_exception()
1486 * Only insert this exception route if its mtu in rt6_insert_exception()
1489 if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(ort)) { in rt6_insert_exception()
1490 err = -EINVAL; in rt6_insert_exception()
1494 rt6_ex = __rt6_find_exception_spinlock(&bucket, &nrt->rt6i_dst.addr, in rt6_insert_exception()
1501 err = -ENOMEM; in rt6_insert_exception()
1504 rt6_ex->rt6i = nrt; in rt6_insert_exception()
1505 rt6_ex->stamp = jiffies; in rt6_insert_exception()
1506 hlist_add_head_rcu(&rt6_ex->hlist, &bucket->chain); in rt6_insert_exception()
1507 bucket->depth++; in rt6_insert_exception()
1508 net->ipv6.rt6_stats->fib_rt_cache++; in rt6_insert_exception()
1510 if (bucket->depth > FIB6_MAX_DEPTH) in rt6_insert_exception()
1516 /* Update fn->fn_sernum to invalidate all cached dst */ in rt6_insert_exception()
1518 spin_lock_bh(&ort->fib6_table->tb6_lock); in rt6_insert_exception()
1520 spin_unlock_bh(&ort->fib6_table->tb6_lock); in rt6_insert_exception()
1536 rt->exception_bucket_flushed = 1; in rt6_flush_exceptions()
1538 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, in rt6_flush_exceptions()
1544 hlist_for_each_entry_safe(rt6_ex, tmp, &bucket->chain, hlist) in rt6_flush_exceptions()
1546 WARN_ON_ONCE(bucket->depth); in rt6_flush_exceptions()
1573 * So we need to use f6i->fib6_src to redo lookup in rt6_find_cached_rt()
1576 * rt->rt6i_src is updated.) in rt6_find_cached_rt()
1578 if (rt->fib6_src.plen) in rt6_find_cached_rt()
1582 bucket = rcu_dereference(rt->rt6i_exception_bucket); in rt6_find_cached_rt()
1585 if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i)) in rt6_find_cached_rt()
1586 res = rt6_ex->rt6i; in rt6_find_cached_rt()
1590 if (!res && src_key && src_key != &rt->fib6_src.addr) { in rt6_find_cached_rt()
1591 src_key = &rt->fib6_src.addr; in rt6_find_cached_rt()
1608 from = rcu_dereference(rt->from); in rt6_remove_exception_rt()
1610 !(rt->rt6i_flags & RTF_CACHE)) in rt6_remove_exception_rt()
1611 return -EINVAL; in rt6_remove_exception_rt()
1613 if (!rcu_access_pointer(from->rt6i_exception_bucket)) in rt6_remove_exception_rt()
1614 return -ENOENT; in rt6_remove_exception_rt()
1617 bucket = rcu_dereference_protected(from->rt6i_exception_bucket, in rt6_remove_exception_rt()
1626 if (from->fib6_src.plen) in rt6_remove_exception_rt()
1627 src_key = &rt->rt6i_src.addr; in rt6_remove_exception_rt()
1630 &rt->rt6i_dst.addr, in rt6_remove_exception_rt()
1636 err = -ENOENT; in rt6_remove_exception_rt()
1654 from = rcu_dereference(rt->from); in rt6_update_exception_stamp_rt()
1655 if (!from || !(rt->rt6i_flags & RTF_CACHE)) in rt6_update_exception_stamp_rt()
1658 bucket = rcu_dereference(from->rt6i_exception_bucket); in rt6_update_exception_stamp_rt()
1667 if (from->fib6_src.plen) in rt6_update_exception_stamp_rt()
1668 src_key = &rt->rt6i_src.addr; in rt6_update_exception_stamp_rt()
1671 &rt->rt6i_dst.addr, in rt6_update_exception_stamp_rt()
1674 rt6_ex->stamp = jiffies; in rt6_update_exception_stamp_rt()
1686 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, in rt6_exceptions_remove_prefsrc()
1691 hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { in rt6_exceptions_remove_prefsrc()
1692 rt6_ex->rt6i->rt6i_prefsrc.plen = 0; in rt6_exceptions_remove_prefsrc()
1702 /* If the new MTU is lower than the route PMTU, this new MTU will be the in rt6_mtu_change_route_allowed()
1703 * lowest MTU in the path: always allow updating the route PMTU to in rt6_mtu_change_route_allowed()
1706 * If the new MTU is higher, and the route PMTU is equal to the local in rt6_mtu_change_route_allowed()
1712 if (dst_mtu(&rt->dst) >= mtu) in rt6_mtu_change_route_allowed()
1715 if (dst_mtu(&rt->dst) == idev->cnf.mtu6) in rt6_mtu_change_route_allowed()
1728 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, in rt6_exceptions_update_pmtu()
1735 hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { in rt6_exceptions_update_pmtu()
1736 struct rt6_info *entry = rt6_ex->rt6i; in rt6_exceptions_update_pmtu()
1739 * route), the metrics of its rt->from have already in rt6_exceptions_update_pmtu()
1742 if (dst_metric_raw(&entry->dst, RTAX_MTU) && in rt6_exceptions_update_pmtu()
1744 dst_metric_set(&entry->dst, RTAX_MTU, mtu); in rt6_exceptions_update_pmtu()
1760 if (!rcu_access_pointer(rt->rt6i_exception_bucket)) in rt6_exceptions_clean_tohost()
1764 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, in rt6_exceptions_clean_tohost()
1770 &bucket->chain, hlist) { in rt6_exceptions_clean_tohost()
1771 struct rt6_info *entry = rt6_ex->rt6i; in rt6_exceptions_clean_tohost()
1773 if ((entry->rt6i_flags & RTF_CACHE_GATEWAY) == in rt6_exceptions_clean_tohost()
1776 &entry->rt6i_gateway)) { in rt6_exceptions_clean_tohost()
1792 struct rt6_info *rt = rt6_ex->rt6i; in rt6_age_examine_exception()
1794 /* we are pruning and obsoleting aged-out and non gateway exceptions in rt6_age_examine_exception()
1797 * EXPIRES exceptions - e.g. pmtu-generated ones are pruned when in rt6_age_examine_exception()
1800 if (!(rt->rt6i_flags & RTF_EXPIRES)) { in rt6_age_examine_exception()
1801 if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) { in rt6_age_examine_exception()
1806 } else if (time_after(jiffies, rt->dst.expires)) { in rt6_age_examine_exception()
1807 RT6_TRACE("purging expired route %p\n", rt); in rt6_age_examine_exception()
1812 if (rt->rt6i_flags & RTF_GATEWAY) { in rt6_age_examine_exception()
1816 neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); in rt6_age_examine_exception()
1818 neigh_flags = neigh->flags; in rt6_age_examine_exception()
1821 RT6_TRACE("purging route %p via non-router but gateway\n", in rt6_age_examine_exception()
1828 gc_args->more++; in rt6_age_examine_exception()
1840 if (!rcu_access_pointer(rt->rt6i_exception_bucket)) in rt6_age_exceptions()
1845 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, in rt6_age_exceptions()
1851 &bucket->chain, hlist) { in rt6_age_exceptions()
1869 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); in fib6_table_lookup()
1872 if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) in fib6_table_lookup()
1877 if (f6i == net->ipv6.fib6_null_entry) { in fib6_table_lookup()
1878 fn = fib6_backtrack(fn, &fl6->saddr); in fib6_table_lookup()
1882 /* also consider unreachable route */ in fib6_table_lookup()
1904 if (net->ipv6.devconf_all->forwarding == 0) in ip6_pol_route()
1910 if (f6i->fib6_nsiblings) in ip6_pol_route()
1913 if (f6i == net->ipv6.fib6_null_entry) { in ip6_pol_route()
1914 rt = net->ipv6.ip6_null_entry; in ip6_pol_route()
1916 dst_hold(&rt->dst); in ip6_pol_route()
1921 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr); in ip6_pol_route()
1924 dst_use_noref(&rt->dst, jiffies); in ip6_pol_route()
1928 } else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) && in ip6_pol_route()
1929 !(f6i->fib6_flags & RTF_GATEWAY))) { in ip6_pol_route()
1932 * the daddr in the skb during the neighbor look-up is different in ip6_pol_route()
1933 * from the fl6->daddr used to look-up route here. in ip6_pol_route()
1937 uncached_rt = ip6_rt_cache_alloc(f6i, &fl6->daddr, NULL); in ip6_pol_route()
1946 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache); in ip6_pol_route()
1948 uncached_rt = net->ipv6.ip6_null_entry; in ip6_pol_route()
1949 dst_hold(&uncached_rt->dst); in ip6_pol_route()
1978 return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, skb, flags); in ip6_pol_route_input()
1987 if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG) in ip6_route_input_lookup()
2006 if (likely(outer_iph->nexthdr != IPPROTO_ICMPV6)) in ip6_multipath_l3_keys()
2014 if (icmph->icmp6_type != ICMPV6_DEST_UNREACH && in ip6_multipath_l3_keys()
2015 icmph->icmp6_type != ICMPV6_PKT_TOOBIG && in ip6_multipath_l3_keys()
2016 icmph->icmp6_type != ICMPV6_TIME_EXCEED && in ip6_multipath_l3_keys()
2017 icmph->icmp6_type != ICMPV6_PARAMPROB) in ip6_multipath_l3_keys()
2030 keys->addrs.v6addrs.src = _flkeys->addrs.v6addrs.src; in ip6_multipath_l3_keys()
2031 keys->addrs.v6addrs.dst = _flkeys->addrs.v6addrs.dst; in ip6_multipath_l3_keys()
2032 keys->tags.flow_label = _flkeys->tags.flow_label; in ip6_multipath_l3_keys()
2033 keys->basic.ip_proto = _flkeys->basic.ip_proto; in ip6_multipath_l3_keys()
2035 keys->addrs.v6addrs.src = key_iph->saddr; in ip6_multipath_l3_keys()
2036 keys->addrs.v6addrs.dst = key_iph->daddr; in ip6_multipath_l3_keys()
2037 keys->tags.flow_label = ip6_flowlabel(key_iph); in ip6_multipath_l3_keys()
2038 keys->basic.ip_proto = key_iph->nexthdr; in ip6_multipath_l3_keys()
2056 hash_keys.addrs.v6addrs.src = fl6->saddr; in rt6_multipath_hash()
2057 hash_keys.addrs.v6addrs.dst = fl6->daddr; in rt6_multipath_hash()
2059 hash_keys.basic.ip_proto = fl6->flowi6_proto; in rt6_multipath_hash()
2067 /* short-circuit if we already have L4 hash present */ in rt6_multipath_hash()
2068 if (skb->l4_hash) in rt6_multipath_hash()
2078 hash_keys.addrs.v6addrs.src = flkeys->addrs.v6addrs.src; in rt6_multipath_hash()
2079 hash_keys.addrs.v6addrs.dst = flkeys->addrs.v6addrs.dst; in rt6_multipath_hash()
2080 hash_keys.ports.src = flkeys->ports.src; in rt6_multipath_hash()
2081 hash_keys.ports.dst = flkeys->ports.dst; in rt6_multipath_hash()
2082 hash_keys.basic.ip_proto = flkeys->basic.ip_proto; in rt6_multipath_hash()
2086 hash_keys.addrs.v6addrs.src = fl6->saddr; in rt6_multipath_hash()
2087 hash_keys.addrs.v6addrs.dst = fl6->daddr; in rt6_multipath_hash()
2088 hash_keys.ports.src = fl6->fl6_sport; in rt6_multipath_hash()
2089 hash_keys.ports.dst = fl6->fl6_dport; in rt6_multipath_hash()
2090 hash_keys.basic.ip_proto = fl6->flowi6_proto; in rt6_multipath_hash()
2102 struct net *net = dev_net(skb->dev); in ip6_route_input()
2106 .flowi6_iif = skb->dev->ifindex, in ip6_route_input()
2107 .daddr = iph->daddr, in ip6_route_input()
2108 .saddr = iph->saddr, in ip6_route_input()
2110 .flowi6_mark = skb->mark, in ip6_route_input()
2111 .flowi6_proto = iph->nexthdr, in ip6_route_input()
2116 if (tun_info && !(tun_info->mode & IP_TUNNEL_INFO_TX)) in ip6_route_input()
2117 fl6.flowi6_tun_key.tun_id = tun_info->key.tun_id; in ip6_route_input()
2126 ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags)); in ip6_route_input()
2135 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags); in ip6_pol_route_output()
2143 if (rt6_need_strict(&fl6->daddr)) { in ip6_route_output_flags()
2151 fl6->flowi6_iif = LOOPBACK_IFINDEX; in ip6_route_output_flags()
2153 any_src = ipv6_addr_any(&fl6->saddr); in ip6_route_output_flags()
2154 if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) || in ip6_route_output_flags()
2155 (fl6->flowi6_oif && any_src)) in ip6_route_output_flags()
2161 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); in ip6_route_output_flags()
2170 struct net_device *loopback_dev = net->loopback_dev; in ip6_blackhole_route()
2177 atomic_inc(&net->ipv6.rt6_stats->fib_rt_alloc); in ip6_blackhole_route()
2179 new = &rt->dst; in ip6_blackhole_route()
2180 new->__use = 1; in ip6_blackhole_route()
2181 new->input = dst_discard; in ip6_blackhole_route()
2182 new->output = dst_discard_out; in ip6_blackhole_route()
2184 dst_copy_metrics(new, &ort->dst); in ip6_blackhole_route()
2186 rt->rt6i_idev = in6_dev_get(loopback_dev); in ip6_blackhole_route()
2187 rt->rt6i_gateway = ort->rt6i_gateway; in ip6_blackhole_route()
2188 rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU; in ip6_blackhole_route()
2190 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); in ip6_blackhole_route()
2192 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); in ip6_blackhole_route()
2197 return new ? new : ERR_PTR(-ENOMEM); in ip6_blackhole_route()
2230 return &rt->dst; in rt6_check()
2238 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && in rt6_dst_from_check()
2240 return &rt->dst; in rt6_dst_from_check()
2255 /* All IPV6 dsts are created with ->obsolete set to the value in ip6_dst_check()
2260 from = rcu_dereference(rt->from); in ip6_dst_check()
2262 if (from && (rt->rt6i_flags & RTF_PCPU || in ip6_dst_check()
2263 unlikely(!list_empty(&rt->rt6i_uncached)))) in ip6_dst_check()
2278 if (rt->rt6i_flags & RTF_CACHE) { in ip6_negative_advice()
2302 if (rt->rt6i_flags & RTF_CACHE) { in ip6_link_failure()
2308 from = rcu_dereference(rt->from); in ip6_link_failure()
2310 fn = rcu_dereference(from->fib6_node); in ip6_link_failure()
2311 if (fn && (rt->rt6i_flags & RTF_DEFAULT)) in ip6_link_failure()
2312 fn->fn_sernum = -1; in ip6_link_failure()
2321 if (!(rt0->rt6i_flags & RTF_EXPIRES)) { in rt6_update_expires()
2325 from = rcu_dereference(rt0->from); in rt6_update_expires()
2327 rt0->dst.expires = from->expires; in rt6_update_expires()
2331 dst_set_expires(&rt0->dst, timeout); in rt6_update_expires()
2332 rt0->rt6i_flags |= RTF_EXPIRES; in rt6_update_expires()
2337 struct net *net = dev_net(rt->dst.dev); in rt6_do_update_pmtu()
2339 dst_metric_set(&rt->dst, RTAX_MTU, mtu); in rt6_do_update_pmtu()
2340 rt->rt6i_flags |= RTF_MODIFIED; in rt6_do_update_pmtu()
2341 rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); in rt6_do_update_pmtu()
2349 from_set = !!rcu_dereference(rt->from); in rt6_cache_allowed_for_pmtu()
2352 return !(rt->rt6i_flags & RTF_CACHE) && in rt6_cache_allowed_for_pmtu()
2353 (rt->rt6i_flags & RTF_PCPU || from_set); in rt6_cache_allowed_for_pmtu()
2369 daddr = &iph->daddr; in __ip6_rt_update_pmtu()
2370 saddr = &iph->saddr; in __ip6_rt_update_pmtu()
2372 daddr = &sk->sk_v6_daddr; in __ip6_rt_update_pmtu()
2373 saddr = &inet6_sk(sk)->saddr; in __ip6_rt_update_pmtu()
2388 /* update rt6_ex->stamp for cache */ in __ip6_rt_update_pmtu()
2389 if (rt6->rt6i_flags & RTF_CACHE) in __ip6_rt_update_pmtu()
2396 from = rcu_dereference(rt6->from); in __ip6_rt_update_pmtu()
2405 dst_release_immediate(&nrt6->dst); in __ip6_rt_update_pmtu()
2422 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; in ip6_update_pmtu()
2428 fl6.flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark); in ip6_update_pmtu()
2429 fl6.daddr = iph->daddr; in ip6_update_pmtu()
2430 fl6.saddr = iph->saddr; in ip6_update_pmtu()
2435 if (!dst->error) in ip6_update_pmtu()
2443 int oif = sk->sk_bound_dev_if; in ip6_sk_update_pmtu()
2446 if (!oif && skb->dev) in ip6_sk_update_pmtu()
2447 oif = l3mdev_master_ifindex(skb->dev); in ip6_sk_update_pmtu()
2449 ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid); in ip6_sk_update_pmtu()
2452 if (!dst || !dst->obsolete || in ip6_sk_update_pmtu()
2453 dst->ops->check(dst, inet6_sk(sk)->dst_cookie)) in ip6_sk_update_pmtu()
2457 if (!sock_owned_by_user(sk) && !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in ip6_sk_update_pmtu()
2471 ipv6_addr_equal(&fl6->daddr, &sk->sk_v6_daddr) ? in ip6_sk_dst_store_flow()
2472 &sk->sk_v6_daddr : NULL, in ip6_sk_dst_store_flow()
2474 ipv6_addr_equal(&fl6->saddr, &np->saddr) ? in ip6_sk_dst_store_flow()
2475 &np->saddr : in ip6_sk_dst_store_flow()
2500 if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) in __ip6_route_redirect()
2501 fl6->flowi6_oif = skb->dev->ifindex; in __ip6_route_redirect()
2503 /* Get the "current" route for this destination and in __ip6_route_redirect()
2514 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); in __ip6_route_redirect()
2517 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD) in __ip6_route_redirect()
2521 if (rt->fib6_flags & RTF_REJECT) in __ip6_route_redirect()
2523 if (!(rt->fib6_flags & RTF_GATEWAY)) in __ip6_route_redirect()
2525 if (fl6->flowi6_oif != rt->fib6_nh.nh_dev->ifindex) in __ip6_route_redirect()
2532 if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.nh_gw)) { in __ip6_route_redirect()
2534 &fl6->daddr, in __ip6_route_redirect()
2535 &fl6->saddr); in __ip6_route_redirect()
2537 ipv6_addr_equal(&rdfl->gateway, in __ip6_route_redirect()
2538 &rt_cache->rt6i_gateway)) { in __ip6_route_redirect()
2548 rt = net->ipv6.fib6_null_entry; in __ip6_route_redirect()
2549 else if (rt->fib6_flags & RTF_REJECT) { in __ip6_route_redirect()
2550 ret = net->ipv6.ip6_null_entry; in __ip6_route_redirect()
2554 if (rt == net->ipv6.fib6_null_entry) { in __ip6_route_redirect()
2555 fn = fib6_backtrack(fn, &fl6->saddr); in __ip6_route_redirect()
2590 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; in ip6_redirect()
2598 fl6.daddr = iph->daddr; in ip6_redirect()
2599 fl6.saddr = iph->saddr; in ip6_redirect()
2603 dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr); in ip6_redirect()
2621 fl6.daddr = msg->dest; in ip6_redirect_no_header()
2622 fl6.saddr = iph->daddr; in ip6_redirect_no_header()
2625 dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr); in ip6_redirect_no_header()
2632 ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark, in ip6_sk_redirect()
2633 sk->sk_uid); in ip6_sk_redirect()
2639 struct net_device *dev = dst->dev; in ip6_default_advmss()
2643 mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); in ip6_default_advmss()
2645 if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) in ip6_default_advmss()
2646 mtu = net->ipv6.sysctl.ip6_rt_min_advmss; in ip6_default_advmss()
2649 * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and in ip6_default_advmss()
2650 * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. in ip6_default_advmss()
2654 if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr)) in ip6_default_advmss()
2671 idev = __in6_dev_get(dst->dev); in ip6_mtu()
2673 mtu = idev->cnf.mtu6; in ip6_mtu()
2679 return mtu - lwtunnel_headroom(dst->lwtstate, mtu); in ip6_mtu()
2683 * 1. mtu on route is locked - use it
2698 mtu = f6i->fib6_pmtu; in ip6_mtu_from_fib6()
2705 mtu = dst_metric_raw(&rt->dst, RTAX_MTU); in ip6_mtu_from_fib6()
2711 if (idev && idev->cnf.mtu6 > mtu) in ip6_mtu_from_fib6()
2712 mtu = idev->cnf.mtu6; in ip6_mtu_from_fib6()
2717 return mtu - lwtunnel_headroom(fib6_info_nh_lwt(f6i), mtu); in ip6_mtu_from_fib6()
2729 return ERR_PTR(-ENODEV); in icmp6_dst_alloc()
2734 dst = ERR_PTR(-ENOMEM); in icmp6_dst_alloc()
2738 rt->dst.flags |= DST_HOST; in icmp6_dst_alloc()
2739 rt->dst.input = ip6_input; in icmp6_dst_alloc()
2740 rt->dst.output = ip6_output; in icmp6_dst_alloc()
2741 rt->rt6i_gateway = fl6->daddr; in icmp6_dst_alloc()
2742 rt->rt6i_dst.addr = fl6->daddr; in icmp6_dst_alloc()
2743 rt->rt6i_dst.plen = 128; in icmp6_dst_alloc()
2744 rt->rt6i_idev = idev; in icmp6_dst_alloc()
2745 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); in icmp6_dst_alloc()
2751 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache); in icmp6_dst_alloc()
2753 dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); in icmp6_dst_alloc()
2762 int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; in ip6_dst_gc()
2763 int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; in ip6_dst_gc()
2764 int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; in ip6_dst_gc()
2765 int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; in ip6_dst_gc()
2766 unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; in ip6_dst_gc()
2774 net->ipv6.ip6_rt_gc_expire++; in ip6_dst_gc()
2775 fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, true); in ip6_dst_gc()
2777 if (entries < ops->gc_thresh) in ip6_dst_gc()
2778 net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; in ip6_dst_gc()
2780 net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity; in ip6_dst_gc()
2789 if (!cfg->fc_mx) in ip6_convert_metrics()
2792 p = kzalloc(sizeof(*rt->fib6_metrics), GFP_KERNEL); in ip6_convert_metrics()
2794 return -ENOMEM; in ip6_convert_metrics()
2796 refcount_set(&p->refcnt, 1); in ip6_convert_metrics()
2797 rt->fib6_metrics = p; in ip6_convert_metrics()
2799 return ip_metrics_convert(net, cfg->fc_mx, cfg->fc_mx_len, p->metrics); in ip6_convert_metrics()
2808 .flowi6_oif = cfg->fc_ifindex, in ip6_nh_lookup_table()
2810 .saddr = cfg->fc_prefsrc, in ip6_nh_lookup_table()
2819 if (!ipv6_addr_any(&cfg->fc_prefsrc)) in ip6_nh_lookup_table()
2823 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, NULL, flags); in ip6_nh_lookup_table()
2826 if (rt == net->ipv6.ip6_null_entry) { in ip6_nh_lookup_table()
2840 const struct in6_addr *gw_addr = &cfg->fc_gateway; in ip6_route_check_nh_onlink()
2850 from = rcu_dereference(grt->from); in ip6_route_check_nh_onlink()
2851 if (!grt->dst.error && in ip6_route_check_nh_onlink()
2852 /* ignore match if it is the default route */ in ip6_route_check_nh_onlink()
2853 from && !ipv6_addr_any(&from->fib6_dst.addr) && in ip6_route_check_nh_onlink()
2854 (grt->rt6i_flags & flags || dev != grt->dst.dev)) { in ip6_route_check_nh_onlink()
2857 err = -EINVAL; in ip6_route_check_nh_onlink()
2872 const struct in6_addr *gw_addr = &cfg->fc_gateway; in ip6_route_check_nh()
2875 int err = -EHOSTUNREACH; in ip6_route_check_nh()
2877 if (cfg->fc_table) { in ip6_route_check_nh()
2881 cfg->fc_table, flags); in ip6_route_check_nh()
2883 if (grt->rt6i_flags & RTF_GATEWAY || in ip6_route_check_nh()
2884 (dev && dev != grt->dst.dev)) { in ip6_route_check_nh()
2892 grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, NULL, 1); in ip6_route_check_nh()
2898 if (dev != grt->dst.dev) { in ip6_route_check_nh()
2903 *_dev = dev = grt->dst.dev; in ip6_route_check_nh()
2904 *idev = grt->rt6i_idev; in ip6_route_check_nh()
2906 in6_dev_hold(grt->rt6i_idev); in ip6_route_check_nh()
2909 if (!(grt->rt6i_flags & RTF_GATEWAY)) in ip6_route_check_nh()
2922 const struct in6_addr *gw_addr = &cfg->fc_gateway; in ip6_validate_gw()
2927 int err = -EINVAL; in ip6_validate_gw()
2931 * will return already-added prefix route via interface that in ip6_validate_gw()
2932 * prefix route was assigned to, which might be non-loopback. in ip6_validate_gw()
2941 /* IPv6 strictly inhibits using not link-local in ip6_validate_gw()
2945 * (SIT, PtP, NBMA NOARP links) it is handy to allow in ip6_validate_gw()
2946 * some exceptions. --ANK in ip6_validate_gw()
2947 * We allow IPv4-mapped nexthops to support RFC4798-type in ip6_validate_gw()
2955 if (cfg->fc_flags & RTNH_F_ONLINK) in ip6_validate_gw()
2967 err = -EINVAL; in ip6_validate_gw()
2971 } else if (dev->flags & IFF_LOOPBACK) { in ip6_validate_gw()
2973 "Egress device can not be loopback device for this route"); in ip6_validate_gw()
2995 struct net *net = cfg->fc_nlinfo.nl_net; in ip6_route_info_create()
3001 int err = -EINVAL; in ip6_route_info_create()
3004 if (cfg->fc_flags & RTF_PCPU) { in ip6_route_info_create()
3010 if (cfg->fc_flags & RTF_CACHE) { in ip6_route_info_create()
3015 if (cfg->fc_type > RTN_MAX) { in ip6_route_info_create()
3016 NL_SET_ERR_MSG(extack, "Invalid route type"); in ip6_route_info_create()
3020 if (cfg->fc_dst_len > 128) { in ip6_route_info_create()
3024 if (cfg->fc_src_len > 128) { in ip6_route_info_create()
3029 if (cfg->fc_src_len) { in ip6_route_info_create()
3035 if (cfg->fc_ifindex) { in ip6_route_info_create()
3036 err = -ENODEV; in ip6_route_info_create()
3037 dev = dev_get_by_index(net, cfg->fc_ifindex); in ip6_route_info_create()
3045 if (cfg->fc_metric == 0) in ip6_route_info_create()
3046 cfg->fc_metric = IP6_RT_PRIO_USER; in ip6_route_info_create()
3048 if (cfg->fc_flags & RTNH_F_ONLINK) { in ip6_route_info_create()
3052 err = -ENODEV; in ip6_route_info_create()
3056 if (!(dev->flags & IFF_UP)) { in ip6_route_info_create()
3058 err = -ENETDOWN; in ip6_route_info_create()
3063 err = -ENOBUFS; in ip6_route_info_create()
3064 if (cfg->fc_nlinfo.nlh && in ip6_route_info_create()
3065 !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) { in ip6_route_info_create()
3066 table = fib6_get_table(net, cfg->fc_table); in ip6_route_info_create()
3068 pr_warn("NLM_F_CREATE should be specified when creating new route\n"); in ip6_route_info_create()
3069 table = fib6_new_table(net, cfg->fc_table); in ip6_route_info_create()
3072 table = fib6_new_table(net, cfg->fc_table); in ip6_route_info_create()
3078 err = -ENOMEM; in ip6_route_info_create()
3084 rt->last_probe = jiffies; in ip6_route_info_create()
3086 if (cfg->fc_flags & RTF_ADDRCONF) in ip6_route_info_create()
3087 rt->dst_nocount = true; in ip6_route_info_create()
3093 if (cfg->fc_flags & RTF_EXPIRES) in ip6_route_info_create()
3095 clock_t_to_jiffies(cfg->fc_expires)); in ip6_route_info_create()
3099 if (cfg->fc_protocol == RTPROT_UNSPEC) in ip6_route_info_create()
3100 cfg->fc_protocol = RTPROT_BOOT; in ip6_route_info_create()
3101 rt->fib6_protocol = cfg->fc_protocol; in ip6_route_info_create()
3103 addr_type = ipv6_addr_type(&cfg->fc_dst); in ip6_route_info_create()
3105 if (cfg->fc_encap) { in ip6_route_info_create()
3108 err = lwtunnel_build_state(cfg->fc_encap_type, in ip6_route_info_create()
3109 cfg->fc_encap, AF_INET6, cfg, in ip6_route_info_create()
3113 rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate); in ip6_route_info_create()
3116 ipv6_addr_prefix(&rt->fib6_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); in ip6_route_info_create()
3117 rt->fib6_dst.plen = cfg->fc_dst_len; in ip6_route_info_create()
3118 if (rt->fib6_dst.plen == 128) in ip6_route_info_create()
3119 rt->dst_host = true; in ip6_route_info_create()
3122 ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len); in ip6_route_info_create()
3123 rt->fib6_src.plen = cfg->fc_src_len; in ip6_route_info_create()
3126 rt->fib6_metric = cfg->fc_metric; in ip6_route_info_create()
3127 rt->fib6_nh.nh_weight = 1; in ip6_route_info_create()
3129 rt->fib6_type = cfg->fc_type ? : RTN_UNICAST; in ip6_route_info_create()
3134 if ((cfg->fc_flags & RTF_REJECT) || in ip6_route_info_create()
3135 (dev && (dev->flags & IFF_LOOPBACK) && in ip6_route_info_create()
3137 !(cfg->fc_flags & RTF_LOCAL))) { in ip6_route_info_create()
3139 if (dev != net->loopback_dev) { in ip6_route_info_create()
3144 dev = net->loopback_dev; in ip6_route_info_create()
3148 err = -ENODEV; in ip6_route_info_create()
3152 rt->fib6_flags = RTF_REJECT|RTF_NONEXTHOP; in ip6_route_info_create()
3156 if (cfg->fc_flags & RTF_GATEWAY) { in ip6_route_info_create()
3161 rt->fib6_nh.nh_gw = cfg->fc_gateway; in ip6_route_info_create()
3164 err = -ENODEV; in ip6_route_info_create()
3168 if (idev->cnf.disable_ipv6) { in ip6_route_info_create()
3170 err = -EACCES; in ip6_route_info_create()
3174 if (!(dev->flags & IFF_UP)) { in ip6_route_info_create()
3176 err = -ENETDOWN; in ip6_route_info_create()
3180 if (!ipv6_addr_any(&cfg->fc_prefsrc)) { in ip6_route_info_create()
3181 if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) { in ip6_route_info_create()
3183 err = -EINVAL; in ip6_route_info_create()
3186 rt->fib6_prefsrc.addr = cfg->fc_prefsrc; in ip6_route_info_create()
3187 rt->fib6_prefsrc.plen = 128; in ip6_route_info_create()
3189 rt->fib6_prefsrc.plen = 0; in ip6_route_info_create()
3191 rt->fib6_flags = cfg->fc_flags; in ip6_route_info_create()
3194 if (!(rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) && in ip6_route_info_create()
3196 rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN; in ip6_route_info_create()
3197 rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK); in ip6_route_info_create()
3198 rt->fib6_nh.nh_dev = dev; in ip6_route_info_create()
3199 rt->fib6_table = table; in ip6_route_info_create()
3201 cfg->fc_nlinfo.nl_net = dev_net(dev); in ip6_route_info_create()
3227 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack); in ip6_route_add()
3235 struct net *net = info->nl_net; in __ip6_del_rt()
3239 if (rt == net->ipv6.fib6_null_entry) { in __ip6_del_rt()
3240 err = -ENOENT; in __ip6_del_rt()
3244 table = rt->fib6_table; in __ip6_del_rt()
3245 spin_lock_bh(&table->tb6_lock); in __ip6_del_rt()
3247 spin_unlock_bh(&table->tb6_lock); in __ip6_del_rt()
3263 struct nl_info *info = &cfg->fc_nlinfo; in __ip6_del_rt_siblings()
3264 struct net *net = info->nl_net; in __ip6_del_rt_siblings()
3267 int err = -ENOENT; in __ip6_del_rt_siblings()
3269 if (rt == net->ipv6.fib6_null_entry) in __ip6_del_rt_siblings()
3271 table = rt->fib6_table; in __ip6_del_rt_siblings()
3272 spin_lock_bh(&table->tb6_lock); in __ip6_del_rt_siblings()
3274 if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) { in __ip6_del_rt_siblings()
3280 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; in __ip6_del_rt_siblings()
3284 info->portid, seq, 0) < 0) { in __ip6_del_rt_siblings()
3288 info->skip_notify = 1; in __ip6_del_rt_siblings()
3292 &rt->fib6_siblings, in __ip6_del_rt_siblings()
3302 spin_unlock_bh(&table->tb6_lock); in __ip6_del_rt_siblings()
3307 rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, in __ip6_del_rt_siblings()
3308 info->nlh, gfp_any()); in __ip6_del_rt_siblings()
3315 int rc = -ESRCH; in ip6_del_cached_rt()
3317 if (cfg->fc_ifindex && rt->dst.dev->ifindex != cfg->fc_ifindex) in ip6_del_cached_rt()
3320 if (cfg->fc_flags & RTF_GATEWAY && in ip6_del_cached_rt()
3321 !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) in ip6_del_cached_rt()
3336 int err = -ESRCH; in ip6_route_del()
3338 table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); in ip6_route_del()
3346 fn = fib6_locate(&table->tb6_root, in ip6_route_del()
3347 &cfg->fc_dst, cfg->fc_dst_len, in ip6_route_del()
3348 &cfg->fc_src, cfg->fc_src_len, in ip6_route_del()
3349 !(cfg->fc_flags & RTF_CACHE)); in ip6_route_del()
3353 if (cfg->fc_flags & RTF_CACHE) { in ip6_route_del()
3356 rt_cache = rt6_find_cached_rt(rt, &cfg->fc_dst, in ip6_route_del()
3357 &cfg->fc_src); in ip6_route_del()
3360 if (rc != -ESRCH) { in ip6_route_del()
3367 if (cfg->fc_ifindex && in ip6_route_del()
3368 (!rt->fib6_nh.nh_dev || in ip6_route_del()
3369 rt->fib6_nh.nh_dev->ifindex != cfg->fc_ifindex)) in ip6_route_del()
3371 if (cfg->fc_flags & RTF_GATEWAY && in ip6_route_del()
3372 !ipv6_addr_equal(&cfg->fc_gateway, &rt->fib6_nh.nh_gw)) in ip6_route_del()
3374 if (cfg->fc_metric && cfg->fc_metric != rt->fib6_metric) in ip6_route_del()
3376 if (cfg->fc_protocol && cfg->fc_protocol != rt->fib6_protocol) in ip6_route_del()
3383 if (cfg->fc_flags & RTF_GATEWAY) in ip6_route_del()
3384 return __ip6_del_rt(rt, &cfg->fc_nlinfo); in ip6_route_del()
3406 optlen = skb_tail_pointer(skb) - skb_transport_header(skb); in rt6_do_redirect()
3407 optlen -= sizeof(*msg); in rt6_do_redirect()
3416 if (ipv6_addr_is_multicast(&msg->dest)) { in rt6_do_redirect()
3422 if (ipv6_addr_equal(&msg->dest, &msg->target)) { in rt6_do_redirect()
3424 } else if (ipv6_addr_type(&msg->target) != in rt6_do_redirect()
3426 net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n"); in rt6_do_redirect()
3430 in6_dev = __in6_dev_get(skb->dev); in rt6_do_redirect()
3433 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) in rt6_do_redirect()
3438 * first-hop router for the specified ICMP Destination Address. in rt6_do_redirect()
3441 if (!ndisc_parse_options(skb->dev, msg->opt, optlen, &ndopts)) { in rt6_do_redirect()
3449 skb->dev); in rt6_do_redirect()
3451 net_dbg_ratelimited("rt6_redirect: invalid link-layer address length\n"); in rt6_do_redirect()
3457 if (rt->rt6i_flags & RTF_REJECT) { in rt6_do_redirect()
3462 /* Redirect received -> path was valid. in rt6_do_redirect()
3464 * so that this nexthop apparently is reachable. --ANK in rt6_do_redirect()
3466 dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr); in rt6_do_redirect()
3468 neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1); in rt6_do_redirect()
3476 ndisc_update(skb->dev, neigh, lladdr, NUD_STALE, in rt6_do_redirect()
3484 from = rcu_dereference(rt->from); in rt6_do_redirect()
3488 nrt = ip6_rt_cache_alloc(from, &msg->dest, NULL); in rt6_do_redirect()
3492 nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; in rt6_do_redirect()
3494 nrt->rt6i_flags &= ~RTF_GATEWAY; in rt6_do_redirect()
3496 nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; in rt6_do_redirect()
3500 dst_release_immediate(&nrt->dst); in rt6_do_redirect()
3504 netevent.old = &rt->dst; in rt6_do_redirect()
3505 netevent.new = &nrt->dst; in rt6_do_redirect()
3506 netevent.daddr = &msg->dest; in rt6_do_redirect()
3522 int ifindex = dev->ifindex; in rt6_get_route_info()
3532 fn = fib6_locate(&table->tb6_root, prefix, prefixlen, NULL, 0, true); in rt6_get_route_info()
3537 if (rt->fib6_nh.nh_dev->ifindex != ifindex) in rt6_get_route_info()
3539 if ((rt->fib6_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) in rt6_get_route_info()
3541 if (!ipv6_addr_equal(&rt->fib6_nh.nh_gw, gwaddr)) in rt6_get_route_info()
3560 .fc_ifindex = dev->ifindex, in rt6_add_route_info()
3575 /* We should treat it as a default route if prefix length is 0. */ in rt6_add_route_info()
3598 for_each_fib6_node_rt_rcu(&table->tb6_root) { in rt6_get_dflt_router()
3599 if (dev == rt->fib6_nh.nh_dev && in rt6_get_dflt_router()
3600 ((rt->fib6_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && in rt6_get_dflt_router()
3601 ipv6_addr_equal(&rt->fib6_nh.nh_gw, addr)) in rt6_get_dflt_router()
3618 .fc_ifindex = dev->ifindex, in rt6_add_dflt_router()
3635 table->flags |= RT6_TABLE_HAS_DFLT_ROUTER; in rt6_add_dflt_router()
3648 for_each_fib6_node_rt_rcu(&table->tb6_root) { in __rt6_purge_dflt_routers()
3652 if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) && in __rt6_purge_dflt_routers()
3653 (!idev || idev->cnf.accept_ra != 2) && in __rt6_purge_dflt_routers()
3662 table->flags &= ~RT6_TABLE_HAS_DFLT_ROUTER; in __rt6_purge_dflt_routers()
3674 head = &net->ipv6.fib_table_hash[h]; in rt6_purge_dflt_routers()
3676 if (table->flags & RT6_TABLE_HAS_DFLT_ROUTER) in rt6_purge_dflt_routers()
3690 cfg->fc_table = l3mdev_fib_table_by_index(net, rtmsg->rtmsg_ifindex) ? in rtmsg_to_fib6_config()
3692 cfg->fc_ifindex = rtmsg->rtmsg_ifindex; in rtmsg_to_fib6_config()
3693 cfg->fc_metric = rtmsg->rtmsg_metric; in rtmsg_to_fib6_config()
3694 cfg->fc_expires = rtmsg->rtmsg_info; in rtmsg_to_fib6_config()
3695 cfg->fc_dst_len = rtmsg->rtmsg_dst_len; in rtmsg_to_fib6_config()
3696 cfg->fc_src_len = rtmsg->rtmsg_src_len; in rtmsg_to_fib6_config()
3697 cfg->fc_flags = rtmsg->rtmsg_flags; in rtmsg_to_fib6_config()
3698 cfg->fc_type = rtmsg->rtmsg_type; in rtmsg_to_fib6_config()
3700 cfg->fc_nlinfo.nl_net = net; in rtmsg_to_fib6_config()
3702 cfg->fc_dst = rtmsg->rtmsg_dst; in rtmsg_to_fib6_config()
3703 cfg->fc_src = rtmsg->rtmsg_src; in rtmsg_to_fib6_config()
3704 cfg->fc_gateway = rtmsg->rtmsg_gateway; in rtmsg_to_fib6_config()
3714 case SIOCADDRT: /* Add a route */ in ipv6_route_ioctl()
3715 case SIOCDELRT: /* Delete a route */ in ipv6_route_ioctl()
3716 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) in ipv6_route_ioctl()
3717 return -EPERM; in ipv6_route_ioctl()
3721 return -EFAULT; in ipv6_route_ioctl()
3734 err = -EINVAL; in ipv6_route_ioctl()
3741 return -EINVAL; in ipv6_route_ioctl()
3754 type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); in ip6_pkt_drop()
3756 IP6_INC_STATS(dev_net(dst->dev), in ip6_pkt_drop()
3757 __in6_dev_get_safely(skb->dev), in ip6_pkt_drop()
3763 IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst), in ip6_pkt_drop()
3779 skb->dev = skb_dst(skb)->dev; in ip6_pkt_discard_out()
3790 skb->dev = skb_dst(skb)->dev; in ip6_pkt_prohibit_out()
3804 struct net_device *dev = idev->dev; in addrconf_f6i_alloc()
3809 return ERR_PTR(-ENOMEM); in addrconf_f6i_alloc()
3811 f6i->dst_nocount = true; in addrconf_f6i_alloc()
3812 f6i->dst_host = true; in addrconf_f6i_alloc()
3813 f6i->fib6_protocol = RTPROT_KERNEL; in addrconf_f6i_alloc()
3814 f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP; in addrconf_f6i_alloc()
3816 f6i->fib6_type = RTN_ANYCAST; in addrconf_f6i_alloc()
3817 f6i->fib6_flags |= RTF_ANYCAST; in addrconf_f6i_alloc()
3819 f6i->fib6_type = RTN_LOCAL; in addrconf_f6i_alloc()
3820 f6i->fib6_flags |= RTF_LOCAL; in addrconf_f6i_alloc()
3823 f6i->fib6_nh.nh_gw = *addr; in addrconf_f6i_alloc()
3825 f6i->fib6_nh.nh_dev = dev; in addrconf_f6i_alloc()
3826 f6i->fib6_dst.addr = *addr; in addrconf_f6i_alloc()
3827 f6i->fib6_dst.plen = 128; in addrconf_f6i_alloc()
3828 tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL; in addrconf_f6i_alloc()
3829 f6i->fib6_table = fib6_get_table(net, tb_id); in addrconf_f6i_alloc()
3843 struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev; in fib6_remove_prefsrc()
3844 struct net *net = ((struct arg_dev_net_ip *)arg)->net; in fib6_remove_prefsrc()
3845 struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; in fib6_remove_prefsrc()
3847 if (((void *)rt->fib6_nh.nh_dev == dev || !dev) && in fib6_remove_prefsrc()
3848 rt != net->ipv6.fib6_null_entry && in fib6_remove_prefsrc()
3849 ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) { in fib6_remove_prefsrc()
3852 rt->fib6_prefsrc.plen = 0; in fib6_remove_prefsrc()
3862 struct net *net = dev_net(ifp->idev->dev); in rt6_remove_prefsrc()
3864 .dev = ifp->idev->dev, in rt6_remove_prefsrc()
3866 .addr = &ifp->addr, in rt6_remove_prefsrc()
3878 if (((rt->fib6_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) && in fib6_clean_tohost()
3879 ipv6_addr_equal(gateway, &rt->fib6_nh.nh_gw)) { in fib6_clean_tohost()
3880 return -1; in fib6_clean_tohost()
3884 * This is needed because cached route may have a different in fib6_clean_tohost()
3910 fn = rcu_dereference_protected(rt->fib6_node, in rt6_multipath_first_sibling()
3911 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
3912 iter = rcu_dereference_protected(fn->leaf, in rt6_multipath_first_sibling()
3913 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
3915 if (iter->fib6_metric == rt->fib6_metric && in rt6_multipath_first_sibling()
3918 iter = rcu_dereference_protected(iter->fib6_next, in rt6_multipath_first_sibling()
3919 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
3927 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD || in rt6_is_dead()
3928 (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN && in rt6_is_dead()
3941 total += rt->fib6_nh.nh_weight; in rt6_multipath_total_weight()
3943 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) { in rt6_multipath_total_weight()
3945 total += iter->fib6_nh.nh_weight; in rt6_multipath_total_weight()
3953 int upper_bound = -1; in rt6_upper_bound_set()
3956 *weight += rt->fib6_nh.nh_weight; in rt6_upper_bound_set()
3958 total) - 1; in rt6_upper_bound_set()
3960 atomic_set(&rt->fib6_nh.nh_upper_bound, upper_bound); in rt6_upper_bound_set()
3970 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_upper_bound_set()
3979 /* In case the entire multipath route was marked for flushing, in rt6_multipath_rebalance()
3981 * sibling route. in rt6_multipath_rebalance()
3983 if (!rt->fib6_nsiblings || rt->should_flush) in rt6_multipath_rebalance()
4001 struct net *net = dev_net(arg->dev); in fib6_ifup()
4003 if (rt != net->ipv6.fib6_null_entry && rt->fib6_nh.nh_dev == arg->dev) { in fib6_ifup()
4004 rt->fib6_nh.nh_flags &= ~arg->nh_flags; in fib6_ifup()
4032 if (rt->fib6_nh.nh_dev == dev) in rt6_multipath_uses_dev()
4034 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_uses_dev()
4035 if (iter->fib6_nh.nh_dev == dev) in rt6_multipath_uses_dev()
4045 rt->should_flush = 1; in rt6_multipath_flush()
4046 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_flush()
4047 iter->should_flush = 1; in rt6_multipath_flush()
4056 if (rt->fib6_nh.nh_dev == down_dev || in rt6_multipath_dead_count()
4057 rt->fib6_nh.nh_flags & RTNH_F_DEAD) in rt6_multipath_dead_count()
4059 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_dead_count()
4060 if (iter->fib6_nh.nh_dev == down_dev || in rt6_multipath_dead_count()
4061 iter->fib6_nh.nh_flags & RTNH_F_DEAD) in rt6_multipath_dead_count()
4073 if (rt->fib6_nh.nh_dev == dev) in rt6_multipath_nh_flags_set()
4074 rt->fib6_nh.nh_flags |= nh_flags; in rt6_multipath_nh_flags_set()
4075 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_nh_flags_set()
4076 if (iter->fib6_nh.nh_dev == dev) in rt6_multipath_nh_flags_set()
4077 iter->fib6_nh.nh_flags |= nh_flags; in rt6_multipath_nh_flags_set()
4084 const struct net_device *dev = arg->dev; in fib6_ifdown()
4087 if (rt == net->ipv6.fib6_null_entry) in fib6_ifdown()
4090 switch (arg->event) { in fib6_ifdown()
4092 return rt->fib6_nh.nh_dev == dev ? -1 : 0; in fib6_ifdown()
4094 if (rt->should_flush) in fib6_ifdown()
4095 return -1; in fib6_ifdown()
4096 if (!rt->fib6_nsiblings) in fib6_ifdown()
4097 return rt->fib6_nh.nh_dev == dev ? -1 : 0; in fib6_ifdown()
4102 if (rt->fib6_nsiblings + 1 == count) { in fib6_ifdown()
4104 return -1; in fib6_ifdown()
4111 return -2; in fib6_ifdown()
4113 if (rt->fib6_nh.nh_dev != dev || in fib6_ifdown()
4114 rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) in fib6_ifdown()
4116 rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN; in fib6_ifdown()
4159 idev = __in6_dev_get(arg->dev); in rt6_mtu_change_route()
4168 if (rt->fib6_nh.nh_dev == arg->dev && in rt6_mtu_change_route()
4170 u32 mtu = rt->fib6_pmtu; in rt6_mtu_change_route()
4172 if (mtu >= arg->mtu || in rt6_mtu_change_route()
4173 (mtu < arg->mtu && mtu == idev->cnf.mtu6)) in rt6_mtu_change_route()
4174 fib6_metric_set(rt, RTAX_MTU, arg->mtu); in rt6_mtu_change_route()
4177 rt6_exceptions_update_pmtu(idev, rt, arg->mtu); in rt6_mtu_change_route()
4227 err = -EINVAL; in rtm_to_fib6_config()
4231 cfg->fc_table = rtm->rtm_table; in rtm_to_fib6_config()
4232 cfg->fc_dst_len = rtm->rtm_dst_len; in rtm_to_fib6_config()
4233 cfg->fc_src_len = rtm->rtm_src_len; in rtm_to_fib6_config()
4234 cfg->fc_flags = RTF_UP; in rtm_to_fib6_config()
4235 cfg->fc_protocol = rtm->rtm_protocol; in rtm_to_fib6_config()
4236 cfg->fc_type = rtm->rtm_type; in rtm_to_fib6_config()
4238 if (rtm->rtm_type == RTN_UNREACHABLE || in rtm_to_fib6_config()
4239 rtm->rtm_type == RTN_BLACKHOLE || in rtm_to_fib6_config()
4240 rtm->rtm_type == RTN_PROHIBIT || in rtm_to_fib6_config()
4241 rtm->rtm_type == RTN_THROW) in rtm_to_fib6_config()
4242 cfg->fc_flags |= RTF_REJECT; in rtm_to_fib6_config()
4244 if (rtm->rtm_type == RTN_LOCAL) in rtm_to_fib6_config()
4245 cfg->fc_flags |= RTF_LOCAL; in rtm_to_fib6_config()
4247 if (rtm->rtm_flags & RTM_F_CLONED) in rtm_to_fib6_config()
4248 cfg->fc_flags |= RTF_CACHE; in rtm_to_fib6_config()
4250 cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK); in rtm_to_fib6_config()
4252 cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid; in rtm_to_fib6_config()
4253 cfg->fc_nlinfo.nlh = nlh; in rtm_to_fib6_config()
4254 cfg->fc_nlinfo.nl_net = sock_net(skb->sk); in rtm_to_fib6_config()
4257 cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]); in rtm_to_fib6_config()
4258 cfg->fc_flags |= RTF_GATEWAY; in rtm_to_fib6_config()
4266 int plen = (rtm->rtm_dst_len + 7) >> 3; in rtm_to_fib6_config()
4271 nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen); in rtm_to_fib6_config()
4275 int plen = (rtm->rtm_src_len + 7) >> 3; in rtm_to_fib6_config()
4280 nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); in rtm_to_fib6_config()
4284 cfg->fc_prefsrc = nla_get_in6_addr(tb[RTA_PREFSRC]); in rtm_to_fib6_config()
4287 cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); in rtm_to_fib6_config()
4290 cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]); in rtm_to_fib6_config()
4293 cfg->fc_mx = nla_data(tb[RTA_METRICS]); in rtm_to_fib6_config()
4294 cfg->fc_mx_len = nla_len(tb[RTA_METRICS]); in rtm_to_fib6_config()
4298 cfg->fc_table = nla_get_u32(tb[RTA_TABLE]); in rtm_to_fib6_config()
4301 cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]); in rtm_to_fib6_config()
4302 cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]); in rtm_to_fib6_config()
4304 err = lwtunnel_valid_encap_type_attr(cfg->fc_mp, in rtm_to_fib6_config()
4305 cfg->fc_mp_len, extack); in rtm_to_fib6_config()
4315 cfg->fc_flags |= RTF_PREF(pref); in rtm_to_fib6_config()
4319 cfg->fc_encap = tb[RTA_ENCAP]; in rtm_to_fib6_config()
4322 cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]); in rtm_to_fib6_config()
4324 err = lwtunnel_valid_encap_type(cfg->fc_encap_type, extack); in rtm_to_fib6_config()
4333 cfg->fc_expires = jiffies_to_clock_t(timeout * HZ); in rtm_to_fib6_config()
4334 cfg->fc_flags |= RTF_EXPIRES; in rtm_to_fib6_config()
4354 …pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6c nexth… in ip6_print_replace_route_err()
4355 &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway, in ip6_print_replace_route_err()
4356 nh->r_cfg.fc_ifindex); in ip6_print_replace_route_err()
4366 int err = -EEXIST; in ip6_route_info_append()
4370 if (rt6_duplicate_nexthop(nh->fib6_info, rt)) in ip6_route_info_append()
4376 return -ENOMEM; in ip6_route_info_append()
4377 nh->fib6_info = rt; in ip6_route_info_append()
4378 memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg)); in ip6_route_info_append()
4379 list_add_tail(&nh->next, rt6_nh_list); in ip6_route_info_append()
4389 /* if this is an APPEND route, then rt points to the first route in ip6_route_mpath_notify()
4390 * inserted and rt_last points to last route inserted. Userspace in ip6_route_mpath_notify()
4391 * wants a consistent dump of the route which starts at the first in ip6_route_mpath_notify()
4393 * the list, find the first sibling of the last route appended in ip6_route_mpath_notify()
4395 if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->fib6_nsiblings) { in ip6_route_mpath_notify()
4396 rt = list_first_entry(&rt_last->fib6_siblings, in ip6_route_mpath_notify()
4409 struct nl_info *info = &cfg->fc_nlinfo; in ip6_route_multipath_add()
4420 int replace = (cfg->fc_nlinfo.nlh && in ip6_route_multipath_add()
4421 (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE)); in ip6_route_multipath_add()
4425 if (info->nlh && info->nlh->nlmsg_flags & NLM_F_APPEND) in ip6_route_multipath_add()
4428 remaining = cfg->fc_mp_len; in ip6_route_multipath_add()
4429 rtnh = (struct rtnexthop *)cfg->fc_mp; in ip6_route_multipath_add()
4436 if (rtnh->rtnh_ifindex) in ip6_route_multipath_add()
4437 r_cfg.fc_ifindex = rtnh->rtnh_ifindex; in ip6_route_multipath_add()
4454 r_cfg.fc_flags |= (rtnh->rtnh_flags & RTNH_F_ONLINK); in ip6_route_multipath_add()
4462 err = -EINVAL; in ip6_route_multipath_add()
4469 rt->fib6_nh.nh_weight = rtnh->rtnh_hops + 1; in ip6_route_multipath_add()
4471 err = ip6_route_info_append(info->nl_net, &rt6_nh_list, in ip6_route_multipath_add()
4483 * the full route when done in ip6_route_multipath_add()
4485 info->skip_notify = 1; in ip6_route_multipath_add()
4489 err = __ip6_ins_rt(nh->fib6_info, info, extack); in ip6_route_multipath_add()
4490 fib6_info_release(nh->fib6_info); in ip6_route_multipath_add()
4493 /* save reference to last route successfully inserted */ in ip6_route_multipath_add()
4494 rt_last = nh->fib6_info; in ip6_route_multipath_add()
4496 /* save reference to first route for notification */ in ip6_route_multipath_add()
4498 rt_notif = nh->fib6_info; in ip6_route_multipath_add()
4501 /* nh->fib6_info is used or freed at this point, reset to NULL*/ in ip6_route_multipath_add()
4502 nh->fib6_info = NULL; in ip6_route_multipath_add()
4510 /* Because each route is added like a single route we remove in ip6_route_multipath_add()
4517 cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | in ip6_route_multipath_add()
4519 cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; in ip6_route_multipath_add()
4523 /* success ... tell user about new route */ in ip6_route_multipath_add()
4539 ip6_route_del(&nh->r_cfg, extack); in ip6_route_multipath_add()
4544 if (nh->fib6_info) in ip6_route_multipath_add()
4545 fib6_info_release(nh->fib6_info); in ip6_route_multipath_add()
4546 list_del(&nh->next); in ip6_route_multipath_add()
4562 remaining = cfg->fc_mp_len; in ip6_route_multipath_del()
4563 rtnh = (struct rtnexthop *)cfg->fc_mp; in ip6_route_multipath_del()
4568 if (rtnh->rtnh_ifindex) in ip6_route_multipath_del()
4569 r_cfg.fc_ifindex = rtnh->rtnh_ifindex; in ip6_route_multipath_del()
4629 if (rt->fib6_nsiblings) { in rt6_nlmsg_size()
4633 + lwtunnel_get_encap_size(rt->fib6_nh.nh_lwtstate); in rt6_nlmsg_size()
4635 nexthop_len *= rt->fib6_nsiblings; in rt6_nlmsg_size()
4651 + lwtunnel_get_encap_size(rt->fib6_nh.nh_lwtstate) in rt6_nlmsg_size()
4658 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD) in rt6_nexthop_info()
4661 if (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN) { in rt6_nexthop_info()
4670 if (rt->fib6_flags & RTF_GATEWAY) { in rt6_nexthop_info()
4671 if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->fib6_nh.nh_gw) < 0) in rt6_nexthop_info()
4675 *flags |= (rt->fib6_nh.nh_flags & RTNH_F_ONLINK); in rt6_nexthop_info()
4676 if (rt->fib6_nh.nh_flags & RTNH_F_OFFLOAD) in rt6_nexthop_info()
4680 if (!skip_oif && rt->fib6_nh.nh_dev && in rt6_nexthop_info()
4681 nla_put_u32(skb, RTA_OIF, rt->fib6_nh.nh_dev->ifindex)) in rt6_nexthop_info()
4684 if (rt->fib6_nh.nh_lwtstate && in rt6_nexthop_info()
4685 lwtunnel_fill_encap(skb, rt->fib6_nh.nh_lwtstate) < 0) in rt6_nexthop_info()
4691 return -EMSGSIZE; in rt6_nexthop_info()
4697 const struct net_device *dev = rt->fib6_nh.nh_dev; in rt6_add_nexthop()
4705 rtnh->rtnh_hops = rt->fib6_nh.nh_weight - 1; in rt6_add_nexthop()
4706 rtnh->rtnh_ifindex = dev ? dev->ifindex : 0; in rt6_add_nexthop()
4711 rtnh->rtnh_flags = flags; in rt6_add_nexthop()
4714 rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh; in rt6_add_nexthop()
4719 return -EMSGSIZE; in rt6_add_nexthop()
4737 return -EMSGSIZE; in rt6_fill_node()
4740 rt6_dst = &rt6->rt6i_dst; in rt6_fill_node()
4741 rt6_src = &rt6->rt6i_src; in rt6_fill_node()
4742 rt6_flags = rt6->rt6i_flags; in rt6_fill_node()
4744 rt6_dst = &rt->fib6_dst; in rt6_fill_node()
4745 rt6_src = &rt->fib6_src; in rt6_fill_node()
4746 rt6_flags = rt->fib6_flags; in rt6_fill_node()
4750 rtm->rtm_family = AF_INET6; in rt6_fill_node()
4751 rtm->rtm_dst_len = rt6_dst->plen; in rt6_fill_node()
4752 rtm->rtm_src_len = rt6_src->plen; in rt6_fill_node()
4753 rtm->rtm_tos = 0; in rt6_fill_node()
4754 if (rt->fib6_table) in rt6_fill_node()
4755 table = rt->fib6_table->tb6_id; in rt6_fill_node()
4758 rtm->rtm_table = table < 256 ? table : RT_TABLE_COMPAT; in rt6_fill_node()
4762 rtm->rtm_type = rt->fib6_type; in rt6_fill_node()
4763 rtm->rtm_flags = 0; in rt6_fill_node()
4764 rtm->rtm_scope = RT_SCOPE_UNIVERSE; in rt6_fill_node()
4765 rtm->rtm_protocol = rt->fib6_protocol; in rt6_fill_node()
4768 rtm->rtm_flags |= RTM_F_CLONED; in rt6_fill_node()
4773 rtm->rtm_dst_len = 128; in rt6_fill_node()
4774 } else if (rtm->rtm_dst_len) in rt6_fill_node()
4775 if (nla_put_in6_addr(skb, RTA_DST, &rt6_dst->addr)) in rt6_fill_node()
4781 rtm->rtm_src_len = 128; in rt6_fill_node()
4782 } else if (rtm->rtm_src_len && in rt6_fill_node()
4783 nla_put_in6_addr(skb, RTA_SRC, &rt6_src->addr)) in rt6_fill_node()
4788 if (ipv6_addr_is_multicast(&rt6_dst->addr)) { in rt6_fill_node()
4806 if (rt->fib6_prefsrc.plen) { in rt6_fill_node()
4808 saddr_buf = rt->fib6_prefsrc.addr; in rt6_fill_node()
4813 pmetrics = dst ? dst_metrics_ptr(dst) : rt->fib6_metrics->metrics; in rt6_fill_node()
4817 if (nla_put_u32(skb, RTA_PRIORITY, rt->fib6_metric)) in rt6_fill_node()
4825 nla_put_in6_addr(skb, RTA_GATEWAY, &rt6->rt6i_gateway)) in rt6_fill_node()
4828 if (dst->dev && nla_put_u32(skb, RTA_OIF, dst->dev->ifindex)) in rt6_fill_node()
4830 } else if (rt->fib6_nsiblings) { in rt6_fill_node()
4842 &rt->fib6_siblings, fib6_siblings) { in rt6_fill_node()
4849 if (rt6_nexthop_info(skb, rt, &rtm->rtm_flags, false) < 0) in rt6_fill_node()
4854 expires = dst ? dst->expires : rt->expires; in rt6_fill_node()
4855 expires -= jiffies; in rt6_fill_node()
4858 if (rtnl_put_cacheinfo(skb, dst, 0, expires, dst ? dst->error : 0) < 0) in rt6_fill_node()
4870 return -EMSGSIZE; in rt6_fill_node()
4876 struct net *net = arg->net; in rt6_dump_route()
4878 if (rt == net->ipv6.fib6_null_entry) in rt6_dump_route()
4881 if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) { in rt6_dump_route()
4882 struct rtmsg *rtm = nlmsg_data(arg->cb->nlh); in rt6_dump_route()
4885 if (rtm->rtm_flags & RTM_F_PREFIX && in rt6_dump_route()
4886 !(rt->fib6_flags & RTF_PREFIX_RT)) { in rt6_dump_route()
4887 /* success since this is not a prefix route */ in rt6_dump_route()
4892 return rt6_fill_node(net, arg->skb, rt, NULL, NULL, NULL, 0, in rt6_dump_route()
4893 RTM_NEWROUTE, NETLINK_CB(arg->cb->skb).portid, in rt6_dump_route()
4894 arg->cb->nlh->nlmsg_seq, NLM_F_MULTI); in rt6_dump_route()
4900 struct net *net = sock_net(in_skb->sk); in inet6_rtm_getroute()
4916 err = -EINVAL; in inet6_rtm_getroute()
4919 fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0); in inet6_rtm_getroute()
4920 fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH); in inet6_rtm_getroute()
4974 err = -ENODEV; in inet6_rtm_getroute()
4994 if (rt->dst.error) { in inet6_rtm_getroute()
4995 err = rt->dst.error; in inet6_rtm_getroute()
5000 if (rt == net->ipv6.ip6_null_entry) { in inet6_rtm_getroute()
5001 err = rt->dst.error; in inet6_rtm_getroute()
5009 err = -ENOBUFS; in inet6_rtm_getroute()
5013 skb_dst_set(skb, &rt->dst); in inet6_rtm_getroute()
5016 from = rcu_dereference(rt->from); in inet6_rtm_getroute()
5022 nlh->nlmsg_seq, 0); in inet6_rtm_getroute()
5027 nlh->nlmsg_seq, 0); in inet6_rtm_getroute()
5029 err = -ENETUNREACH; in inet6_rtm_getroute()
5047 struct net *net = info->nl_net; in inet6_rt_notify()
5051 err = -ENOBUFS; in inet6_rt_notify()
5052 seq = info->nlh ? info->nlh->nlmsg_seq : 0; in inet6_rt_notify()
5059 event, info->portid, seq, nlm_flags); in inet6_rt_notify()
5061 /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ in inet6_rt_notify()
5062 WARN_ON(err == -EMSGSIZE); in inet6_rt_notify()
5066 rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, in inet6_rt_notify()
5067 info->nlh, gfp_any()); in inet6_rt_notify()
5080 if (!(dev->flags & IFF_LOOPBACK)) in ip6_route_dev_notify()
5084 net->ipv6.fib6_null_entry->fib6_nh.nh_dev = dev; in ip6_route_dev_notify()
5085 net->ipv6.ip6_null_entry->dst.dev = dev; in ip6_route_dev_notify()
5086 net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); in ip6_route_dev_notify()
5088 net->ipv6.ip6_prohibit_entry->dst.dev = dev; in ip6_route_dev_notify()
5089 net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); in ip6_route_dev_notify()
5090 net->ipv6.ip6_blk_hole_entry->dst.dev = dev; in ip6_route_dev_notify()
5091 net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); in ip6_route_dev_notify()
5094 dev->reg_state != NETREG_UNREGISTERED) { in ip6_route_dev_notify()
5098 in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); in ip6_route_dev_notify()
5100 in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); in ip6_route_dev_notify()
5101 in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); in ip6_route_dev_notify()
5115 struct net *net = (struct net *)seq->private; in rt6_stats_seq_show()
5117 net->ipv6.rt6_stats->fib_nodes, in rt6_stats_seq_show()
5118 net->ipv6.rt6_stats->fib_route_nodes, in rt6_stats_seq_show()
5119 atomic_read(&net->ipv6.rt6_stats->fib_rt_alloc), in rt6_stats_seq_show()
5120 net->ipv6.rt6_stats->fib_rt_entries, in rt6_stats_seq_show()
5121 net->ipv6.rt6_stats->fib_rt_cache, in rt6_stats_seq_show()
5122 dst_entries_get_slow(&net->ipv6.ip6_dst_ops), in rt6_stats_seq_show()
5123 net->ipv6.rt6_stats->fib_discarded_routes); in rt6_stats_seq_show()
5138 return -EINVAL; in ipv6_sysctl_rtcache_flush()
5140 net = (struct net *)ctl->extra1; in ipv6_sysctl_rtcache_flush()
5141 delay = net->ipv6.sysctl.flush_delay; in ipv6_sysctl_rtcache_flush()
5230 table[0].data = &net->ipv6.sysctl.flush_delay; in ipv6_route_sysctl_init()
5232 table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh; in ipv6_route_sysctl_init()
5233 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; in ipv6_route_sysctl_init()
5234 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; in ipv6_route_sysctl_init()
5235 table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; in ipv6_route_sysctl_init()
5236 table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval; in ipv6_route_sysctl_init()
5237 table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; in ipv6_route_sysctl_init()
5238 table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; in ipv6_route_sysctl_init()
5239 table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; in ipv6_route_sysctl_init()
5240 table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; in ipv6_route_sysctl_init()
5243 if (net->user_ns != &init_user_ns) in ipv6_route_sysctl_init()
5253 int ret = -ENOMEM; in ip6_route_net_init()
5255 memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template, in ip6_route_net_init()
5256 sizeof(net->ipv6.ip6_dst_ops)); in ip6_route_net_init()
5258 if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0) in ip6_route_net_init()
5261 net->ipv6.fib6_null_entry = kmemdup(&fib6_null_entry_template, in ip6_route_net_init()
5262 sizeof(*net->ipv6.fib6_null_entry), in ip6_route_net_init()
5264 if (!net->ipv6.fib6_null_entry) in ip6_route_net_init()
5267 net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, in ip6_route_net_init()
5268 sizeof(*net->ipv6.ip6_null_entry), in ip6_route_net_init()
5270 if (!net->ipv6.ip6_null_entry) in ip6_route_net_init()
5272 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; in ip6_route_net_init()
5273 dst_init_metrics(&net->ipv6.ip6_null_entry->dst, in ip6_route_net_init()
5277 net->ipv6.fib6_has_custom_rules = false; in ip6_route_net_init()
5278 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, in ip6_route_net_init()
5279 sizeof(*net->ipv6.ip6_prohibit_entry), in ip6_route_net_init()
5281 if (!net->ipv6.ip6_prohibit_entry) in ip6_route_net_init()
5283 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; in ip6_route_net_init()
5284 dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst, in ip6_route_net_init()
5287 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, in ip6_route_net_init()
5288 sizeof(*net->ipv6.ip6_blk_hole_entry), in ip6_route_net_init()
5290 if (!net->ipv6.ip6_blk_hole_entry) in ip6_route_net_init()
5292 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; in ip6_route_net_init()
5293 dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, in ip6_route_net_init()
5297 net->ipv6.sysctl.flush_delay = 0; in ip6_route_net_init()
5298 net->ipv6.sysctl.ip6_rt_max_size = 4096; in ip6_route_net_init()
5299 net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2; in ip6_route_net_init()
5300 net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ; in ip6_route_net_init()
5301 net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ; in ip6_route_net_init()
5302 net->ipv6.sysctl.ip6_rt_gc_elasticity = 9; in ip6_route_net_init()
5303 net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; in ip6_route_net_init()
5304 net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; in ip6_route_net_init()
5306 net->ipv6.ip6_rt_gc_expire = 30*HZ; in ip6_route_net_init()
5314 kfree(net->ipv6.ip6_prohibit_entry); in ip6_route_net_init()
5316 kfree(net->ipv6.ip6_null_entry); in ip6_route_net_init()
5319 kfree(net->ipv6.fib6_null_entry); in ip6_route_net_init()
5321 dst_entries_destroy(&net->ipv6.ip6_dst_ops); in ip6_route_net_init()
5328 kfree(net->ipv6.fib6_null_entry); in ip6_route_net_exit()
5329 kfree(net->ipv6.ip6_null_entry); in ip6_route_net_exit()
5331 kfree(net->ipv6.ip6_prohibit_entry); in ip6_route_net_exit()
5332 kfree(net->ipv6.ip6_blk_hole_entry); in ip6_route_net_exit()
5334 dst_entries_destroy(&net->ipv6.ip6_dst_ops); in ip6_route_net_exit()
5340 proc_create_net("ipv6_route", 0, net->proc_net, &ipv6_route_seq_ops, in ip6_route_net_init_late()
5342 proc_create_net_single("rt6_stats", 0444, net->proc_net, in ip6_route_net_init_late()
5351 remove_proc_entry("ipv6_route", net->proc_net); in ip6_route_net_exit_late()
5352 remove_proc_entry("rt6_stats", net->proc_net); in ip6_route_net_exit_late()
5366 return -ENOMEM; in ipv6_inetpeer_init()
5368 net->ipv6.peers = bp; in ipv6_inetpeer_init()
5374 struct inet_peer_base *bp = net->ipv6.peers; in ipv6_inetpeer_exit()
5376 net->ipv6.peers = NULL; in ipv6_inetpeer_exit()
5393 .priority = ADDRCONF_NOTIFY_PRIORITY - 10,
5401 init_net.ipv6.fib6_null_entry->fib6_nh.nh_dev = init_net.loopback_dev; in ip6_route_init_special_entries()
5402 init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; in ip6_route_init_special_entries()
5403 init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); in ip6_route_init_special_entries()
5405 init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; in ip6_route_init_special_entries()
5406 init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); in ip6_route_init_special_entries()
5407 init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; in ip6_route_init_special_entries()
5408 init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); in ip6_route_init_special_entries()
5417 ret = -ENOMEM; in ip6_route_init()
5477 INIT_LIST_HEAD(&ul->head); in ip6_route_init()
5478 spin_lock_init(&ul->lock); in ip6_route_init()