route.c (1d053da910947afccec96d90892c0f5488c7a9cf) route.c (d4bea421f7322400d804c2284739e42e61f78349)
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

--- 1064 unchanged lines hidden (view full) ---

1073 flags);
1074 }
1075 if (f6i == net->ipv6.fib6_null_entry) {
1076 fn = fib6_backtrack(fn, &fl6->saddr);
1077 if (fn)
1078 goto restart;
1079 }
1080
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

--- 1064 unchanged lines hidden (view full) ---

1073 flags);
1074 }
1075 if (f6i == net->ipv6.fib6_null_entry) {
1076 fn = fib6_backtrack(fn, &fl6->saddr);
1077 if (fn)
1078 goto restart;
1079 }
1080
1081 trace_fib6_table_lookup(net, f6i, table, fl6);
1082
1081 /* Search through exception table */
1082 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
1083 if (rt) {
1084 if (ip6_hold_safe(net, &rt, true))
1085 dst_use_noref(&rt->dst, jiffies);
1086 } else if (f6i == net->ipv6.fib6_null_entry) {
1087 rt = net->ipv6.ip6_null_entry;
1088 dst_hold(&rt->dst);
1089 } else {
1090 rt = ip6_create_rt_rcu(f6i);
1091 if (!rt) {
1092 rt = net->ipv6.ip6_null_entry;
1093 dst_hold(&rt->dst);
1094 }
1095 }
1096
1097 rcu_read_unlock();
1098
1083 /* Search through exception table */
1084 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
1085 if (rt) {
1086 if (ip6_hold_safe(net, &rt, true))
1087 dst_use_noref(&rt->dst, jiffies);
1088 } else if (f6i == net->ipv6.fib6_null_entry) {
1089 rt = net->ipv6.ip6_null_entry;
1090 dst_hold(&rt->dst);
1091 } else {
1092 rt = ip6_create_rt_rcu(f6i);
1093 if (!rt) {
1094 rt = net->ipv6.ip6_null_entry;
1095 dst_hold(&rt->dst);
1096 }
1097 }
1098
1099 rcu_read_unlock();
1100
1099 trace_fib6_table_lookup(net, rt, table, fl6);
1100
1101 return rt;
1102}
1103
1104struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
1105 const struct sk_buff *skb, int flags)
1106{
1107 return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_lookup);
1108}

--- 713 unchanged lines hidden (view full) ---

1822 else if (strict & RT6_LOOKUP_F_REACHABLE) {
1823 /* also consider unreachable route */
1824 strict &= ~RT6_LOOKUP_F_REACHABLE;
1825 fn = saved_fn;
1826 goto redo_rt6_select;
1827 }
1828 }
1829
1101 return rt;
1102}
1103
1104struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
1105 const struct sk_buff *skb, int flags)
1106{
1107 return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_lookup);
1108}

--- 713 unchanged lines hidden (view full) ---

