route.c (930352862e9533fecc42c7ed20798a7c9e3aa874) | route.c (a3c00e46efdb4009369971c97203ea67f7630fe4) |
---|---|
1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * This program is free software; you can redistribute it and/or --- 758 unchanged lines hidden (view full) --- 767 rt6_set_expires(rt, jiffies + HZ * lifetime); 768 769 ip6_rt_put(rt); 770 } 771 return 0; 772} 773#endif 774 | 1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * This program is free software; you can redistribute it and/or --- 758 unchanged lines hidden (view full) --- 767 rt6_set_expires(rt, jiffies + HZ * lifetime); 768 769 ip6_rt_put(rt); 770 } 771 return 0; 772} 773#endif 774 |
775#define BACKTRACK(__net, saddr) \ 776do { \ 777 if (rt == __net->ipv6.ip6_null_entry) { \ 778 struct fib6_node *pn; \ 779 while (1) { \ 780 if (fn->fn_flags & RTN_TL_ROOT) \ 781 goto out; \ 782 pn = fn->parent; \ 783 if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \ 784 fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); \ 785 else \ 786 fn = pn; \ 787 if (fn->fn_flags & RTN_RTINFO) \ 788 goto restart; \ 789 } \ 790 } \ 791} while (0) | 775static struct fib6_node* fib6_backtrack(struct fib6_node *fn, 776 struct in6_addr *saddr) 777{ 778 struct fib6_node *pn; 779 while (1) { 780 if (fn->fn_flags & RTN_TL_ROOT) 781 return NULL; 782 pn = fn->parent; 783 if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) 784 fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); 785 else 786 fn = pn; 787 if (fn->fn_flags & RTN_RTINFO) 788 return fn; 789 } 790} |
792 793static struct rt6_info *ip6_pol_route_lookup(struct net *net, 794 struct fib6_table *table, 795 struct flowi6 *fl6, int flags) 796{ 797 struct fib6_node *fn; 798 struct rt6_info *rt; 799 800 read_lock_bh(&table->tb6_lock); 801 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 802restart: 803 rt = fn->leaf; 804 rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); 805 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) 806 rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags); | 791 792static struct rt6_info *ip6_pol_route_lookup(struct net *net, 793 struct fib6_table *table, 794 struct flowi6 *fl6, int flags) 795{ 796 struct fib6_node *fn; 797 struct rt6_info *rt; 798 799 read_lock_bh(&table->tb6_lock); 800 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 801restart: 802 rt = fn->leaf; 803 rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); 804 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) 805 rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags); |
807 BACKTRACK(net, &fl6->saddr); 808out: | 806 if (rt == net->ipv6.ip6_null_entry) { 807 fn = fib6_backtrack(fn, &fl6->saddr); 808 if (fn) 809 goto restart; 810 } |
809 dst_use(&rt->dst, jiffies); 810 read_unlock_bh(&table->tb6_lock); 811 return rt; 812 813} 814 815struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, 816 int flags) --- 102 unchanged lines hidden (view full) --- 919 struct rt6_info *rt, *nrt; 920 int strict = 0; 921 int attempts = 3; 922 int err; 923 int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; 924 925 strict |= flags & RT6_LOOKUP_F_IFACE; 926 | 811 dst_use(&rt->dst, jiffies); 812 read_unlock_bh(&table->tb6_lock); 813 return rt; 814 815} 816 817struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, 818 int flags) --- 102 unchanged lines hidden (view full) --- 921 struct rt6_info *rt, *nrt; 922 int strict = 0; 923 int attempts = 3; 924 int err; 925 int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; 926 927 strict |= flags & RT6_LOOKUP_F_IFACE; 928 |
927relookup: | 929redo_fib6_lookup_lock: |
928 read_lock_bh(&table->tb6_lock); 929 | 930 read_lock_bh(&table->tb6_lock); 931 |
930restart_2: | 932redo_fib6_lookup: |
931 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 932 | 933 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 934 |
933restart: | 935redo_rt6_select: |
934 rt = rt6_select(fn, oif, strict | reachable); 935 if (rt->rt6i_nsiblings) 936 rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); | 936 rt = rt6_select(fn, oif, strict | reachable); 937 if (rt->rt6i_nsiblings) 938 rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); |
937 BACKTRACK(net, &fl6->saddr); 938 if (rt == net->ipv6.ip6_null_entry || 939 rt->rt6i_flags & RTF_CACHE) | 939 if (rt == net->ipv6.ip6_null_entry) { 940 fn = fib6_backtrack(fn, &fl6->saddr); 941 if (fn) 942 goto redo_rt6_select; 943 else 944 goto out; 945 } 946 947 if (rt->rt6i_flags & RTF_CACHE) |
940 goto out; 941 942 dst_hold(&rt->dst); 943 read_unlock_bh(&table->tb6_lock); 944 945 if (!(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY))) 946 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); 947 else if (!(rt->dst.flags & DST_HOST)) --- 14 unchanged lines hidden (view full) --- 962 if (--attempts <= 0) 963 goto out2; 964 965 /* 966 * Race condition! In the gap, when table->tb6_lock was 967 * released someone could insert this route. Relookup. 968 */ 969 ip6_rt_put(rt); | 948 goto out; 949 950 dst_hold(&rt->dst); 951 read_unlock_bh(&table->tb6_lock); 952 953 if (!(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY))) 954 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); 955 else if (!(rt->dst.flags & DST_HOST)) --- 14 unchanged lines hidden (view full) --- 970 if (--attempts <= 0) 971 goto out2; 972 973 /* 974 * Race condition! In the gap, when table->tb6_lock was 975 * released someone could insert this route. Relookup. 976 */ 977 ip6_rt_put(rt); |
970 goto relookup; | 978 goto redo_fib6_lookup_lock; |
971 972out: 973 if (reachable) { 974 reachable = 0; | 979 980out: 981 if (reachable) { 982 reachable = 0; |
975 goto restart_2; | 983 goto redo_fib6_lookup; |
976 } 977 dst_hold(&rt->dst); 978 read_unlock_bh(&table->tb6_lock); 979out2: 980 rt->dst.lastuse = jiffies; 981 rt->dst.__use++; 982 983 return rt; --- 246 unchanged lines hidden (view full) --- 1230 continue; 1231 break; 1232 } 1233 1234 if (!rt) 1235 rt = net->ipv6.ip6_null_entry; 1236 else if (rt->dst.error) { 1237 rt = net->ipv6.ip6_null_entry; | 984 } 985 dst_hold(&rt->dst); 986 read_unlock_bh(&table->tb6_lock); 987out2: 988 rt->dst.lastuse = jiffies; 989 rt->dst.__use++; 990 991 return rt; --- 246 unchanged lines hidden (view full) --- 1238 continue; 1239 break; 1240 } 1241 1242 if (!rt) 1243 rt = net->ipv6.ip6_null_entry; 1244 else if (rt->dst.error) { 1245 rt = net->ipv6.ip6_null_entry; |
1238 goto out; | 1246 } else if (rt == net->ipv6.ip6_null_entry) { 1247 fn = fib6_backtrack(fn, &fl6->saddr); 1248 if (fn) 1249 goto restart; |
1239 } | 1250 } |
1240 BACKTRACK(net, &fl6->saddr); 1241out: | 1251 |
1242 dst_hold(&rt->dst); 1243 1244 read_unlock_bh(&table->tb6_lock); 1245 1246 return rt; 1247}; 1248 1249static struct dst_entry *ip6_route_redirect(struct net *net, --- 1981 unchanged lines hidden --- | 1252 dst_hold(&rt->dst); 1253 1254 read_unlock_bh(&table->tb6_lock); 1255 1256 return rt; 1257}; 1258 1259static struct dst_entry *ip6_route_redirect(struct net *net, --- 1981 unchanged lines hidden --- |