Lines Matching refs:rt

105 			 struct fib6_info *rt, struct dst_entry *dst,
132 void rt6_uncached_list_add(struct rt6_info *rt) in rt6_uncached_list_add() argument
136 rt->rt6i_uncached_list = ul; in rt6_uncached_list_add()
139 list_add_tail(&rt->rt6i_uncached, &ul->head); in rt6_uncached_list_add()
143 void rt6_uncached_list_del(struct rt6_info *rt) in rt6_uncached_list_del() argument
145 if (!list_empty(&rt->rt6i_uncached)) { in rt6_uncached_list_del()
146 struct uncached_list *ul = rt->rt6i_uncached_list; in rt6_uncached_list_del()
147 struct net *net = dev_net(rt->dst.dev); in rt6_uncached_list_del()
150 list_del(&rt->rt6i_uncached); in rt6_uncached_list_del()
166 struct rt6_info *rt; in rt6_uncached_list_flush_dev() local
169 list_for_each_entry(rt, &ul->head, rt6i_uncached) { in rt6_uncached_list_flush_dev()
170 struct inet6_dev *rt_idev = rt->rt6i_idev; in rt6_uncached_list_flush_dev()
171 struct net_device *rt_dev = rt->dst.dev; in rt6_uncached_list_flush_dev()
174 rt->rt6i_idev = in6_dev_get(loopback_dev); in rt6_uncached_list_flush_dev()
179 rt->dst.dev = blackhole_netdev; in rt6_uncached_list_flush_dev()
180 dev_hold(rt->dst.dev); in rt6_uncached_list_flush_dev()
219 const struct rt6_info *rt = container_of(dst, struct rt6_info, dst); in ip6_dst_neigh_lookup() local
221 return ip6_neigh_lookup(rt6_nexthop(rt, &in6addr_any), in ip6_dst_neigh_lookup()
228 struct rt6_info *rt = (struct rt6_info *)dst; in ip6_confirm_neigh() local
230 daddr = choose_neigh_daddr(rt6_nexthop(rt, &in6addr_any), NULL, daddr); in ip6_confirm_neigh()
341 static void rt6_info_init(struct rt6_info *rt) in rt6_info_init() argument
343 struct dst_entry *dst = &rt->dst; in rt6_info_init()
345 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); in rt6_info_init()
346 INIT_LIST_HEAD(&rt->rt6i_uncached); in rt6_info_init()
353 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, in ip6_dst_alloc() local
356 if (rt) { in ip6_dst_alloc()
357 rt6_info_init(rt); in ip6_dst_alloc()
361 return rt; in ip6_dst_alloc()
367 struct rt6_info *rt = (struct rt6_info *)dst; in ip6_dst_destroy() local
372 rt6_uncached_list_del(rt); in ip6_dst_destroy()
374 idev = rt->rt6i_idev; in ip6_dst_destroy()
376 rt->rt6i_idev = NULL; in ip6_dst_destroy()
380 from = xchg((__force struct fib6_info **)&rt->from, NULL); in ip6_dst_destroy()
387 struct rt6_info *rt = (struct rt6_info *)dst; in ip6_dst_ifdown() local
388 struct inet6_dev *idev = rt->rt6i_idev; in ip6_dst_ifdown()
395 rt->rt6i_idev = loopback_idev; in ip6_dst_ifdown()
401 static bool __rt6_check_expired(const struct rt6_info *rt) in __rt6_check_expired() argument
403 if (rt->rt6i_flags & RTF_EXPIRES) in __rt6_check_expired()
404 return time_after(jiffies, rt->dst.expires); in __rt6_check_expired()
409 static bool rt6_check_expired(const struct rt6_info *rt) in rt6_check_expired() argument
413 from = rcu_dereference(rt->from); in rt6_check_expired()
415 if (rt->rt6i_flags & RTF_EXPIRES) { in rt6_check_expired()
416 if (time_after(jiffies, rt->dst.expires)) in rt6_check_expired()
419 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK || in rt6_check_expired()
941 struct fib6_info *rt; in rt6_route_rcv() local
979 rt = rt6_get_dflt_router(net, gwaddr, dev); in rt6_route_rcv()
981 rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, in rt6_route_rcv()
984 if (rt && !lifetime) { in rt6_route_rcv()
985 ip6_del_rt(net, rt); in rt6_route_rcv()
986 rt = NULL; in rt6_route_rcv()
989 if (!rt && lifetime) in rt6_route_rcv()
990 rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, in rt6_route_rcv()
992 else if (rt) in rt6_route_rcv()
993 rt->fib6_flags = RTF_ROUTEINFO | in rt6_route_rcv()
994 (rt->fib6_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); in rt6_route_rcv()
996 if (rt) { in rt6_route_rcv()
998 fib6_clean_expires(rt); in rt6_route_rcv()
1000 fib6_set_expires(rt, jiffies + HZ * lifetime); in rt6_route_rcv()
1002 fib6_info_release(rt); in rt6_route_rcv()
1055 static unsigned short fib6_info_dst_flags(struct fib6_info *rt) in fib6_info_dst_flags() argument
1059 if (rt->dst_nocount) in fib6_info_dst_flags()
1061 if (rt->dst_nopolicy) in fib6_info_dst_flags()
1063 if (rt->dst_host) in fib6_info_dst_flags()
1069 static void ip6_rt_init_dst_reject(struct rt6_info *rt, u8 fib6_type) in ip6_rt_init_dst_reject() argument
1071 rt->dst.error = ip6_rt_type_to_error(fib6_type); in ip6_rt_init_dst_reject()
1075 rt->dst.output = dst_discard_out; in ip6_rt_init_dst_reject()
1076 rt->dst.input = dst_discard; in ip6_rt_init_dst_reject()
1079 rt->dst.output = ip6_pkt_prohibit_out; in ip6_rt_init_dst_reject()
1080 rt->dst.input = ip6_pkt_prohibit; in ip6_rt_init_dst_reject()
1085 rt->dst.output = ip6_pkt_discard_out; in ip6_rt_init_dst_reject()
1086 rt->dst.input = ip6_pkt_discard; in ip6_rt_init_dst_reject()
1091 static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res) in ip6_rt_init_dst() argument
1096 ip6_rt_init_dst_reject(rt, res->fib6_type); in ip6_rt_init_dst()
1100 rt->dst.error = 0; in ip6_rt_init_dst()
1101 rt->dst.output = ip6_output; in ip6_rt_init_dst()
1104 rt->dst.input = ip6_input; in ip6_rt_init_dst()
1106 rt->dst.input = ip6_mc_input; in ip6_rt_init_dst()
1108 rt->dst.input = ip6_forward; in ip6_rt_init_dst()
1112 rt->dst.lwtstate = lwtstate_get(res->nh->fib_nh_lws); in ip6_rt_init_dst()
1113 lwtunnel_set_redirect(&rt->dst); in ip6_rt_init_dst()
1116 rt->dst.lastuse = jiffies; in ip6_rt_init_dst()
1120 static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from) in rt6_set_from() argument
1122 rt->rt6i_flags &= ~RTF_EXPIRES; in rt6_set_from()
1123 rcu_assign_pointer(rt->from, from); in rt6_set_from()
1124 ip_dst_init_metrics(&rt->dst, from->fib6_metrics); in rt6_set_from()
1128 static void ip6_rt_copy_init(struct rt6_info *rt, const struct fib6_result *res) in ip6_rt_copy_init() argument
1134 ip6_rt_init_dst(rt, res); in ip6_rt_copy_init()
1136 rt->rt6i_dst = f6i->fib6_dst; in ip6_rt_copy_init()
1137 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL; in ip6_rt_copy_init()
1138 rt->rt6i_flags = res->fib6_flags; in ip6_rt_copy_init()
1140 rt->rt6i_gateway = nh->fib_nh_gw6; in ip6_rt_copy_init()
1141 rt->rt6i_flags |= RTF_GATEWAY; in ip6_rt_copy_init()
1143 rt6_set_from(rt, f6i); in ip6_rt_copy_init()
1145 rt->rt6i_src = f6i->fib6_src; in ip6_rt_copy_init()
1169 struct rt6_info *rt = *prt; in ip6_hold_safe() local
1171 if (dst_hold_safe(&rt->dst)) in ip6_hold_safe()
1174 rt = net->ipv6.ip6_null_entry; in ip6_hold_safe()
1175 dst_hold(&rt->dst); in ip6_hold_safe()
1177 rt = NULL; in ip6_hold_safe()
1179 *prt = rt; in ip6_hold_safe()
1218 struct rt6_info *rt; in ip6_pol_route_lookup() local
1238 rt = net->ipv6.ip6_null_entry; in ip6_pol_route_lookup()
1239 dst_hold(&rt->dst); in ip6_pol_route_lookup()
1249 rt = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr); in ip6_pol_route_lookup()
1250 if (rt) { in ip6_pol_route_lookup()
1251 if (ip6_hold_safe(net, &rt)) in ip6_pol_route_lookup()
1252 dst_use_noref(&rt->dst, jiffies); in ip6_pol_route_lookup()
1255 rt = ip6_create_rt_rcu(&res); in ip6_pol_route_lookup()
1263 return rt; in ip6_pol_route_lookup()
1305 static int __ip6_ins_rt(struct fib6_info *rt, struct nl_info *info, in __ip6_ins_rt() argument
1311 table = rt->fib6_table; in __ip6_ins_rt()
1313 err = fib6_add(&table->tb6_root, rt, info, extack); in __ip6_ins_rt()
1319 int ip6_ins_rt(struct net *net, struct fib6_info *rt) in ip6_ins_rt() argument
1323 return __ip6_ins_rt(rt, &info, NULL); in ip6_ins_rt()
1332 struct rt6_info *rt; in ip6_rt_cache_alloc() local
1342 rt = ip6_dst_alloc(dev_net(dev), dev, 0); in ip6_rt_cache_alloc()
1343 if (!rt) { in ip6_rt_cache_alloc()
1348 ip6_rt_copy_init(rt, res); in ip6_rt_cache_alloc()
1349 rt->rt6i_flags |= RTF_CACHE; in ip6_rt_cache_alloc()
1350 rt->dst.flags |= DST_HOST; in ip6_rt_cache_alloc()
1351 rt->rt6i_dst.addr = *daddr; in ip6_rt_cache_alloc()
1352 rt->rt6i_dst.plen = 128; in ip6_rt_cache_alloc()
1357 rt->rt6i_flags |= RTF_ANYCAST; in ip6_rt_cache_alloc()
1359 if (rt->rt6i_src.plen && saddr) { in ip6_rt_cache_alloc()
1360 rt->rt6i_src.addr = *saddr; in ip6_rt_cache_alloc()
1361 rt->rt6i_src.plen = 128; in ip6_rt_cache_alloc()
1366 return rt; in ip6_rt_cache_alloc()
1809 const struct rt6_info *rt) in fib6_nh_remove_exception() argument
1830 src_key = &rt->rt6i_src.addr; in fib6_nh_remove_exception()
1833 &rt->rt6i_dst.addr, in fib6_nh_remove_exception()
1847 struct rt6_info *rt; member
1856 err = fib6_nh_remove_exception(nh, arg->plen, arg->rt); in rt6_nh_remove_exception_rt()
1863 static int rt6_remove_exception_rt(struct rt6_info *rt) in rt6_remove_exception_rt() argument
1867 from = rcu_dereference(rt->from); in rt6_remove_exception_rt()
1868 if (!from || !(rt->rt6i_flags & RTF_CACHE)) in rt6_remove_exception_rt()
1873 .rt = rt, in rt6_remove_exception_rt()
1886 from->fib6_src.plen, rt); in rt6_remove_exception_rt()
1893 const struct rt6_info *rt) in fib6_nh_update_exception() argument
1908 src_key = &rt->rt6i_src.addr; in fib6_nh_update_exception()
1910 rt6_ex = __rt6_find_exception_rcu(&bucket, &rt->rt6i_dst.addr, src_key); in fib6_nh_update_exception()
1938 static void rt6_update_exception_stamp_rt(struct rt6_info *rt) in rt6_update_exception_stamp_rt() argument
1945 from = rcu_dereference(rt->from); in rt6_update_exception_stamp_rt()
1946 if (!from || !(rt->rt6i_flags & RTF_CACHE)) in rt6_update_exception_stamp_rt()
1951 .dev = rt->dst.dev, in rt6_update_exception_stamp_rt()
1952 .gw = &rt->rt6i_gateway, in rt6_update_exception_stamp_rt()
1963 fib6_nh_update_exception(fib6_nh, from->fib6_src.plen, rt); in rt6_update_exception_stamp_rt()
1969 struct rt6_info *rt, int mtu) in rt6_mtu_change_route_allowed() argument
1981 if (dst_mtu(&rt->dst) >= mtu) in rt6_mtu_change_route_allowed()
1984 if (dst_mtu(&rt->dst) == idev->cnf.mtu6) in rt6_mtu_change_route_allowed()
2057 struct rt6_info *rt = rt6_ex->rt6i; in rt6_age_examine_exception() local
2065 if (!(rt->rt6i_flags & RTF_EXPIRES)) { in rt6_age_examine_exception()
2066 if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) { in rt6_age_examine_exception()
2067 RT6_TRACE("aging clone %p\n", rt); in rt6_age_examine_exception()
2071 } else if (time_after(jiffies, rt->dst.expires)) { in rt6_age_examine_exception()
2072 RT6_TRACE("purging expired route %p\n", rt); in rt6_age_examine_exception()
2077 if (rt->rt6i_flags & RTF_GATEWAY) { in rt6_age_examine_exception()
2081 neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); in rt6_age_examine_exception()
2087 rt); in rt6_age_examine_exception()
2191 struct rt6_info *rt = NULL; in ip6_pol_route() local
2211 rt = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr); in ip6_pol_route()
2212 if (rt) { in ip6_pol_route()
2221 rt = ip6_rt_cache_alloc(&res, &fl6->daddr, NULL); in ip6_pol_route()
2223 if (rt) { in ip6_pol_route()
2229 rt6_uncached_list_add(rt); in ip6_pol_route()
2233 return rt; in ip6_pol_route()
2238 rt = rt6_get_pcpu_route(&res); in ip6_pol_route()
2240 if (!rt) in ip6_pol_route()
2241 rt = rt6_make_pcpu_route(net, &res); in ip6_pol_route()
2246 if (!rt) in ip6_pol_route()
2247 rt = net->ipv6.ip6_null_entry; in ip6_pol_route()
2249 ip6_hold_safe(net, &rt); in ip6_pol_route()
2252 return rt; in ip6_pol_route()
2516 struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig; in ip6_blackhole_route() local
2520 rt = dst_alloc(&ip6_dst_blackhole_ops, loopback_dev, 1, in ip6_blackhole_route()
2522 if (rt) { in ip6_blackhole_route()
2523 rt6_info_init(rt); in ip6_blackhole_route()
2526 new = &rt->dst; in ip6_blackhole_route()
2533 rt->rt6i_idev = in6_dev_get(loopback_dev); in ip6_blackhole_route()
2534 rt->rt6i_gateway = ort->rt6i_gateway; in ip6_blackhole_route()
2535 rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU; in ip6_blackhole_route()
2537 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); in ip6_blackhole_route()
2539 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); in ip6_blackhole_route()
2564 static struct dst_entry *rt6_check(struct rt6_info *rt, in rt6_check() argument
2574 if (rt6_check_expired(rt)) in rt6_check()
2577 return &rt->dst; in rt6_check()
2580 static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, in rt6_dst_from_check() argument
2584 if (!__rt6_check_expired(rt) && in rt6_dst_from_check()
2585 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && in rt6_dst_from_check()
2587 return &rt->dst; in rt6_dst_from_check()
2596 struct rt6_info *rt; in ip6_dst_check() local
2598 rt = container_of(dst, struct rt6_info, dst); in ip6_dst_check()
2607 from = rcu_dereference(rt->from); in ip6_dst_check()
2609 if (from && (rt->rt6i_flags & RTF_PCPU || in ip6_dst_check()
2610 unlikely(!list_empty(&rt->rt6i_uncached)))) in ip6_dst_check()
2611 dst_ret = rt6_dst_from_check(rt, from, cookie); in ip6_dst_check()
2613 dst_ret = rt6_check(rt, from, cookie); in ip6_dst_check()
2622 struct rt6_info *rt = (struct rt6_info *) dst; in ip6_negative_advice() local
2624 if (rt) { in ip6_negative_advice()
2625 if (rt->rt6i_flags & RTF_CACHE) { in ip6_negative_advice()
2627 if (rt6_check_expired(rt)) { in ip6_negative_advice()
2628 rt6_remove_exception_rt(rt); in ip6_negative_advice()
2642 struct rt6_info *rt; in ip6_link_failure() local
2646 rt = (struct rt6_info *) skb_dst(skb); in ip6_link_failure()
2647 if (rt) { in ip6_link_failure()
2649 if (rt->rt6i_flags & RTF_CACHE) { in ip6_link_failure()
2650 rt6_remove_exception_rt(rt); in ip6_link_failure()
2655 from = rcu_dereference(rt->from); in ip6_link_failure()
2658 if (fn && (rt->rt6i_flags & RTF_DEFAULT)) in ip6_link_failure()
2682 static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu) in rt6_do_update_pmtu() argument
2684 struct net *net = dev_net(rt->dst.dev); in rt6_do_update_pmtu()
2686 dst_metric_set(&rt->dst, RTAX_MTU, mtu); in rt6_do_update_pmtu()
2687 rt->rt6i_flags |= RTF_MODIFIED; in rt6_do_update_pmtu()
2688 rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); in rt6_do_update_pmtu()
2691 static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) in rt6_cache_allowed_for_pmtu() argument
2693 return !(rt->rt6i_flags & RTF_CACHE) && in rt6_cache_allowed_for_pmtu()
2694 (rt->rt6i_flags & RTF_PCPU || rcu_access_pointer(rt->from)); in rt6_cache_allowed_for_pmtu()
2901 struct fib6_info *rt; in __ip6_route_redirect() local
2924 res.f6i = rt; in __ip6_route_redirect()
2925 if (fib6_check_expired(rt)) in __ip6_route_redirect()
2927 if (rt->fib6_flags & RTF_REJECT) in __ip6_route_redirect()
2929 if (unlikely(rt->nh)) { in __ip6_route_redirect()
2930 if (nexthop_is_blackhole(rt->nh)) in __ip6_route_redirect()
2933 if (nexthop_for_each_fib6_nh(rt->nh, in __ip6_route_redirect()
2938 res.nh = rt->fib6_nh; in __ip6_route_redirect()
2945 if (!rt) in __ip6_route_redirect()
2946 rt = net->ipv6.fib6_null_entry; in __ip6_route_redirect()
2947 else if (rt->fib6_flags & RTF_REJECT) { in __ip6_route_redirect()
2952 if (rt == net->ipv6.fib6_null_entry) { in __ip6_route_redirect()
2958 res.f6i = rt; in __ip6_route_redirect()
2959 res.nh = rt->fib6_nh; in __ip6_route_redirect()
3096 struct rt6_info *rt; in ip6_mtu_from_fib6() local
3105 rt = rt6_find_cached_rt(res, daddr, saddr); in ip6_mtu_from_fib6()
3106 if (unlikely(rt)) { in ip6_mtu_from_fib6()
3107 mtu = dst_metric_raw(&rt->dst, RTAX_MTU); in ip6_mtu_from_fib6()
3126 struct rt6_info *rt; in icmp6_dst_alloc() local
3133 rt = ip6_dst_alloc(net, dev, 0); in icmp6_dst_alloc()
3134 if (unlikely(!rt)) { in icmp6_dst_alloc()
3140 rt->dst.flags |= DST_HOST; in icmp6_dst_alloc()
3141 rt->dst.input = ip6_input; in icmp6_dst_alloc()
3142 rt->dst.output = ip6_output; in icmp6_dst_alloc()
3143 rt->rt6i_gateway = fl6->daddr; in icmp6_dst_alloc()
3144 rt->rt6i_dst.addr = fl6->daddr; in icmp6_dst_alloc()
3145 rt->rt6i_dst.plen = 128; in icmp6_dst_alloc()
3146 rt->rt6i_idev = idev; in icmp6_dst_alloc()
3147 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); in icmp6_dst_alloc()
3152 rt6_uncached_list_add(rt); in icmp6_dst_alloc()
3155 dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); in icmp6_dst_alloc()
3544 struct fib6_info *rt = NULL; in ip6_route_info_create() local
3610 rt = fib6_info_alloc(gfp_flags, !nh); in ip6_route_info_create()
3611 if (!rt) in ip6_route_info_create()
3614 rt->fib6_metrics = ip_fib_metrics_init(net, cfg->fc_mx, cfg->fc_mx_len, in ip6_route_info_create()
3616 if (IS_ERR(rt->fib6_metrics)) { in ip6_route_info_create()
3617 err = PTR_ERR(rt->fib6_metrics); in ip6_route_info_create()
3619 rt->fib6_metrics = (struct dst_metrics *)&dst_default_metrics; in ip6_route_info_create()
3624 rt->dst_nocount = true; in ip6_route_info_create()
3627 fib6_set_expires(rt, jiffies + in ip6_route_info_create()
3630 fib6_clean_expires(rt); in ip6_route_info_create()
3634 rt->fib6_protocol = cfg->fc_protocol; in ip6_route_info_create()
3636 rt->fib6_table = table; in ip6_route_info_create()
3637 rt->fib6_metric = cfg->fc_metric; in ip6_route_info_create()
3638 rt->fib6_type = cfg->fc_type ? : RTN_UNICAST; in ip6_route_info_create()
3639 rt->fib6_flags = cfg->fc_flags & ~RTF_GATEWAY; in ip6_route_info_create()
3641 ipv6_addr_prefix(&rt->fib6_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); in ip6_route_info_create()
3642 rt->fib6_dst.plen = cfg->fc_dst_len; in ip6_route_info_create()
3643 if (rt->fib6_dst.plen == 128) in ip6_route_info_create()
3644 rt->dst_host = true; in ip6_route_info_create()
3647 ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len); in ip6_route_info_create()
3648 rt->fib6_src.plen = cfg->fc_src_len; in ip6_route_info_create()
3655 if (rt->fib6_src.plen) { in ip6_route_info_create()
3659 rt->nh = nh; in ip6_route_info_create()
3660 fib6_nh = nexthop_fib6_nh(rt->nh); in ip6_route_info_create()
3662 err = fib6_nh_init(net, rt->fib6_nh, cfg, gfp_flags, extack); in ip6_route_info_create()
3666 fib6_nh = rt->fib6_nh; in ip6_route_info_create()
3672 if (fib6_is_reject(cfg->fc_flags, rt->fib6_nh->fib_nh_dev, in ip6_route_info_create()
3674 rt->fib6_flags = RTF_REJECT | RTF_NONEXTHOP; in ip6_route_info_create()
3685 rt->fib6_prefsrc.addr = cfg->fc_prefsrc; in ip6_route_info_create()
3686 rt->fib6_prefsrc.plen = 128; in ip6_route_info_create()
3688 rt->fib6_prefsrc.plen = 0; in ip6_route_info_create()
3690 return rt; in ip6_route_info_create()
3692 fib6_info_release(rt); in ip6_route_info_create()
3699 struct fib6_info *rt; in ip6_route_add() local
3702 rt = ip6_route_info_create(cfg, gfp_flags, extack); in ip6_route_add()
3703 if (IS_ERR(rt)) in ip6_route_add()
3704 return PTR_ERR(rt); in ip6_route_add()
3706 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack); in ip6_route_add()
3707 fib6_info_release(rt); in ip6_route_add()
3712 static int __ip6_del_rt(struct fib6_info *rt, struct nl_info *info) in __ip6_del_rt() argument
3718 if (rt == net->ipv6.fib6_null_entry) { in __ip6_del_rt()
3723 table = rt->fib6_table; in __ip6_del_rt()
3725 err = fib6_del(rt, info); in __ip6_del_rt()
3729 fib6_info_release(rt); in __ip6_del_rt()
3733 int ip6_del_rt(struct net *net, struct fib6_info *rt) in ip6_del_rt() argument
3737 return __ip6_del_rt(rt, &info); in ip6_del_rt()
3740 static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg) in __ip6_del_rt_siblings() argument
3748 if (rt == net->ipv6.fib6_null_entry) in __ip6_del_rt_siblings()
3750 table = rt->fib6_table; in __ip6_del_rt_siblings()
3753 if (rt->fib6_nsiblings && cfg->fc_delete_all_nh) { in __ip6_del_rt_siblings()
3757 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); in __ip6_del_rt_siblings()
3761 if (rt6_fill_node(net, skb, rt, NULL, in __ip6_del_rt_siblings()
3773 rt, in __ip6_del_rt_siblings()
3774 rt->fib6_nsiblings, in __ip6_del_rt_siblings()
3777 &rt->fib6_siblings, in __ip6_del_rt_siblings()
3785 err = fib6_del(rt, info); in __ip6_del_rt_siblings()
3789 fib6_info_release(rt); in __ip6_del_rt_siblings()
3798 static int __ip6_del_cached_rt(struct rt6_info *rt, struct fib6_config *cfg) in __ip6_del_cached_rt() argument
3802 if (cfg->fc_ifindex && rt->dst.dev->ifindex != cfg->fc_ifindex) in __ip6_del_cached_rt()
3806 !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) in __ip6_del_cached_rt()
3809 rc = rt6_remove_exception_rt(rt); in __ip6_del_cached_rt()
3814 static int ip6_del_cached_rt(struct fib6_config *cfg, struct fib6_info *rt, in ip6_del_cached_rt() argument
3818 .f6i = rt, in ip6_del_cached_rt()
3858 struct fib6_info *rt; in ip6_route_del() local
3879 if (rt->nh && cfg->fc_nh_id && in ip6_route_del()
3880 rt->nh->id != cfg->fc_nh_id) in ip6_route_del()
3886 if (rt->nh) { in ip6_route_del()
3887 rc = ip6_del_cached_rt_nh(cfg, rt); in ip6_route_del()
3891 nh = rt->fib6_nh; in ip6_route_del()
3892 rc = ip6_del_cached_rt(cfg, rt, nh); in ip6_route_del()
3901 if (cfg->fc_metric && cfg->fc_metric != rt->fib6_metric) in ip6_route_del()
3904 cfg->fc_protocol != rt->fib6_protocol) in ip6_route_del()
3907 if (rt->nh) { in ip6_route_del()
3908 if (!fib6_info_hold_safe(rt)) in ip6_route_del()
3912 return __ip6_del_rt(rt, &cfg->fc_nlinfo); in ip6_route_del()
3917 nh = rt->fib6_nh; in ip6_route_del()
3925 if (!fib6_info_hold_safe(rt)) in ip6_route_del()
3931 return __ip6_del_rt(rt, &cfg->fc_nlinfo); in ip6_route_del()
3933 return __ip6_del_rt_siblings(rt, cfg); in ip6_route_del()
3944 struct rt6_info *rt, *nrt = NULL; in rt6_do_redirect() local
4003 rt = (struct rt6_info *) dst; in rt6_do_redirect()
4004 if (rt->rt6i_flags & RTF_REJECT) { in rt6_do_redirect()
4013 dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr); in rt6_do_redirect()
4031 res.f6i = rcu_dereference(rt->from); in rt6_do_redirect()
4038 .gw = &rt->rt6i_gateway, in rt6_do_redirect()
4072 netevent.old = &rt->dst; in rt6_do_redirect()
4092 struct fib6_info *rt = NULL; in rt6_get_route_info() local
4106 if (rt->nh) in rt6_get_route_info()
4108 if (rt->fib6_nh->fib_nh_dev->ifindex != ifindex) in rt6_get_route_info()
4110 if (!(rt->fib6_flags & RTF_ROUTEINFO) || in rt6_get_route_info()
4111 !rt->fib6_nh->fib_nh_gw_family) in rt6_get_route_info()
4113 if (!ipv6_addr_equal(&rt->fib6_nh->fib_nh_gw6, gwaddr)) in rt6_get_route_info()
4115 if (!fib6_info_hold_safe(rt)) in rt6_get_route_info()
4121 return rt; in rt6_get_route_info()
4162 struct fib6_info *rt; in rt6_get_dflt_router() local
4174 if (rt->nh) in rt6_get_dflt_router()
4177 nh = rt->fib6_nh; in rt6_get_dflt_router()
4179 ((rt->fib6_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && in rt6_get_dflt_router()
4183 if (rt && !fib6_info_hold_safe(rt)) in rt6_get_dflt_router()
4184 rt = NULL; in rt6_get_dflt_router()
4186 return rt; in rt6_get_dflt_router()
4223 struct fib6_info *rt; in __rt6_purge_dflt_routers() local
4228 struct net_device *dev = fib6_info_nh_dev(rt); in __rt6_purge_dflt_routers()
4231 if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) && in __rt6_purge_dflt_routers()
4233 fib6_info_hold_safe(rt)) { in __rt6_purge_dflt_routers()
4235 ip6_del_rt(net, rt); in __rt6_purge_dflt_routers()
4426 static int fib6_remove_prefsrc(struct fib6_info *rt, void *arg) in fib6_remove_prefsrc() argument
4432 if (!rt->nh && in fib6_remove_prefsrc()
4433 ((void *)rt->fib6_nh->fib_nh_dev == dev || !dev) && in fib6_remove_prefsrc()
4434 rt != net->ipv6.fib6_null_entry && in fib6_remove_prefsrc()
4435 ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) { in fib6_remove_prefsrc()
4438 rt->fib6_prefsrc.plen = 0; in fib6_remove_prefsrc()
4458 static int fib6_clean_tohost(struct fib6_info *rt, void *arg) in fib6_clean_tohost() argument
4464 if (rt->nh) in fib6_clean_tohost()
4467 nh = rt->fib6_nh; in fib6_clean_tohost()
4468 if (((rt->fib6_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) && in fib6_clean_tohost()
4494 static struct fib6_info *rt6_multipath_first_sibling(const struct fib6_info *rt) in rt6_multipath_first_sibling() argument
4499 fn = rcu_dereference_protected(rt->fib6_node, in rt6_multipath_first_sibling()
4500 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
4502 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
4504 if (iter->fib6_metric == rt->fib6_metric && in rt6_multipath_first_sibling()
4508 lockdep_is_held(&rt->fib6_table->tb6_lock)); in rt6_multipath_first_sibling()
4515 static bool rt6_is_dead(const struct fib6_info *rt) in rt6_is_dead() argument
4517 if (rt->fib6_nh->fib_nh_flags & RTNH_F_DEAD || in rt6_is_dead()
4518 (rt->fib6_nh->fib_nh_flags & RTNH_F_LINKDOWN && in rt6_is_dead()
4519 ip6_ignore_linkdown(rt->fib6_nh->fib_nh_dev))) in rt6_is_dead()
4525 static int rt6_multipath_total_weight(const struct fib6_info *rt) in rt6_multipath_total_weight() argument
4530 if (!rt6_is_dead(rt)) in rt6_multipath_total_weight()
4531 total += rt->fib6_nh->fib_nh_weight; in rt6_multipath_total_weight()
4533 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) { in rt6_multipath_total_weight()
4541 static void rt6_upper_bound_set(struct fib6_info *rt, int *weight, int total) in rt6_upper_bound_set() argument
4545 if (!rt6_is_dead(rt)) { in rt6_upper_bound_set()
4546 *weight += rt->fib6_nh->fib_nh_weight; in rt6_upper_bound_set()
4550 atomic_set(&rt->fib6_nh->fib_nh_upper_bound, upper_bound); in rt6_upper_bound_set()
4553 static void rt6_multipath_upper_bound_set(struct fib6_info *rt, int total) in rt6_multipath_upper_bound_set() argument
4558 rt6_upper_bound_set(rt, &weight, total); in rt6_multipath_upper_bound_set()
4560 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_upper_bound_set()
4564 void rt6_multipath_rebalance(struct fib6_info *rt) in rt6_multipath_rebalance() argument
4573 if (!rt->fib6_nsiblings || rt->should_flush) in rt6_multipath_rebalance()
4580 first = rt6_multipath_first_sibling(rt); in rt6_multipath_rebalance()
4588 static int fib6_ifup(struct fib6_info *rt, void *p_arg) in fib6_ifup() argument
4593 if (rt != net->ipv6.fib6_null_entry && !rt->nh && in fib6_ifup()
4594 rt->fib6_nh->fib_nh_dev == arg->dev) { in fib6_ifup()
4595 rt->fib6_nh->fib_nh_flags &= ~arg->nh_flags; in fib6_ifup()
4596 fib6_update_sernum_upto_root(net, rt); in fib6_ifup()
4597 rt6_multipath_rebalance(rt); in fib6_ifup()
4619 static bool rt6_multipath_uses_dev(const struct fib6_info *rt, in rt6_multipath_uses_dev() argument
4624 if (rt->fib6_nh->fib_nh_dev == dev) in rt6_multipath_uses_dev()
4626 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_uses_dev()
4633 static void rt6_multipath_flush(struct fib6_info *rt) in rt6_multipath_flush() argument
4637 rt->should_flush = 1; in rt6_multipath_flush()
4638 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_flush()
4642 static unsigned int rt6_multipath_dead_count(const struct fib6_info *rt, in rt6_multipath_dead_count() argument
4648 if (rt->fib6_nh->fib_nh_dev == down_dev || in rt6_multipath_dead_count()
4649 rt->fib6_nh->fib_nh_flags & RTNH_F_DEAD) in rt6_multipath_dead_count()
4651 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_dead_count()
4659 static void rt6_multipath_nh_flags_set(struct fib6_info *rt, in rt6_multipath_nh_flags_set() argument
4665 if (rt->fib6_nh->fib_nh_dev == dev) in rt6_multipath_nh_flags_set()
4666 rt->fib6_nh->fib_nh_flags |= nh_flags; in rt6_multipath_nh_flags_set()
4667 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) in rt6_multipath_nh_flags_set()
4673 static int fib6_ifdown(struct fib6_info *rt, void *p_arg) in fib6_ifdown() argument
4679 if (rt == net->ipv6.fib6_null_entry || rt->nh) in fib6_ifdown()
4684 return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0; in fib6_ifdown()
4686 if (rt->should_flush) in fib6_ifdown()
4688 if (!rt->fib6_nsiblings) in fib6_ifdown()
4689 return rt->fib6_nh->fib_nh_dev == dev ? -1 : 0; in fib6_ifdown()
4690 if (rt6_multipath_uses_dev(rt, dev)) { in fib6_ifdown()
4693 count = rt6_multipath_dead_count(rt, dev); in fib6_ifdown()
4694 if (rt->fib6_nsiblings + 1 == count) { in fib6_ifdown()
4695 rt6_multipath_flush(rt); in fib6_ifdown()
4698 rt6_multipath_nh_flags_set(rt, dev, RTNH_F_DEAD | in fib6_ifdown()
4700 fib6_update_sernum(net, rt); in fib6_ifdown()
4701 rt6_multipath_rebalance(rt); in fib6_ifdown()
4705 if (rt->fib6_nh->fib_nh_dev != dev || in fib6_ifdown()
4706 rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) in fib6_ifdown()
4708 rt->fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN; in fib6_ifdown()
4709 rt6_multipath_rebalance(rt); in fib6_ifdown()
4980 struct fib6_info *rt, in ip6_route_info_append() argument
4988 if (rt6_duplicate_nexthop(nh->fib6_info, rt)) in ip6_route_info_append()
4995 nh->fib6_info = rt; in ip6_route_info_append()
5002 static void ip6_route_mpath_notify(struct fib6_info *rt, in ip6_route_mpath_notify() argument
5014 rt = list_first_entry(&rt_last->fib6_siblings, in ip6_route_mpath_notify()
5019 if (rt) in ip6_route_mpath_notify()
5020 inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); in ip6_route_mpath_notify()
5031 struct fib6_info *rt; in ip6_route_multipath_add() local
5074 rt = ip6_route_info_create(&r_cfg, GFP_KERNEL, extack); in ip6_route_multipath_add()
5075 if (IS_ERR(rt)) { in ip6_route_multipath_add()
5076 err = PTR_ERR(rt); in ip6_route_multipath_add()
5077 rt = NULL; in ip6_route_multipath_add()
5080 if (!rt6_qualify_for_ecmp(rt)) { in ip6_route_multipath_add()
5084 fib6_info_release(rt); in ip6_route_multipath_add()
5088 rt->fib6_nh->fib_nh_weight = rtnh->rtnh_hops + 1; in ip6_route_multipath_add()
5091 rt, &r_cfg); in ip6_route_multipath_add()
5093 fib6_info_release(rt); in ip6_route_multipath_add()
5361 struct fib6_info *rt, struct dst_entry *dst, in rt6_fill_node() argument
5383 rt6_dst = &rt->fib6_dst; in rt6_fill_node()
5384 rt6_src = &rt->fib6_src; in rt6_fill_node()
5385 rt6_flags = rt->fib6_flags; in rt6_fill_node()
5393 if (rt->fib6_table) in rt6_fill_node()
5394 table = rt->fib6_table->tb6_id; in rt6_fill_node()
5401 rtm->rtm_type = rt->fib6_type; in rt6_fill_node()
5404 rtm->rtm_protocol = rt->fib6_protocol; in rt6_fill_node()
5440 if (ip6_route_get_saddr(net, rt, dest, 0, &saddr_buf) == 0 && in rt6_fill_node()
5445 if (rt->fib6_prefsrc.plen) { in rt6_fill_node()
5447 saddr_buf = rt->fib6_prefsrc.addr; in rt6_fill_node()
5452 pmetrics = dst ? dst_metrics_ptr(dst) : rt->fib6_metrics->metrics; in rt6_fill_node()
5456 if (nla_put_u32(skb, RTA_PRIORITY, rt->fib6_metric)) in rt6_fill_node()
5469 } else if (rt->fib6_nsiblings) { in rt6_fill_node()
5477 if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common, in rt6_fill_node()
5478 rt->fib6_nh->fib_nh_weight, AF_INET6) < 0) in rt6_fill_node()
5482 &rt->fib6_siblings, fib6_siblings) { in rt6_fill_node()
5490 } else if (rt->nh) { in rt6_fill_node()
5491 if (nla_put_u32(skb, RTA_NH_ID, rt->nh->id)) in rt6_fill_node()
5494 if (nexthop_is_blackhole(rt->nh)) in rt6_fill_node()
5497 if (rt6_fill_node_nexthop(skb, rt->nh, &nh_flags) < 0) in rt6_fill_node()
5502 if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common, AF_INET6, in rt6_fill_node()
5510 expires = dst ? dst->expires : rt->expires; in rt6_fill_node()
5568 struct fib6_info *rt; member
5609 err = rt6_fill_node(dump->net, dump->skb, w->rt, in rt6_nh_dump_exceptions()
5626 int rt6_dump_route(struct fib6_info *rt, void *p_arg, unsigned int skip) in rt6_dump_route() argument
5634 if (rt == net->ipv6.fib6_null_entry) in rt6_dump_route()
5638 !(rt->fib6_flags & RTF_PREFIX_RT)) { in rt6_dump_route()
5643 ((filter->rt_type && rt->fib6_type != filter->rt_type) || in rt6_dump_route()
5644 (filter->dev && !fib6_info_uses_dev(rt, filter->dev)) || in rt6_dump_route()
5645 (filter->protocol && rt->fib6_protocol != filter->protocol))) { in rt6_dump_route()
5658 if (rt6_fill_node(net, arg->skb, rt, NULL, NULL, NULL, in rt6_dump_route()
5670 .rt = rt, in rt6_dump_route()
5677 if (rt->nh) { in rt6_dump_route()
5678 err = nexthop_for_each_fib6_nh(rt->nh, in rt6_dump_route()
5682 err = rt6_nh_dump_exceptions(rt->fib6_nh, &w); in rt6_dump_route()
5768 struct rt6_info *rt; in inet6_rtm_getroute() local
5854 rt = container_of(dst, struct rt6_info, dst); in inet6_rtm_getroute()
5855 if (rt->dst.error) { in inet6_rtm_getroute()
5856 err = rt->dst.error; in inet6_rtm_getroute()
5857 ip6_rt_put(rt); in inet6_rtm_getroute()
5861 if (rt == net->ipv6.ip6_null_entry) { in inet6_rtm_getroute()
5862 err = rt->dst.error; in inet6_rtm_getroute()
5863 ip6_rt_put(rt); in inet6_rtm_getroute()
5869 ip6_rt_put(rt); in inet6_rtm_getroute()
5874 skb_dst_set(skb, &rt->dst); in inet6_rtm_getroute()
5877 from = rcu_dereference(rt->from); in inet6_rtm_getroute()
5904 void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, in inet6_rt_notify() argument
5915 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); in inet6_rt_notify()
5919 err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0, in inet6_rt_notify()
5935 void fib6_rt_update(struct net *net, struct fib6_info *rt, in fib6_rt_update() argument
5945 call_fib6_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, rt, NULL); in fib6_rt_update()
5947 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); in fib6_rt_update()
5951 err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0, in fib6_rt_update()