1822 else if (strict & RT6_LOOKUP_F_REACHABLE) {
1823 /* also consider unreachable route */
1824 strict &= ~RT6_LOOKUP_F_REACHABLE;
1825 fn = saved_fn;
1826 goto redo_rt6_select;
1827 }
1828 }
1829
1830 trace_fib6_table_lookup(net, f6i, table, fl6);
1831
1830 return f6i;
1831}
1832
1833struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
1834 int oif, struct flowi6 *fl6,
1835 const struct sk_buff *skb, int flags)
1836{
1837 struct fib6_info *f6i;

--- 10 unchanged lines hidden (view full) ---

1848 f6i = fib6_table_lookup(net, table, oif, fl6, strict);
1849 if (f6i->fib6_nsiblings)
1850 f6i = fib6_multipath_select(net, f6i, fl6, oif, skb, strict);
1851
1852 if (f6i == net->ipv6.fib6_null_entry) {
1853 rt = net->ipv6.ip6_null_entry;
1854 rcu_read_unlock();
1855 dst_hold(&rt->dst);
1832 return f6i;
1833}
1834
1835struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
1836 int oif, struct flowi6 *fl6,
1837 const struct sk_buff *skb, int flags)
1838{
1839 struct fib6_info *f6i;

--- 10 unchanged lines hidden (view full) ---

1850 f6i = fib6_table_lookup(net, table, oif, fl6, strict);
1851 if (f6i->fib6_nsiblings)
1852 f6i = fib6_multipath_select(net, f6i, fl6, oif, skb, strict);
1853
1854 if (f6i == net->ipv6.fib6_null_entry) {
1855 rt = net->ipv6.ip6_null_entry;
1856 rcu_read_unlock();
1857 dst_hold(&rt->dst);
1856 trace_fib6_table_lookup(net, rt, table, fl6);
1857 return rt;
1858 }
1859
1860 /*Search through exception table */
1861 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
1862 if (rt) {
1863 if (ip6_hold_safe(net, &rt, true))
1864 dst_use_noref(&rt->dst, jiffies);
1865
1866 rcu_read_unlock();
1858 return rt;
1859 }
1860
1861 /*Search through exception table */
1862 rt = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
1863 if (rt) {
1864 if (ip6_hold_safe(net, &rt, true))
1865 dst_use_noref(&rt->dst, jiffies);
1866
1867 rcu_read_unlock();
1867 trace_fib6_table_lookup(net, rt, table, fl6);
1868 return rt;
1869 } else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) &&
1870 !(f6i->fib6_flags & RTF_GATEWAY))) {
1871 /* Create a RTF_CACHE clone which will not be
1872 * owned by the fib6 tree. It is for the special case where
1873 * the daddr in the skb during the neighbor look-up is different
1874 * from the fl6->daddr used to look-up route here.
1875 */

--- 9 unchanged lines hidden (view full) ---

1885 */
1886 rt6_uncached_list_add(uncached_rt);
1887 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache);
1888 } else {
1889 uncached_rt = net->ipv6.ip6_null_entry;
1890 dst_hold(&uncached_rt->dst);
1891 }
1892
1868 return rt;
1869 } else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) &&
1870 !(f6i->fib6_flags & RTF_GATEWAY))) {
1871 /* Create a RTF_CACHE clone which will not be
1872 * owned by the fib6 tree. It is for the special case where
1873 * the daddr in the skb during the neighbor look-up is different
1874 * from the fl6->daddr used to look-up route here.
1875 */

--- 9 unchanged lines hidden (view full) ---

1885 */
1886 rt6_uncached_list_add(uncached_rt);
1887 atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache);
1888 } else {
1889 uncached_rt = net->ipv6.ip6_null_entry;
1890 dst_hold(&uncached_rt->dst);
1891 }
1892
1893 trace_fib6_table_lookup(net, uncached_rt, table, fl6);
1894 return uncached_rt;
1893 return uncached_rt;
1895
1896 } else {
1897 /* Get a percpu copy */
1898
1899 struct rt6_info *pcpu_rt;
1900
1901 local_bh_disable();
1902 pcpu_rt = rt6_get_pcpu_route(f6i);
1903
1904 if (!pcpu_rt)
1905 pcpu_rt = rt6_make_pcpu_route(net, f6i);
1906
1907 local_bh_enable();
1908 rcu_read_unlock();
1894 } else {
1895 /* Get a percpu copy */
1896
1897 struct rt6_info *pcpu_rt;
1898
1899 local_bh_disable();
1900 pcpu_rt = rt6_get_pcpu_route(f6i);
1901
1902 if (!pcpu_rt)
1903 pcpu_rt = rt6_make_pcpu_route(net, f6i);
1904
1905 local_bh_enable();
1906 rcu_read_unlock();
1909 trace_fib6_table_lookup(net, pcpu_rt, table, fl6);
1907
1910 return pcpu_rt;
1911 }
1912}
1913EXPORT_SYMBOL_GPL(ip6_pol_route);
1914
1915static struct rt6_info *ip6_pol_route_input(struct net *net,
1916 struct fib6_table *table,
1917 struct flowi6 *fl6,

--- 568 unchanged lines hidden (view full) ---

2486out:
2487 if (ret)
2488 dst_hold(&ret->dst);
2489 else
2490 ret = ip6_create_rt_rcu(rt);
2491
2492 rcu_read_unlock();
2493
1908 return pcpu_rt;
1909 }
1910}
1911EXPORT_SYMBOL_GPL(ip6_pol_route);
1912
1913static struct rt6_info *ip6_pol_route_input(struct net *net,
1914 struct fib6_table *table,
1915 struct flowi6 *fl6,

--- 568 unchanged lines hidden (view full) ---

2484out:
2485 if (ret)
2486 dst_hold(&ret->dst);
2487 else
2488 ret = ip6_create_rt_rcu(rt);
2489
2490 rcu_read_unlock();
2491
2494 trace_fib6_table_lookup(net, ret, table, fl6);
2492 trace_fib6_table_lookup(net, rt, table, fl6);
2495 return ret;
2496};
2497
2498static struct dst_entry *ip6_route_redirect(struct net *net,
2499 const struct flowi6 *fl6,
2500 const struct sk_buff *skb,
2501 const struct in6_addr *gateway)
2502{

--- 2859 unchanged lines hidden ---
2493 return ret;
2494};
2495
2496static struct dst_entry *ip6_route_redirect(struct net *net,
2497 const struct flowi6 *fl6,
2498 const struct sk_buff *skb,
2499 const struct in6_addr *gateway)
2500{

--- 2859 unchanged lines hidden ---