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 ---