diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-06-10 20:22:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:05:57 -0400 |
commit | e06e7c615877026544ad7f8b309d1a3706410383 (patch) | |
tree | eb087b49279e6db492039a5d684ca9acb13265a3 /net/ipv4/route.c | |
parent | 4eb6bf6bfb580afaf1e1a1d30cba17a078530cf4 (diff) |
[IPV4]: The scheduled removal of multipath cached routing support.
With help from Chris Wedgwood.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 259 |
1 files changed, 11 insertions, 248 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 29ca63e81ced..85285021518b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -101,7 +101,6 @@ | |||
101 | #include <net/tcp.h> | 101 | #include <net/tcp.h> |
102 | #include <net/icmp.h> | 102 | #include <net/icmp.h> |
103 | #include <net/xfrm.h> | 103 | #include <net/xfrm.h> |
104 | #include <net/ip_mp_alg.h> | ||
105 | #include <net/netevent.h> | 104 | #include <net/netevent.h> |
106 | #include <net/rtnetlink.h> | 105 | #include <net/rtnetlink.h> |
107 | #ifdef CONFIG_SYSCTL | 106 | #ifdef CONFIG_SYSCTL |
@@ -495,13 +494,11 @@ static const struct file_operations rt_cpu_seq_fops = { | |||
495 | 494 | ||
496 | static __inline__ void rt_free(struct rtable *rt) | 495 | static __inline__ void rt_free(struct rtable *rt) |
497 | { | 496 | { |
498 | multipath_remove(rt); | ||
499 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); | 497 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); |
500 | } | 498 | } |
501 | 499 | ||
502 | static __inline__ void rt_drop(struct rtable *rt) | 500 | static __inline__ void rt_drop(struct rtable *rt) |
503 | { | 501 | { |
504 | multipath_remove(rt); | ||
505 | ip_rt_put(rt); | 502 | ip_rt_put(rt); |
506 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); | 503 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); |
507 | } | 504 | } |
@@ -574,52 +571,6 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | |||
574 | (fl1->iif ^ fl2->iif)) == 0; | 571 | (fl1->iif ^ fl2->iif)) == 0; |
575 | } | 572 | } |
576 | 573 | ||
577 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
578 | static struct rtable **rt_remove_balanced_route(struct rtable **chain_head, | ||
579 | struct rtable *expentry, | ||
580 | int *removed_count) | ||
581 | { | ||
582 | int passedexpired = 0; | ||
583 | struct rtable **nextstep = NULL; | ||
584 | struct rtable **rthp = chain_head; | ||
585 | struct rtable *rth; | ||
586 | |||
587 | if (removed_count) | ||
588 | *removed_count = 0; | ||
589 | |||
590 | while ((rth = *rthp) != NULL) { | ||
591 | if (rth == expentry) | ||
592 | passedexpired = 1; | ||
593 | |||
594 | if (((*rthp)->u.dst.flags & DST_BALANCED) != 0 && | ||
595 | compare_keys(&(*rthp)->fl, &expentry->fl)) { | ||
596 | if (*rthp == expentry) { | ||
597 | *rthp = rth->u.dst.rt_next; | ||
598 | continue; | ||
599 | } else { | ||
600 | *rthp = rth->u.dst.rt_next; | ||
601 | rt_free(rth); | ||
602 | if (removed_count) | ||
603 | ++(*removed_count); | ||
604 | } | ||
605 | } else { | ||
606 | if (!((*rthp)->u.dst.flags & DST_BALANCED) && | ||
607 | passedexpired && !nextstep) | ||
608 | nextstep = &rth->u.dst.rt_next; | ||
609 | |||
610 | rthp = &rth->u.dst.rt_next; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | rt_free(expentry); | ||
615 | if (removed_count) | ||
616 | ++(*removed_count); | ||
617 | |||
618 | return nextstep; | ||
619 | } | ||
620 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
621 | |||
622 | |||
623 | /* This runs via a timer and thus is always in BH context. */ | 574 | /* This runs via a timer and thus is always in BH context. */ |
624 | static void rt_check_expire(unsigned long dummy) | 575 | static void rt_check_expire(unsigned long dummy) |
625 | { | 576 | { |
@@ -658,22 +609,8 @@ static void rt_check_expire(unsigned long dummy) | |||
658 | } | 609 | } |
659 | 610 | ||
660 | /* Cleanup aged off entries. */ | 611 | /* Cleanup aged off entries. */ |
661 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
662 | /* remove all related balanced entries if necessary */ | ||
663 | if (rth->u.dst.flags & DST_BALANCED) { | ||
664 | rthp = rt_remove_balanced_route( | ||
665 | &rt_hash_table[i].chain, | ||
666 | rth, NULL); | ||
667 | if (!rthp) | ||
668 | break; | ||
669 | } else { | ||
670 | *rthp = rth->u.dst.rt_next; | ||
671 | rt_free(rth); | ||
672 | } | ||
673 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
674 | *rthp = rth->u.dst.rt_next; | 612 | *rthp = rth->u.dst.rt_next; |
675 | rt_free(rth); | 613 | rt_free(rth); |
676 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
677 | } | 614 | } |
678 | spin_unlock(rt_hash_lock_addr(i)); | 615 | spin_unlock(rt_hash_lock_addr(i)); |
679 | 616 | ||
@@ -721,9 +658,6 @@ void rt_cache_flush(int delay) | |||
721 | if (delay < 0) | 658 | if (delay < 0) |
722 | delay = ip_rt_min_delay; | 659 | delay = ip_rt_min_delay; |
723 | 660 | ||
724 | /* flush existing multipath state*/ | ||
725 | multipath_flush(); | ||
726 | |||
727 | spin_lock_bh(&rt_flush_lock); | 661 | spin_lock_bh(&rt_flush_lock); |
728 | 662 | ||
729 | if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { | 663 | if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { |
@@ -842,30 +776,9 @@ static int rt_garbage_collect(void) | |||
842 | rthp = &rth->u.dst.rt_next; | 776 | rthp = &rth->u.dst.rt_next; |
843 | continue; | 777 | continue; |
844 | } | 778 | } |
845 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
846 | /* remove all related balanced entries | ||
847 | * if necessary | ||
848 | */ | ||
849 | if (rth->u.dst.flags & DST_BALANCED) { | ||
850 | int r; | ||
851 | |||
852 | rthp = rt_remove_balanced_route( | ||
853 | &rt_hash_table[k].chain, | ||
854 | rth, | ||
855 | &r); | ||
856 | goal -= r; | ||
857 | if (!rthp) | ||
858 | break; | ||
859 | } else { | ||
860 | *rthp = rth->u.dst.rt_next; | ||
861 | rt_free(rth); | ||
862 | goal--; | ||
863 | } | ||
864 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
865 | *rthp = rth->u.dst.rt_next; | 779 | *rthp = rth->u.dst.rt_next; |
866 | rt_free(rth); | 780 | rt_free(rth); |
867 | goal--; | 781 | goal--; |
868 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
869 | } | 782 | } |
870 | spin_unlock_bh(rt_hash_lock_addr(k)); | 783 | spin_unlock_bh(rt_hash_lock_addr(k)); |
871 | if (goal <= 0) | 784 | if (goal <= 0) |
@@ -939,12 +852,7 @@ restart: | |||
939 | 852 | ||
940 | spin_lock_bh(rt_hash_lock_addr(hash)); | 853 | spin_lock_bh(rt_hash_lock_addr(hash)); |
941 | while ((rth = *rthp) != NULL) { | 854 | while ((rth = *rthp) != NULL) { |
942 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
943 | if (!(rth->u.dst.flags & DST_BALANCED) && | ||
944 | compare_keys(&rth->fl, &rt->fl)) { | ||
945 | #else | ||
946 | if (compare_keys(&rth->fl, &rt->fl)) { | 855 | if (compare_keys(&rth->fl, &rt->fl)) { |
947 | #endif | ||
948 | /* Put it first */ | 856 | /* Put it first */ |
949 | *rthp = rth->u.dst.rt_next; | 857 | *rthp = rth->u.dst.rt_next; |
950 | /* | 858 | /* |
@@ -1774,10 +1682,6 @@ static inline int __mkroute_input(struct sk_buff *skb, | |||
1774 | 1682 | ||
1775 | atomic_set(&rth->u.dst.__refcnt, 1); | 1683 | atomic_set(&rth->u.dst.__refcnt, 1); |
1776 | rth->u.dst.flags= DST_HOST; | 1684 | rth->u.dst.flags= DST_HOST; |
1777 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
1778 | if (res->fi->fib_nhs > 1) | ||
1779 | rth->u.dst.flags |= DST_BALANCED; | ||
1780 | #endif | ||
1781 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) | 1685 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) |
1782 | rth->u.dst.flags |= DST_NOPOLICY; | 1686 | rth->u.dst.flags |= DST_NOPOLICY; |
1783 | if (IN_DEV_CONF_GET(out_dev, NOXFRM)) | 1687 | if (IN_DEV_CONF_GET(out_dev, NOXFRM)) |
@@ -1812,11 +1716,11 @@ static inline int __mkroute_input(struct sk_buff *skb, | |||
1812 | return err; | 1716 | return err; |
1813 | } | 1717 | } |
1814 | 1718 | ||
1815 | static inline int ip_mkroute_input_def(struct sk_buff *skb, | 1719 | static inline int ip_mkroute_input(struct sk_buff *skb, |
1816 | struct fib_result* res, | 1720 | struct fib_result* res, |
1817 | const struct flowi *fl, | 1721 | const struct flowi *fl, |
1818 | struct in_device *in_dev, | 1722 | struct in_device *in_dev, |
1819 | __be32 daddr, __be32 saddr, u32 tos) | 1723 | __be32 daddr, __be32 saddr, u32 tos) |
1820 | { | 1724 | { |
1821 | struct rtable* rth = NULL; | 1725 | struct rtable* rth = NULL; |
1822 | int err; | 1726 | int err; |
@@ -1837,63 +1741,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb, | |||
1837 | return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); | 1741 | return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); |
1838 | } | 1742 | } |
1839 | 1743 | ||
1840 | static inline int ip_mkroute_input(struct sk_buff *skb, | ||
1841 | struct fib_result* res, | ||
1842 | const struct flowi *fl, | ||
1843 | struct in_device *in_dev, | ||
1844 | __be32 daddr, __be32 saddr, u32 tos) | ||
1845 | { | ||
1846 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
1847 | struct rtable* rth = NULL, *rtres; | ||
1848 | unsigned char hop, hopcount; | ||
1849 | int err = -EINVAL; | ||
1850 | unsigned int hash; | ||
1851 | |||
1852 | if (res->fi) | ||
1853 | hopcount = res->fi->fib_nhs; | ||
1854 | else | ||
1855 | hopcount = 1; | ||
1856 | |||
1857 | /* distinguish between multipath and singlepath */ | ||
1858 | if (hopcount < 2) | ||
1859 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, | ||
1860 | saddr, tos); | ||
1861 | |||
1862 | /* add all alternatives to the routing cache */ | ||
1863 | for (hop = 0; hop < hopcount; hop++) { | ||
1864 | res->nh_sel = hop; | ||
1865 | |||
1866 | /* put reference to previous result */ | ||
1867 | if (hop) | ||
1868 | ip_rt_put(rtres); | ||
1869 | |||
1870 | /* create a routing cache entry */ | ||
1871 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, | ||
1872 | &rth); | ||
1873 | if (err) | ||
1874 | return err; | ||
1875 | |||
1876 | /* put it into the cache */ | ||
1877 | hash = rt_hash(daddr, saddr, fl->iif); | ||
1878 | err = rt_intern_hash(hash, rth, &rtres); | ||
1879 | if (err) | ||
1880 | return err; | ||
1881 | |||
1882 | /* forward hop information to multipath impl. */ | ||
1883 | multipath_set_nhinfo(rth, | ||
1884 | FIB_RES_NETWORK(*res), | ||
1885 | FIB_RES_NETMASK(*res), | ||
1886 | res->prefixlen, | ||
1887 | &FIB_RES_NH(*res)); | ||
1888 | } | ||
1889 | skb->dst = &rtres->u.dst; | ||
1890 | return err; | ||
1891 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
1892 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos); | ||
1893 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
1894 | } | ||
1895 | |||
1896 | |||
1897 | /* | 1744 | /* |
1898 | * NOTE. We drop all the packets that has local source | 1745 | * NOTE. We drop all the packets that has local source |
1899 | * addresses, because every properly looped back packet | 1746 | * addresses, because every properly looped back packet |
@@ -2211,13 +2058,6 @@ static inline int __mkroute_output(struct rtable **result, | |||
2211 | 2058 | ||
2212 | atomic_set(&rth->u.dst.__refcnt, 1); | 2059 | atomic_set(&rth->u.dst.__refcnt, 1); |
2213 | rth->u.dst.flags= DST_HOST; | 2060 | rth->u.dst.flags= DST_HOST; |
2214 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2215 | if (res->fi) { | ||
2216 | rth->rt_multipath_alg = res->fi->fib_mp_alg; | ||
2217 | if (res->fi->fib_nhs > 1) | ||
2218 | rth->u.dst.flags |= DST_BALANCED; | ||
2219 | } | ||
2220 | #endif | ||
2221 | if (IN_DEV_CONF_GET(in_dev, NOXFRM)) | 2061 | if (IN_DEV_CONF_GET(in_dev, NOXFRM)) |
2222 | rth->u.dst.flags |= DST_NOXFRM; | 2062 | rth->u.dst.flags |= DST_NOXFRM; |
2223 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) | 2063 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) |
@@ -2277,12 +2117,12 @@ static inline int __mkroute_output(struct rtable **result, | |||
2277 | return err; | 2117 | return err; |
2278 | } | 2118 | } |
2279 | 2119 | ||
2280 | static inline int ip_mkroute_output_def(struct rtable **rp, | 2120 | static inline int ip_mkroute_output(struct rtable **rp, |
2281 | struct fib_result* res, | 2121 | struct fib_result* res, |
2282 | const struct flowi *fl, | 2122 | const struct flowi *fl, |
2283 | const struct flowi *oldflp, | 2123 | const struct flowi *oldflp, |
2284 | struct net_device *dev_out, | 2124 | struct net_device *dev_out, |
2285 | unsigned flags) | 2125 | unsigned flags) |
2286 | { | 2126 | { |
2287 | struct rtable *rth = NULL; | 2127 | struct rtable *rth = NULL; |
2288 | int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); | 2128 | int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); |
@@ -2295,68 +2135,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp, | |||
2295 | return err; | 2135 | return err; |
2296 | } | 2136 | } |
2297 | 2137 | ||
2298 | static inline int ip_mkroute_output(struct rtable** rp, | ||
2299 | struct fib_result* res, | ||
2300 | const struct flowi *fl, | ||
2301 | const struct flowi *oldflp, | ||
2302 | struct net_device *dev_out, | ||
2303 | unsigned flags) | ||
2304 | { | ||
2305 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2306 | unsigned char hop; | ||
2307 | unsigned hash; | ||
2308 | int err = -EINVAL; | ||
2309 | struct rtable *rth = NULL; | ||
2310 | |||
2311 | if (res->fi && res->fi->fib_nhs > 1) { | ||
2312 | unsigned char hopcount = res->fi->fib_nhs; | ||
2313 | |||
2314 | for (hop = 0; hop < hopcount; hop++) { | ||
2315 | struct net_device *dev2nexthop; | ||
2316 | |||
2317 | res->nh_sel = hop; | ||
2318 | |||
2319 | /* hold a work reference to the output device */ | ||
2320 | dev2nexthop = FIB_RES_DEV(*res); | ||
2321 | dev_hold(dev2nexthop); | ||
2322 | |||
2323 | /* put reference to previous result */ | ||
2324 | if (hop) | ||
2325 | ip_rt_put(*rp); | ||
2326 | |||
2327 | err = __mkroute_output(&rth, res, fl, oldflp, | ||
2328 | dev2nexthop, flags); | ||
2329 | |||
2330 | if (err != 0) | ||
2331 | goto cleanup; | ||
2332 | |||
2333 | hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, | ||
2334 | oldflp->oif); | ||
2335 | err = rt_intern_hash(hash, rth, rp); | ||
2336 | |||
2337 | /* forward hop information to multipath impl. */ | ||
2338 | multipath_set_nhinfo(rth, | ||
2339 | FIB_RES_NETWORK(*res), | ||
2340 | FIB_RES_NETMASK(*res), | ||
2341 | res->prefixlen, | ||
2342 | &FIB_RES_NH(*res)); | ||
2343 | cleanup: | ||
2344 | /* release work reference to output device */ | ||
2345 | dev_put(dev2nexthop); | ||
2346 | |||
2347 | if (err != 0) | ||
2348 | return err; | ||
2349 | } | ||
2350 | return err; | ||
2351 | } else { | ||
2352 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, | ||
2353 | flags); | ||
2354 | } | ||
2355 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
2356 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags); | ||
2357 | #endif | ||
2358 | } | ||
2359 | |||
2360 | /* | 2138 | /* |
2361 | * Major route resolver routine. | 2139 | * Major route resolver routine. |
2362 | */ | 2140 | */ |
@@ -2570,17 +2348,6 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) | |||
2570 | rth->fl.mark == flp->mark && | 2348 | rth->fl.mark == flp->mark && |
2571 | !((rth->fl.fl4_tos ^ flp->fl4_tos) & | 2349 | !((rth->fl.fl4_tos ^ flp->fl4_tos) & |
2572 | (IPTOS_RT_MASK | RTO_ONLINK))) { | 2350 | (IPTOS_RT_MASK | RTO_ONLINK))) { |
2573 | |||
2574 | /* check for multipath routes and choose one if | ||
2575 | * necessary | ||
2576 | */ | ||
2577 | if (multipath_select_route(flp, rth, rp)) { | ||
2578 | dst_hold(&(*rp)->u.dst); | ||
2579 | RT_CACHE_STAT_INC(out_hit); | ||
2580 | rcu_read_unlock_bh(); | ||
2581 | return 0; | ||
2582 | } | ||
2583 | |||
2584 | rth->u.dst.lastuse = jiffies; | 2351 | rth->u.dst.lastuse = jiffies; |
2585 | dst_hold(&rth->u.dst); | 2352 | dst_hold(&rth->u.dst); |
2586 | rth->u.dst.__use++; | 2353 | rth->u.dst.__use++; |
@@ -2729,10 +2496,6 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
2729 | if (rt->u.dst.tclassid) | 2496 | if (rt->u.dst.tclassid) |
2730 | NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); | 2497 | NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); |
2731 | #endif | 2498 | #endif |
2732 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2733 | if (rt->rt_multipath_alg != IP_MP_ALG_NONE) | ||
2734 | NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg); | ||
2735 | #endif | ||
2736 | if (rt->fl.iif) | 2499 | if (rt->fl.iif) |
2737 | NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); | 2500 | NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); |
2738 | else if (rt->rt_src != rt->fl.fl4_src) | 2501 | else if (rt->rt_src != rt->fl.fl4_src) |