Lines Matching refs:rt
79 static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort);
98 static void rt6_dst_from_metrics_check(struct rt6_info *rt);
99 static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
117 static void rt6_uncached_list_add(struct rt6_info *rt) in rt6_uncached_list_add() argument
121 rt->dst.flags |= DST_NOCACHE; in rt6_uncached_list_add()
122 rt->rt6i_uncached_list = ul; in rt6_uncached_list_add()
125 list_add_tail(&rt->rt6i_uncached, &ul->head); in rt6_uncached_list_add()
129 static void rt6_uncached_list_del(struct rt6_info *rt) in rt6_uncached_list_del() argument
131 if (!list_empty(&rt->rt6i_uncached)) { in rt6_uncached_list_del()
132 struct uncached_list *ul = rt->rt6i_uncached_list; in rt6_uncached_list_del()
135 list_del(&rt->rt6i_uncached); in rt6_uncached_list_del()
150 struct rt6_info *rt; in rt6_uncached_list_flush_dev() local
153 list_for_each_entry(rt, &ul->head, rt6i_uncached) { in rt6_uncached_list_flush_dev()
154 struct inet6_dev *rt_idev = rt->rt6i_idev; in rt6_uncached_list_flush_dev()
155 struct net_device *rt_dev = rt->dst.dev; in rt6_uncached_list_flush_dev()
158 rt->rt6i_idev = in6_dev_get(loopback_dev); in rt6_uncached_list_flush_dev()
163 rt->dst.dev = loopback_dev; in rt6_uncached_list_flush_dev()
164 dev_hold(rt->dst.dev); in rt6_uncached_list_flush_dev()
172 static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt) in rt6_pcpu_cow_metrics() argument
174 return dst_metrics_write_ptr(rt->dst.from); in rt6_pcpu_cow_metrics()
179 struct rt6_info *rt = (struct rt6_info *)dst; in ipv6_cow_metrics() local
181 if (rt->rt6i_flags & RTF_PCPU) in ipv6_cow_metrics()
182 return rt6_pcpu_cow_metrics(rt); in ipv6_cow_metrics()
183 else if (rt->rt6i_flags & RTF_CACHE) in ipv6_cow_metrics()
189 static inline const void *choose_neigh_daddr(struct rt6_info *rt, in choose_neigh_daddr() argument
193 struct in6_addr *p = &rt->rt6i_gateway; in choose_neigh_daddr()
206 struct rt6_info *rt = (struct rt6_info *) dst; in ip6_neigh_lookup() local
209 daddr = choose_neigh_daddr(rt, skb, daddr); in ip6_neigh_lookup()
316 static void rt6_info_init(struct rt6_info *rt) in rt6_info_init() argument
318 struct dst_entry *dst = &rt->dst; in rt6_info_init()
320 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); in rt6_info_init()
321 INIT_LIST_HEAD(&rt->rt6i_siblings); in rt6_info_init()
322 INIT_LIST_HEAD(&rt->rt6i_uncached); in rt6_info_init()
330 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, in __ip6_dst_alloc() local
333 if (rt) in __ip6_dst_alloc()
334 rt6_info_init(rt); in __ip6_dst_alloc()
336 return rt; in __ip6_dst_alloc()
343 struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags); in ip6_dst_alloc() local
345 if (rt) { in ip6_dst_alloc()
346 rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC); in ip6_dst_alloc()
347 if (rt->rt6i_pcpu) { in ip6_dst_alloc()
353 p = per_cpu_ptr(rt->rt6i_pcpu, cpu); in ip6_dst_alloc()
358 dst_destroy((struct dst_entry *)rt); in ip6_dst_alloc()
363 return rt; in ip6_dst_alloc()
369 struct rt6_info *rt = (struct rt6_info *)dst; in ip6_dst_destroy() local
374 free_percpu(rt->rt6i_pcpu); in ip6_dst_destroy()
375 rt6_uncached_list_del(rt); in ip6_dst_destroy()
377 idev = rt->rt6i_idev; in ip6_dst_destroy()
379 rt->rt6i_idev = NULL; in ip6_dst_destroy()
390 struct rt6_info *rt = (struct rt6_info *)dst; in ip6_dst_ifdown() local
391 struct inet6_dev *idev = rt->rt6i_idev; in ip6_dst_ifdown()
400 rt->rt6i_idev = loopback_idev; in ip6_dst_ifdown()
407 static bool __rt6_check_expired(const struct rt6_info *rt) in __rt6_check_expired() argument
409 if (rt->rt6i_flags & RTF_EXPIRES) in __rt6_check_expired()
410 return time_after(jiffies, rt->dst.expires); in __rt6_check_expired()
415 static bool rt6_check_expired(const struct rt6_info *rt) in rt6_check_expired() argument
417 if (rt->rt6i_flags & RTF_EXPIRES) { in rt6_check_expired()
418 if (time_after(jiffies, rt->dst.expires)) in rt6_check_expired()
420 } else if (rt->dst.from) { in rt6_check_expired()
421 return rt6_check_expired((struct rt6_info *) rt->dst.from); in rt6_check_expired()
466 struct rt6_info *rt, in rt6_device_match()
477 for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { in rt6_device_match()
509 return rt; in rt6_device_match()
531 static void rt6_probe(struct rt6_info *rt) in rt6_probe() argument
543 if (!rt || !(rt->rt6i_flags & RTF_GATEWAY)) in rt6_probe()
546 neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); in rt6_probe()
556 rt->rt6i_idev->cnf.rtr_probe_interval)) { in rt6_probe()
568 work->target = rt->rt6i_gateway; in rt6_probe()
569 dev_hold(rt->dst.dev); in rt6_probe()
570 work->dev = rt->dst.dev; in rt6_probe()
578 static inline void rt6_probe(struct rt6_info *rt) in rt6_probe() argument
586 static inline int rt6_check_dev(struct rt6_info *rt, int oif) in rt6_check_dev() argument
588 struct net_device *dev = rt->dst.dev; in rt6_check_dev()
592 rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif) in rt6_check_dev()
597 static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt) in rt6_check_neigh() argument
602 if (rt->rt6i_flags & RTF_NONEXTHOP || in rt6_check_neigh()
603 !(rt->rt6i_flags & RTF_GATEWAY)) in rt6_check_neigh()
607 neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); in rt6_check_neigh()
628 static int rt6_score_route(struct rt6_info *rt, int oif, in rt6_score_route() argument
633 m = rt6_check_dev(rt, oif); in rt6_score_route()
637 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; in rt6_score_route()
640 int n = rt6_check_neigh(rt); in rt6_score_route()
647 static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, in find_match() argument
653 struct inet6_dev *idev = rt->rt6i_idev; in find_match()
654 struct net_device *dev = rt->dst.dev; in find_match()
660 if (rt6_check_expired(rt)) in find_match()
663 m = rt6_score_route(rt, oif, strict); in find_match()
672 rt6_probe(rt); in find_match()
678 match = rt; in find_match()
689 struct rt6_info *rt, *match, *cont; in find_rr_leaf() local
694 for (rt = rr_head; rt; rt = rt->dst.rt6_next) { in find_rr_leaf()
695 if (rt->rt6i_metric != metric) { in find_rr_leaf()
696 cont = rt; in find_rr_leaf()
700 match = find_match(rt, oif, strict, &mpri, match, do_rr); in find_rr_leaf()
703 for (rt = fn->leaf; rt && rt != rr_head; rt = rt->dst.rt6_next) { in find_rr_leaf()
704 if (rt->rt6i_metric != metric) { in find_rr_leaf()
705 cont = rt; in find_rr_leaf()
709 match = find_match(rt, oif, strict, &mpri, match, do_rr); in find_rr_leaf()
715 for (rt = cont; rt; rt = rt->dst.rt6_next) in find_rr_leaf()
716 match = find_match(rt, oif, strict, &mpri, match, do_rr); in find_rr_leaf()
749 static bool rt6_is_gw_or_nonexthop(const struct rt6_info *rt) in rt6_is_gw_or_nonexthop() argument
751 return (rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY)); in rt6_is_gw_or_nonexthop()
762 struct rt6_info *rt; in rt6_route_rcv() local
800 rt = rt6_get_dflt_router(gwaddr, dev); in rt6_route_rcv()
802 rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr); in rt6_route_rcv()
804 if (rt && !lifetime) { in rt6_route_rcv()
805 ip6_del_rt(rt); in rt6_route_rcv()
806 rt = NULL; in rt6_route_rcv()
809 if (!rt && lifetime) in rt6_route_rcv()
810 rt = rt6_add_route_info(dev, prefix, rinfo->prefix_len, gwaddr, pref); in rt6_route_rcv()
811 else if (rt) in rt6_route_rcv()
812 rt->rt6i_flags = RTF_ROUTEINFO | in rt6_route_rcv()
813 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); in rt6_route_rcv()
815 if (rt) { in rt6_route_rcv()
817 rt6_clean_expires(rt); in rt6_route_rcv()
819 rt6_set_expires(rt, jiffies + HZ * lifetime); in rt6_route_rcv()
821 ip6_rt_put(rt); in rt6_route_rcv()
849 struct rt6_info *rt; in ip6_pol_route_lookup() local
857 rt = fn->leaf; in ip6_pol_route_lookup()
858 rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); in ip6_pol_route_lookup()
859 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) in ip6_pol_route_lookup()
860 rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags); in ip6_pol_route_lookup()
861 if (rt == net->ipv6.ip6_null_entry) { in ip6_pol_route_lookup()
866 dst_use(&rt->dst, jiffies); in ip6_pol_route_lookup()
868 return rt; in ip6_pol_route_lookup()
910 static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info, in __ip6_ins_rt() argument
916 table = rt->rt6i_table; in __ip6_ins_rt()
918 err = fib6_add(&table->tb6_root, rt, info, mxc); in __ip6_ins_rt()
924 int ip6_ins_rt(struct rt6_info *rt) in ip6_ins_rt() argument
926 struct nl_info info = { .nl_net = dev_net(rt->dst.dev), }; in ip6_ins_rt()
929 return __ip6_ins_rt(rt, &info, &mxc); in ip6_ins_rt()
936 struct rt6_info *rt; in ip6_rt_cache_alloc() local
945 rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0); in ip6_rt_cache_alloc()
947 if (!rt) in ip6_rt_cache_alloc()
950 ip6_rt_copy_init(rt, ort); in ip6_rt_cache_alloc()
951 rt->rt6i_flags |= RTF_CACHE; in ip6_rt_cache_alloc()
952 rt->rt6i_metric = 0; in ip6_rt_cache_alloc()
953 rt->dst.flags |= DST_HOST; in ip6_rt_cache_alloc()
954 rt->rt6i_dst.addr = *daddr; in ip6_rt_cache_alloc()
955 rt->rt6i_dst.plen = 128; in ip6_rt_cache_alloc()
960 rt->rt6i_flags |= RTF_ANYCAST; in ip6_rt_cache_alloc()
962 if (rt->rt6i_src.plen && saddr) { in ip6_rt_cache_alloc()
963 rt->rt6i_src.addr = *saddr; in ip6_rt_cache_alloc()
964 rt->rt6i_src.plen = 128; in ip6_rt_cache_alloc()
969 return rt; in ip6_rt_cache_alloc()
972 static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt) in ip6_rt_pcpu_alloc() argument
976 pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev), in ip6_rt_pcpu_alloc()
977 rt->dst.dev, rt->dst.flags); in ip6_rt_pcpu_alloc()
981 ip6_rt_copy_init(pcpu_rt, rt); in ip6_rt_pcpu_alloc()
982 pcpu_rt->rt6i_protocol = rt->rt6i_protocol; in ip6_rt_pcpu_alloc()
988 static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt) in rt6_get_pcpu_route() argument
992 p = this_cpu_ptr(rt->rt6i_pcpu); in rt6_get_pcpu_route()
1002 static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt) in rt6_make_pcpu_route() argument
1004 struct fib6_table *table = rt->rt6i_table; in rt6_make_pcpu_route()
1007 pcpu_rt = ip6_rt_pcpu_alloc(rt); in rt6_make_pcpu_route()
1009 struct net *net = dev_net(rt->dst.dev); in rt6_make_pcpu_route()
1016 if (rt->rt6i_pcpu) { in rt6_make_pcpu_route()
1017 p = this_cpu_ptr(rt->rt6i_pcpu); in rt6_make_pcpu_route()
1032 pcpu_rt = rt; in rt6_make_pcpu_route()
1044 struct rt6_info *rt; in ip6_pol_route() local
1060 rt = rt6_select(fn, oif, strict); in ip6_pol_route()
1061 if (rt->rt6i_nsiblings) in ip6_pol_route()
1062 rt = rt6_multipath_select(rt, fl6, oif, strict); in ip6_pol_route()
1063 if (rt == net->ipv6.ip6_null_entry) { in ip6_pol_route()
1076 if (rt == net->ipv6.ip6_null_entry || (rt->rt6i_flags & RTF_CACHE)) { in ip6_pol_route()
1077 dst_use(&rt->dst, jiffies); in ip6_pol_route()
1080 rt6_dst_from_metrics_check(rt); in ip6_pol_route()
1081 return rt; in ip6_pol_route()
1083 !(rt->rt6i_flags & RTF_GATEWAY))) { in ip6_pol_route()
1092 dst_use(&rt->dst, jiffies); in ip6_pol_route()
1095 uncached_rt = ip6_rt_cache_alloc(rt, &fl6->daddr, NULL); in ip6_pol_route()
1096 dst_release(&rt->dst); in ip6_pol_route()
1111 rt->dst.lastuse = jiffies; in ip6_pol_route()
1112 rt->dst.__use++; in ip6_pol_route()
1113 pcpu_rt = rt6_get_pcpu_route(rt); in ip6_pol_route()
1122 dst_hold(&rt->dst); in ip6_pol_route()
1124 pcpu_rt = rt6_make_pcpu_route(rt); in ip6_pol_route()
1125 dst_release(&rt->dst); in ip6_pol_route()
1205 struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig; in ip6_blackhole_route() local
1208 rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0); in ip6_blackhole_route()
1209 if (rt) { in ip6_blackhole_route()
1210 rt6_info_init(rt); in ip6_blackhole_route()
1212 new = &rt->dst; in ip6_blackhole_route()
1218 rt->rt6i_idev = ort->rt6i_idev; in ip6_blackhole_route()
1219 if (rt->rt6i_idev) in ip6_blackhole_route()
1220 in6_dev_hold(rt->rt6i_idev); in ip6_blackhole_route()
1222 rt->rt6i_gateway = ort->rt6i_gateway; in ip6_blackhole_route()
1223 rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU; in ip6_blackhole_route()
1224 rt->rt6i_metric = 0; in ip6_blackhole_route()
1226 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); in ip6_blackhole_route()
1228 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); in ip6_blackhole_route()
1242 static void rt6_dst_from_metrics_check(struct rt6_info *rt) in rt6_dst_from_metrics_check() argument
1244 if (rt->dst.from && in rt6_dst_from_metrics_check()
1245 dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from)) in rt6_dst_from_metrics_check()
1246 dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true); in rt6_dst_from_metrics_check()
1249 static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie) in rt6_check() argument
1253 if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie) in rt6_check()
1256 if (rt6_check_expired(rt)) in rt6_check()
1259 return &rt->dst; in rt6_check()
1262 static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie) in rt6_dst_from_check() argument
1264 if (!__rt6_check_expired(rt) && in rt6_dst_from_check()
1265 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && in rt6_dst_from_check()
1266 rt6_check((struct rt6_info *)(rt->dst.from), cookie)) in rt6_dst_from_check()
1267 return &rt->dst; in rt6_dst_from_check()
1274 struct rt6_info *rt; in ip6_dst_check() local
1276 rt = (struct rt6_info *) dst; in ip6_dst_check()
1283 rt6_dst_from_metrics_check(rt); in ip6_dst_check()
1285 if (rt->rt6i_flags & RTF_PCPU || in ip6_dst_check()
1286 (unlikely(dst->flags & DST_NOCACHE) && rt->dst.from)) in ip6_dst_check()
1287 return rt6_dst_from_check(rt, cookie); in ip6_dst_check()
1289 return rt6_check(rt, cookie); in ip6_dst_check()
1294 struct rt6_info *rt = (struct rt6_info *) dst; in ip6_negative_advice() local
1296 if (rt) { in ip6_negative_advice()
1297 if (rt->rt6i_flags & RTF_CACHE) { in ip6_negative_advice()
1298 if (rt6_check_expired(rt)) { in ip6_negative_advice()
1299 ip6_del_rt(rt); in ip6_negative_advice()
1312 struct rt6_info *rt; in ip6_link_failure() local
1316 rt = (struct rt6_info *) skb_dst(skb); in ip6_link_failure()
1317 if (rt) { in ip6_link_failure()
1318 if (rt->rt6i_flags & RTF_CACHE) { in ip6_link_failure()
1319 dst_hold(&rt->dst); in ip6_link_failure()
1320 ip6_del_rt(rt); in ip6_link_failure()
1325 fn = rcu_dereference(rt->rt6i_node); in ip6_link_failure()
1326 if (fn && (rt->rt6i_flags & RTF_DEFAULT)) in ip6_link_failure()
1333 static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu) in rt6_do_update_pmtu() argument
1335 struct net *net = dev_net(rt->dst.dev); in rt6_do_update_pmtu()
1337 rt->rt6i_flags |= RTF_MODIFIED; in rt6_do_update_pmtu()
1338 rt->rt6i_pmtu = mtu; in rt6_do_update_pmtu()
1339 rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); in rt6_do_update_pmtu()
1342 static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) in rt6_cache_allowed_for_pmtu() argument
1344 return !(rt->rt6i_flags & RTF_CACHE) && in rt6_cache_allowed_for_pmtu()
1345 (rt->rt6i_flags & RTF_PCPU || in rt6_cache_allowed_for_pmtu()
1346 rcu_access_pointer(rt->rt6i_node)); in rt6_cache_allowed_for_pmtu()
1442 struct rt6_info *rt; in __ip6_route_redirect() local
1458 for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { in __ip6_route_redirect()
1459 if (rt6_check_expired(rt)) in __ip6_route_redirect()
1461 if (rt->dst.error) in __ip6_route_redirect()
1463 if (!(rt->rt6i_flags & RTF_GATEWAY)) in __ip6_route_redirect()
1465 if (fl6->flowi6_oif != rt->dst.dev->ifindex) in __ip6_route_redirect()
1467 if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) in __ip6_route_redirect()
1472 if (!rt) in __ip6_route_redirect()
1473 rt = net->ipv6.ip6_null_entry; in __ip6_route_redirect()
1474 else if (rt->dst.error) { in __ip6_route_redirect()
1475 rt = net->ipv6.ip6_null_entry; in __ip6_route_redirect()
1479 if (rt == net->ipv6.ip6_null_entry) { in __ip6_route_redirect()
1486 dst_hold(&rt->dst); in __ip6_route_redirect()
1490 return rt; in __ip6_route_redirect()
1581 const struct rt6_info *rt = (const struct rt6_info *)dst; in ip6_mtu() local
1582 unsigned int mtu = rt->rt6i_pmtu; in ip6_mtu()
1611 struct rt6_info *rt; in icmp6_dst_alloc() local
1618 rt = ip6_dst_alloc(net, dev, 0); in icmp6_dst_alloc()
1619 if (unlikely(!rt)) { in icmp6_dst_alloc()
1625 rt->dst.flags |= DST_HOST; in icmp6_dst_alloc()
1626 rt->dst.input = ip6_input; in icmp6_dst_alloc()
1627 rt->dst.output = ip6_output; in icmp6_dst_alloc()
1628 atomic_set(&rt->dst.__refcnt, 1); in icmp6_dst_alloc()
1629 rt->rt6i_gateway = fl6->daddr; in icmp6_dst_alloc()
1630 rt->rt6i_dst.addr = fl6->daddr; in icmp6_dst_alloc()
1631 rt->rt6i_dst.plen = 128; in icmp6_dst_alloc()
1632 rt->rt6i_idev = idev; in icmp6_dst_alloc()
1633 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); in icmp6_dst_alloc()
1636 rt->dst.next = icmp6_dst_gc_list; in icmp6_dst_alloc()
1637 icmp6_dst_gc_list = &rt->dst; in icmp6_dst_alloc()
1642 dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); in icmp6_dst_alloc()
1671 static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg), in icmp6_clean_all() argument
1679 struct rt6_info *rt = (struct rt6_info *) dst; in icmp6_clean_all() local
1680 if (func(rt, arg)) { in icmp6_clean_all()
1780 struct rt6_info *rt; in ip6_nh_lookup_table() local
1790 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags); in ip6_nh_lookup_table()
1793 if (rt == net->ipv6.ip6_null_entry) { in ip6_nh_lookup_table()
1794 ip6_rt_put(rt); in ip6_nh_lookup_table()
1795 rt = NULL; in ip6_nh_lookup_table()
1798 return rt; in ip6_nh_lookup_table()
1804 struct rt6_info *rt = NULL; in ip6_route_info_create() local
1849 rt = ip6_dst_alloc(net, NULL, in ip6_route_info_create()
1852 if (!rt) { in ip6_route_info_create()
1858 rt6_set_expires(rt, jiffies + in ip6_route_info_create()
1861 rt6_clean_expires(rt); in ip6_route_info_create()
1865 rt->rt6i_protocol = cfg->fc_protocol; in ip6_route_info_create()
1870 rt->dst.input = ip6_mc_input; in ip6_route_info_create()
1872 rt->dst.input = ip6_input; in ip6_route_info_create()
1874 rt->dst.input = ip6_forward; in ip6_route_info_create()
1876 rt->dst.output = ip6_output; in ip6_route_info_create()
1886 rt->dst.lwtstate = lwtstate_get(lwtstate); in ip6_route_info_create()
1887 if (lwtunnel_output_redirect(rt->dst.lwtstate)) { in ip6_route_info_create()
1888 rt->dst.lwtstate->orig_output = rt->dst.output; in ip6_route_info_create()
1889 rt->dst.output = lwtunnel_output; in ip6_route_info_create()
1891 if (lwtunnel_input_redirect(rt->dst.lwtstate)) { in ip6_route_info_create()
1892 rt->dst.lwtstate->orig_input = rt->dst.input; in ip6_route_info_create()
1893 rt->dst.input = lwtunnel_input; in ip6_route_info_create()
1897 ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); in ip6_route_info_create()
1898 rt->rt6i_dst.plen = cfg->fc_dst_len; in ip6_route_info_create()
1899 if (rt->rt6i_dst.plen == 128) in ip6_route_info_create()
1900 rt->dst.flags |= DST_HOST; in ip6_route_info_create()
1903 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); in ip6_route_info_create()
1904 rt->rt6i_src.plen = cfg->fc_src_len; in ip6_route_info_create()
1907 rt->rt6i_metric = cfg->fc_metric; in ip6_route_info_create()
1930 rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; in ip6_route_info_create()
1933 rt->dst.error = -EINVAL; in ip6_route_info_create()
1934 rt->dst.output = dst_discard_out; in ip6_route_info_create()
1935 rt->dst.input = dst_discard; in ip6_route_info_create()
1938 rt->dst.error = -EACCES; in ip6_route_info_create()
1939 rt->dst.output = ip6_pkt_prohibit_out; in ip6_route_info_create()
1940 rt->dst.input = ip6_pkt_prohibit; in ip6_route_info_create()
1945 rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN in ip6_route_info_create()
1948 rt->dst.output = ip6_pkt_discard_out; in ip6_route_info_create()
1949 rt->dst.input = ip6_pkt_discard; in ip6_route_info_create()
1973 rt->rt6i_gateway = *gw_addr; in ip6_route_info_create()
2030 rt->rt6i_prefsrc.addr = cfg->fc_prefsrc; in ip6_route_info_create()
2031 rt->rt6i_prefsrc.plen = 128; in ip6_route_info_create()
2033 rt->rt6i_prefsrc.plen = 0; in ip6_route_info_create()
2035 rt->rt6i_flags = cfg->fc_flags; in ip6_route_info_create()
2038 rt->dst.dev = dev; in ip6_route_info_create()
2039 rt->rt6i_idev = idev; in ip6_route_info_create()
2040 rt->rt6i_table = table; in ip6_route_info_create()
2044 return rt; in ip6_route_info_create()
2050 if (rt) in ip6_route_info_create()
2051 dst_free(&rt->dst); in ip6_route_info_create()
2059 struct rt6_info *rt; in ip6_route_add() local
2062 rt = ip6_route_info_create(cfg); in ip6_route_add()
2063 if (IS_ERR(rt)) { in ip6_route_add()
2064 err = PTR_ERR(rt); in ip6_route_add()
2065 rt = NULL; in ip6_route_add()
2073 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc); in ip6_route_add()
2079 if (rt) in ip6_route_add()
2080 dst_free(&rt->dst); in ip6_route_add()
2085 static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) in __ip6_del_rt() argument
2089 struct net *net = dev_net(rt->dst.dev); in __ip6_del_rt()
2091 if (rt == net->ipv6.ip6_null_entry || in __ip6_del_rt()
2092 rt->dst.flags & DST_NOCACHE) { in __ip6_del_rt()
2097 table = rt->rt6i_table; in __ip6_del_rt()
2099 err = fib6_del(rt, info); in __ip6_del_rt()
2103 ip6_rt_put(rt); in __ip6_del_rt()
2107 int ip6_del_rt(struct rt6_info *rt) in ip6_del_rt() argument
2110 .nl_net = dev_net(rt->dst.dev), in ip6_del_rt()
2112 return __ip6_del_rt(rt, &info); in ip6_del_rt()
2119 struct rt6_info *rt; in ip6_route_del() local
2133 for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { in ip6_route_del()
2134 if ((rt->rt6i_flags & RTF_CACHE) && in ip6_route_del()
2138 (!rt->dst.dev || in ip6_route_del()
2139 rt->dst.dev->ifindex != cfg->fc_ifindex)) in ip6_route_del()
2142 !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) in ip6_route_del()
2144 if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) in ip6_route_del()
2146 if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol) in ip6_route_del()
2148 dst_hold(&rt->dst); in ip6_route_del()
2151 return __ip6_del_rt(rt, &cfg->fc_nlinfo); in ip6_route_del()
2162 struct rt6_info *rt, *nrt = NULL; in rt6_do_redirect() local
2220 rt = (struct rt6_info *) dst; in rt6_do_redirect()
2221 if (rt->rt6i_flags & RTF_REJECT) { in rt6_do_redirect()
2230 dst_confirm(&rt->dst); in rt6_do_redirect()
2247 nrt = ip6_rt_cache_alloc(rt, &msg->dest, NULL); in rt6_do_redirect()
2260 netevent.old = &rt->dst; in rt6_do_redirect()
2266 if (rt->rt6i_flags & RTF_CACHE) { in rt6_do_redirect()
2267 rt = (struct rt6_info *) dst_clone(&rt->dst); in rt6_do_redirect()
2268 ip6_del_rt(rt); in rt6_do_redirect()
2279 static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) in rt6_set_from() argument
2283 rt->rt6i_flags &= ~RTF_EXPIRES; in rt6_set_from()
2285 rt->dst.from = &from->dst; in rt6_set_from()
2286 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true); in rt6_set_from()
2289 static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort) in ip6_rt_copy_init() argument
2291 rt->dst.input = ort->dst.input; in ip6_rt_copy_init()
2292 rt->dst.output = ort->dst.output; in ip6_rt_copy_init()
2293 rt->rt6i_dst = ort->rt6i_dst; in ip6_rt_copy_init()
2294 rt->dst.error = ort->dst.error; in ip6_rt_copy_init()
2295 rt->rt6i_idev = ort->rt6i_idev; in ip6_rt_copy_init()
2296 if (rt->rt6i_idev) in ip6_rt_copy_init()
2297 in6_dev_hold(rt->rt6i_idev); in ip6_rt_copy_init()
2298 rt->dst.lastuse = jiffies; in ip6_rt_copy_init()
2299 rt->rt6i_gateway = ort->rt6i_gateway; in ip6_rt_copy_init()
2300 rt->rt6i_flags = ort->rt6i_flags; in ip6_rt_copy_init()
2301 rt6_set_from(rt, ort); in ip6_rt_copy_init()
2302 rt->rt6i_metric = ort->rt6i_metric; in ip6_rt_copy_init()
2304 rt->rt6i_src = ort->rt6i_src; in ip6_rt_copy_init()
2306 rt->rt6i_prefsrc = ort->rt6i_prefsrc; in ip6_rt_copy_init()
2307 rt->rt6i_table = ort->rt6i_table; in ip6_rt_copy_init()
2308 rt->dst.lwtstate = lwtstate_get(ort->dst.lwtstate); in ip6_rt_copy_init()
2317 struct rt6_info *rt = NULL; in rt6_get_route_info() local
2330 for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { in rt6_get_route_info()
2331 if (rt->dst.dev->ifindex != dev->ifindex) in rt6_get_route_info()
2333 if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) in rt6_get_route_info()
2335 if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) in rt6_get_route_info()
2337 dst_hold(&rt->dst); in rt6_get_route_info()
2342 return rt; in rt6_get_route_info()
2376 struct rt6_info *rt; in rt6_get_dflt_router() local
2385 for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { in rt6_get_dflt_router()
2386 if (dev == rt->dst.dev && in rt6_get_dflt_router()
2387 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && in rt6_get_dflt_router()
2388 ipv6_addr_equal(&rt->rt6i_gateway, addr)) in rt6_get_dflt_router()
2391 if (rt) in rt6_get_dflt_router()
2392 dst_hold(&rt->dst); in rt6_get_dflt_router()
2394 return rt; in rt6_get_dflt_router()
2420 int rt6_addrconf_purge(struct rt6_info *rt, void *arg) { in rt6_addrconf_purge() argument
2421 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && in rt6_addrconf_purge()
2422 (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) in rt6_addrconf_purge()
2550 struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, in addrconf_dst_alloc() local
2552 if (!rt) in addrconf_dst_alloc()
2557 rt->dst.flags |= DST_HOST; in addrconf_dst_alloc()
2558 rt->dst.input = ip6_input; in addrconf_dst_alloc()
2559 rt->dst.output = ip6_output; in addrconf_dst_alloc()
2560 rt->rt6i_idev = idev; in addrconf_dst_alloc()
2562 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; in addrconf_dst_alloc()
2564 rt->rt6i_flags |= RTF_ANYCAST; in addrconf_dst_alloc()
2566 rt->rt6i_flags |= RTF_LOCAL; in addrconf_dst_alloc()
2568 rt->rt6i_gateway = *addr; in addrconf_dst_alloc()
2569 rt->rt6i_dst.addr = *addr; in addrconf_dst_alloc()
2570 rt->rt6i_dst.plen = 128; in addrconf_dst_alloc()
2572 rt->rt6i_table = fib6_get_table(net, tb_id); in addrconf_dst_alloc()
2573 rt->dst.flags |= DST_NOCACHE; in addrconf_dst_alloc()
2575 atomic_set(&rt->dst.__refcnt, 1); in addrconf_dst_alloc()
2577 return rt; in addrconf_dst_alloc()
2581 struct rt6_info *rt, in ip6_route_get_saddr() argument
2587 rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL; in ip6_route_get_saddr()
2589 if (rt && rt->rt6i_prefsrc.plen) in ip6_route_get_saddr()
2590 *saddr = rt->rt6i_prefsrc.addr; in ip6_route_get_saddr()
2604 static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) in fib6_remove_prefsrc() argument
2610 if (((void *)rt->dst.dev == dev || !dev) && in fib6_remove_prefsrc()
2611 rt != net->ipv6.ip6_null_entry && in fib6_remove_prefsrc()
2612 ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { in fib6_remove_prefsrc()
2614 rt->rt6i_prefsrc.plen = 0; in fib6_remove_prefsrc()
2634 static int fib6_clean_tohost(struct rt6_info *rt, void *arg) in fib6_clean_tohost() argument
2638 if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) || in fib6_clean_tohost()
2639 ((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) && in fib6_clean_tohost()
2640 ipv6_addr_equal(gateway, &rt->rt6i_gateway)) { in fib6_clean_tohost()
2656 static int fib6_ifdown(struct rt6_info *rt, void *arg) in fib6_ifdown() argument
2661 if ((rt->dst.dev == dev || !dev) && in fib6_ifdown()
2662 rt != adn->net->ipv6.ip6_null_entry) in fib6_ifdown()
2686 static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) in rt6_mtu_change_route() argument
2715 if (rt->dst.dev == arg->dev && in rt6_mtu_change_route()
2716 !dst_metric_locked(&rt->dst, RTAX_MTU)) { in rt6_mtu_change_route()
2717 if (rt->rt6i_flags & RTF_CACHE) { in rt6_mtu_change_route()
2723 if (rt->rt6i_pmtu && rt->rt6i_pmtu > arg->mtu) in rt6_mtu_change_route()
2724 rt->rt6i_pmtu = arg->mtu; in rt6_mtu_change_route()
2725 } else if (dst_mtu(&rt->dst) >= arg->mtu || in rt6_mtu_change_route()
2726 (dst_mtu(&rt->dst) < arg->mtu && in rt6_mtu_change_route()
2727 dst_mtu(&rt->dst) == idev->cnf.mtu6)) { in rt6_mtu_change_route()
2728 dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu); in rt6_mtu_change_route()
2881 struct rt6_info *rt, struct fib6_config *r_cfg) in ip6_route_info_append() argument
2888 if (rt6_duplicate_nexthop(nh->rt6_info, rt)) in ip6_route_info_append()
2895 nh->rt6_info = rt; in ip6_route_info_append()
2911 struct rt6_info *rt; in ip6_route_multipath_add() local
2948 rt = ip6_route_info_create(&r_cfg); in ip6_route_multipath_add()
2949 if (IS_ERR(rt)) { in ip6_route_multipath_add()
2950 err = PTR_ERR(rt); in ip6_route_multipath_add()
2951 rt = NULL; in ip6_route_multipath_add()
2955 err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg); in ip6_route_multipath_add()
2957 dst_free(&rt->dst); in ip6_route_multipath_add()
3080 static inline size_t rt6_nlmsg_size(struct rt6_info *rt) in rt6_nlmsg_size() argument
3095 + lwtunnel_get_encap_size(rt->dst.lwtstate); in rt6_nlmsg_size()
3099 struct sk_buff *skb, struct rt6_info *rt, in rt6_fill_node() argument
3111 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { in rt6_fill_node()
3123 rtm->rtm_dst_len = rt->rt6i_dst.plen; in rt6_fill_node()
3124 rtm->rtm_src_len = rt->rt6i_src.plen; in rt6_fill_node()
3126 if (rt->rt6i_table) in rt6_fill_node()
3127 table = rt->rt6i_table->tb6_id; in rt6_fill_node()
3133 if (rt->rt6i_flags & RTF_REJECT) { in rt6_fill_node()
3134 switch (rt->dst.error) { in rt6_fill_node()
3149 else if (rt->rt6i_flags & RTF_LOCAL) in rt6_fill_node()
3151 else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) in rt6_fill_node()
3156 if (!netif_carrier_ok(rt->dst.dev)) { in rt6_fill_node()
3158 if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown) in rt6_fill_node()
3162 rtm->rtm_protocol = rt->rt6i_protocol; in rt6_fill_node()
3163 if (rt->rt6i_flags & RTF_DYNAMIC) in rt6_fill_node()
3165 else if (rt->rt6i_flags & RTF_ADDRCONF) { in rt6_fill_node()
3166 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO)) in rt6_fill_node()
3172 if (rt->rt6i_flags & RTF_CACHE) in rt6_fill_node()
3180 if (nla_put_in6_addr(skb, RTA_DST, &rt->rt6i_dst.addr)) in rt6_fill_node()
3188 nla_put_in6_addr(skb, RTA_SRC, &rt->rt6i_src.addr)) in rt6_fill_node()
3193 if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { in rt6_fill_node()
3213 if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0 && in rt6_fill_node()
3218 if (rt->rt6i_prefsrc.plen) { in rt6_fill_node()
3220 saddr_buf = rt->rt6i_prefsrc.addr; in rt6_fill_node()
3225 memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics)); in rt6_fill_node()
3226 if (rt->rt6i_pmtu) in rt6_fill_node()
3227 metrics[RTAX_MTU - 1] = rt->rt6i_pmtu; in rt6_fill_node()
3231 if (rt->rt6i_flags & RTF_GATEWAY) { in rt6_fill_node()
3232 if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0) in rt6_fill_node()
3236 if (rt->dst.dev && in rt6_fill_node()
3237 nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) in rt6_fill_node()
3239 if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric)) in rt6_fill_node()
3242 expires = (rt->rt6i_flags & RTF_EXPIRES) ? rt->dst.expires - jiffies : 0; in rt6_fill_node()
3244 if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0) in rt6_fill_node()
3247 if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags))) in rt6_fill_node()
3250 if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0) in rt6_fill_node()
3261 int rt6_dump_route(struct rt6_info *rt, void *p_arg) in rt6_dump_route() argument
3273 arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, in rt6_dump_route()
3282 struct rt6_info *rt; in inet6_rtm_getroute() local
3339 rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6, in inet6_rtm_getroute()
3349 rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6); in inet6_rtm_getroute()
3354 ip6_rt_put(rt); in inet6_rtm_getroute()
3365 skb_dst_set(skb, &rt->dst); in inet6_rtm_getroute()
3367 err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, in inet6_rtm_getroute()
3380 void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info, in inet6_rt_notify() argument
3391 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); in inet6_rt_notify()
3395 err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, in inet6_rt_notify()