Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: Add fib6_type and fib6_flags to fib6_result

Add the fib6_flags and fib6_type to fib6_result. Update the lookup helpers
to set them and update post fib lookup users to use the version from the
result.

This allows nexthop objects to have blackhole nexthop.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ahern and committed by
David S. Miller
7d21fec9 effda4dd

+52 -39
+2
include/net/ip6_fib.h
··· 193 193 struct fib6_result { 194 194 struct fib6_nh *nh; 195 195 struct fib6_info *f6i; 196 + u32 fib6_flags; 197 + u8 fib6_type; 196 198 }; 197 199 198 200 #define for_each_fib6_node_rt_rcu(fn) \
+1 -1
include/trace/events/fib6.h
··· 39 39 struct in6_addr *in6; 40 40 41 41 __entry->tb_id = table->tb6_id; 42 - __entry->err = ip6_rt_type_to_error(res->f6i->fib6_type); 42 + __entry->err = ip6_rt_type_to_error(res->fib6_type); 43 43 __entry->oif = flp->flowi6_oif; 44 44 __entry->iif = flp->flowi6_iif; 45 45 __entry->tos = ip6_tclass(flp->flowlabel);
+12 -14
net/core/filter.c
··· 4741 4741 res.f6i == net->ipv6.fib6_null_entry)) 4742 4742 return BPF_FIB_LKUP_RET_NOT_FWDED; 4743 4743 4744 - if (unlikely(res.f6i->fib6_flags & RTF_REJECT)) { 4745 - switch (res.f6i->fib6_type) { 4746 - case RTN_BLACKHOLE: 4747 - return BPF_FIB_LKUP_RET_BLACKHOLE; 4748 - case RTN_UNREACHABLE: 4749 - return BPF_FIB_LKUP_RET_UNREACHABLE; 4750 - case RTN_PROHIBIT: 4751 - return BPF_FIB_LKUP_RET_PROHIBIT; 4752 - default: 4753 - return BPF_FIB_LKUP_RET_NOT_FWDED; 4754 - } 4755 - } 4756 - 4757 - if (res.f6i->fib6_type != RTN_UNICAST) 4744 + switch (res.fib6_type) { 4745 + /* only unicast is forwarded */ 4746 + case RTN_UNICAST: 4747 + break; 4748 + case RTN_BLACKHOLE: 4749 + return BPF_FIB_LKUP_RET_BLACKHOLE; 4750 + case RTN_UNREACHABLE: 4751 + return BPF_FIB_LKUP_RET_UNREACHABLE; 4752 + case RTN_PROHIBIT: 4753 + return BPF_FIB_LKUP_RET_PROHIBIT; 4754 + default: 4758 4755 return BPF_FIB_LKUP_RET_NOT_FWDED; 4756 + } 4759 4757 4760 4758 ipv6_stub->fib6_select_path(net, &res, &fl6, fl6.flowi6_oif, 4761 4759 fl6.flowi6_oif != 0, NULL, strict);
+37 -24
net/ipv6/route.c
··· 500 500 501 501 if (!oif && ipv6_addr_any(saddr)) { 502 502 nh = &f6i->fib6_nh; 503 - if (!(nh->fib_nh_flags & RTNH_F_DEAD)) { 504 - res->nh = nh; 505 - return; 506 - } 503 + if (!(nh->fib_nh_flags & RTNH_F_DEAD)) 504 + goto out; 507 505 } 508 506 509 507 for (spf6i = f6i; spf6i; spf6i = rcu_dereference(spf6i->fib6_next)) { 510 508 nh = &spf6i->fib6_nh; 511 509 if (__rt6_device_match(net, nh, saddr, oif, flags)) { 512 510 res->f6i = spf6i; 513 - res->nh = nh; 511 + goto out; 514 512 } 515 513 } 516 514 517 515 if (oif && flags & RT6_LOOKUP_F_IFACE) { 518 516 res->f6i = net->ipv6.fib6_null_entry; 519 - res->nh = &res->f6i->fib6_nh; 520 - return; 517 + nh = &res->f6i->fib6_nh; 518 + goto out; 521 519 } 522 520 523 - res->nh = &f6i->fib6_nh; 524 - if (res->nh->fib_nh_flags & RTNH_F_DEAD) { 521 + nh = &f6i->fib6_nh; 522 + if (nh->fib_nh_flags & RTNH_F_DEAD) { 525 523 res->f6i = net->ipv6.fib6_null_entry; 526 - res->nh = &res->f6i->fib6_nh; 524 + nh = &res->f6i->fib6_nh; 527 525 } 526 + out: 527 + res->nh = nh; 528 + res->fib6_type = res->f6i->fib6_type; 529 + res->fib6_flags = res->f6i->fib6_flags; 528 530 } 529 531 530 532 #ifdef CONFIG_IPV6_ROUTER_PREF ··· 721 719 if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) { 722 720 res->f6i = f6i; 723 721 res->nh = nh; 722 + res->fib6_flags = f6i->fib6_flags; 723 + res->fib6_type = f6i->fib6_type; 724 724 } 725 725 } 726 726 } ··· 800 796 if (!res->f6i) { 801 797 res->f6i = net->ipv6.fib6_null_entry; 802 798 res->nh = &res->f6i->fib6_nh; 799 + res->fib6_flags = res->f6i->fib6_flags; 800 + res->fib6_type = res->f6i->fib6_type; 803 801 } 804 802 } 805 803 ··· 895 889 static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res) 896 890 { 897 891 struct net_device *dev = res->nh->fib_nh_dev; 898 - const struct fib6_info *f6i = res->f6i; 899 892 900 - if (f6i->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) { 893 + if (res->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) { 901 894 /* for copies of local routes, dst->dev needs to be the 902 895 * device if it is a master device, the master device if 903 896 * device is enslaved, and the loopback as the default 904 897 */ 905 898 if (netif_is_l3_slave(dev) && 906 - !rt6_need_strict(&f6i->fib6_dst.addr)) 899 + !rt6_need_strict(&res->f6i->fib6_dst.addr)) 907 900 dev = l3mdev_master_dev_rcu(dev); 908 901 else if (!netif_is_l3_master(dev)) 909 902 dev = dev_net(dev)->loopback_dev; ··· 948 943 return flags; 949 944 } 950 945 951 - static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct fib6_info *ort) 946 + static void ip6_rt_init_dst_reject(struct rt6_info *rt, u8 fib6_type) 952 947 { 953 - rt->dst.error = ip6_rt_type_to_error(ort->fib6_type); 948 + rt->dst.error = ip6_rt_type_to_error(fib6_type); 954 949 955 - switch (ort->fib6_type) { 950 + switch (fib6_type) { 956 951 case RTN_BLACKHOLE: 957 952 rt->dst.output = dst_discard_out; 958 953 rt->dst.input = dst_discard; ··· 972 967 973 968 static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res) 974 969 { 975 - struct fib6_info *ort = res->f6i; 970 + struct fib6_info *f6i = res->f6i; 976 971 977 - if (ort->fib6_flags & RTF_REJECT) { 978 - ip6_rt_init_dst_reject(rt, ort); 972 + if (res->fib6_flags & RTF_REJECT) { 973 + ip6_rt_init_dst_reject(rt, res->fib6_type); 979 974 return; 980 975 } 981 976 982 977 rt->dst.error = 0; 983 978 rt->dst.output = ip6_output; 984 979 985 - if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) { 980 + if (res->fib6_type == RTN_LOCAL || res->fib6_type == RTN_ANYCAST) { 986 981 rt->dst.input = ip6_input; 987 - } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) { 982 + } else if (ipv6_addr_type(&f6i->fib6_dst.addr) & IPV6_ADDR_MULTICAST) { 988 983 rt->dst.input = ip6_mc_input; 989 984 } else { 990 985 rt->dst.input = ip6_forward; ··· 1017 1012 1018 1013 rt->rt6i_dst = f6i->fib6_dst; 1019 1014 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL; 1020 - rt->rt6i_flags = f6i->fib6_flags; 1015 + rt->rt6i_flags = res->fib6_flags; 1021 1016 if (nh->fib_nh_gw_family) { 1022 1017 rt->rt6i_gateway = nh->fib_nh_gw6; 1023 1018 rt->rt6i_flags |= RTF_GATEWAY; ··· 2370 2365 return; 2371 2366 } 2372 2367 res.nh = &res.f6i->fib6_nh; 2368 + res.fib6_flags = res.f6i->fib6_flags; 2369 + res.fib6_type = res.f6i->fib6_type; 2370 + 2373 2371 nrt6 = ip6_rt_cache_alloc(&res, daddr, saddr); 2374 2372 if (nrt6) { 2375 2373 rt6_do_update_pmtu(nrt6, mtu); ··· 2538 2530 res.f6i = rt; 2539 2531 res.nh = &rt->fib6_nh; 2540 2532 out: 2541 - if (ret) 2533 + if (ret) { 2542 2534 ip6_hold_safe(net, &ret); 2543 - else 2535 + } else { 2536 + res.fib6_flags = res.f6i->fib6_flags; 2537 + res.fib6_type = res.f6i->fib6_type; 2544 2538 ret = ip6_create_rt_rcu(&res); 2539 + } 2545 2540 2546 2541 rcu_read_unlock(); 2547 2542 ··· 3502 3491 rcu_read_unlock(); 3503 3492 3504 3493 res.nh = &res.f6i->fib6_nh; 3494 + res.fib6_flags = res.f6i->fib6_flags; 3495 + res.fib6_type = res.f6i->fib6_type; 3505 3496 nrt = ip6_rt_cache_alloc(&res, &msg->dest, NULL); 3506 3497 if (!nrt) 3507 3498 goto out;