diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2005-03-17 04:00:13 -0800 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2005-03-17 04:00:13 -0800 |
| commit | ded97b801515e8a9c0c32000880fc865a0d2c6d3 (patch) | |
| tree | 7c8a8d342628a365286ca64fd17952c4ede7c4d6 /include | |
| parent | 59b51e70e85997a24a744f895255760894fac171 (diff) | |
[IPV4]: Make multipath algs into true drivers.
This also makes them configurable on a per-route
basis via rtnetlink route attributes.
Based upon suggestions from Thomas Graf and Alexey
Kuznetsov.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/ip_mp_alg.h | 22 | ||||
| -rw-r--r-- | include/linux/rtnetlink.h | 1 | ||||
| -rw-r--r-- | include/net/ip_fib.h | 10 | ||||
| -rw-r--r-- | include/net/ip_mp_alg.h | 79 | ||||
| -rw-r--r-- | include/net/route.h | 73 |
5 files changed, 105 insertions, 80 deletions
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h new file mode 100644 index 000000000000..e234e2008f5d --- /dev/null +++ b/include/linux/ip_mp_alg.h @@ -0,0 +1,22 @@ +/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values. + * + * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com> + * Copyright (C) 2005 David S. Miller <davem@davemloft.net> + */ + +#ifndef _LINUX_IP_MP_ALG_H +#define _LINUX_IP_MP_ALG_H + +enum ip_mp_alg { + IP_MP_ALG_NONE, + IP_MP_ALG_RR, + IP_MP_ALG_DRR, + IP_MP_ALG_RANDOM, + IP_MP_ALG_WRANDOM, + __IP_MP_ALG_MAX +}; + +#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1) + +#endif /* _LINUX_IP_MP_ALG_H */ + diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index b3fec31e7e6f..6d6b2eae47e0 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -250,6 +250,7 @@ enum rtattr_type_t RTA_FLOW, RTA_CACHEINFO, RTA_SESSION, + RTA_MP_ALGO, __RTA_MAX }; diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index c03741febe66..e5a5f6b62f88 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -37,6 +37,7 @@ struct kern_rta { u32 *rta_flow; struct rta_cacheinfo *rta_ci; struct rta_session *rta_sess; + u32 *rta_mp_alg; }; struct fib_info; @@ -81,6 +82,9 @@ struct fib_info { #ifdef CONFIG_IP_ROUTE_MULTIPATH int fib_power; #endif +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + u32 fib_mp_alg; +#endif struct fib_nh fib_nh[0]; #define fib_dev fib_nh[0].nh_dev }; @@ -95,7 +99,7 @@ struct fib_result { unsigned char nh_sel; unsigned char type; unsigned char scope; -#ifdef CONFIG_IP_ROUTE_MULTIPATH_WRANDOM +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED __u32 network; __u32 netmask; #endif @@ -123,10 +127,10 @@ struct fib_result { #define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev) #define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif) -#ifdef CONFIG_IP_ROUTE_MULTIPATH_WRANDOM +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED #define FIB_RES_NETWORK(res) ((res).network) #define FIB_RES_NETMASK(res) ((res).netmask) -#else /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ +#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ #define FIB_RES_NETWORK(res) (0) #define FIB_RES_NETMASK(res) (0) #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h index 60cebf0130a8..9431df22782c 100644 --- a/include/net/ip_mp_alg.h +++ b/include/net/ip_mp_alg.h @@ -4,13 +4,84 @@ * Copyright (C) 2005 David S. Miller <davem@davemloft.net> */ -#ifndef _IP_MP_ALG_H -#define _IP_MP_ALG_H +#ifndef _NET_IP_MP_ALG_H +#define _NET_IP_MP_ALG_H #include <linux/config.h> +#include <linux/ip_mp_alg.h> #include <net/flow.h> +#include <net/route.h> -static int inline multipath_comparekeys(const struct flowi *flp1, +struct fib_nh; + +struct ip_mp_alg_ops { + void (*mp_alg_select_route)(const struct flowi *flp, + struct rtable *rth, struct rtable **rp); + void (*mp_alg_flush)(void); + void (*mp_alg_set_nhinfo)(__u32 network, __u32 netmask, + unsigned char prefixlen, + const struct fib_nh *nh); + void (*mp_alg_remove)(struct rtable *rth); +}; + +extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg); +extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg); + +extern struct ip_mp_alg_ops *ip_mp_alg_table[]; + +static inline int multipath_select_route(const struct flowi *flp, + struct rtable *rth, + struct rtable **rp) +{ +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; + + if (ops && (rth->u.dst.flags & DST_BALANCED)) { + ops->mp_alg_select_route(flp, rth, rp); + return 1; + } +#endif + return 0; +} + +static inline void multipath_flush(void) +{ +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + int i; + + for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) { + struct ip_mp_alg_ops *ops = ip_mp_alg_table[i]; + + if (ops) + ops->mp_alg_flush(); + } +#endif +} + +static inline void multipath_set_nhinfo(struct rtable *rth, + __u32 network, __u32 netmask, + unsigned char prefixlen, + const struct fib_nh *nh) +{ +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; + + if (ops) + ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh); +#endif +} + +static inline void multipath_remove(struct rtable *rth) +{ +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg]; + + if (ops && (rth->u.dst.flags & DST_BALANCED)) + ops->mp_alg_remove(rth); +#endif +} + +static inline int multipath_comparekeys(const struct flowi *flp1, const struct flowi *flp2) { return flp1->fl4_dst == flp2->fl4_dst && @@ -23,4 +94,4 @@ static int inline multipath_comparekeys(const struct flowi *flp1, (IPTOS_RT_MASK | RTO_ONLINK)); } -#endif /* _IP_MP_ALG_H */ +#endif /* _NET_IP_MP_ALG_H */ diff --git a/include/net/route.h b/include/net/route.h index 4e3b782175d6..22da7579d5de 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -202,77 +202,4 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt) return rt->peer; } -#ifdef CONFIG_IP_ROUTE_MULTIPATH_WRANDOM -extern void __multipath_flush(void); -static inline void multipath_flush(void) -{ - __multipath_flush(); -} -#else /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ -static inline void multipath_flush(void) -{ -} -#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ - -#ifdef CONFIG_IP_ROUTE_MULTIPATH_WRANDOM -extern void __multipath_set_nhinfo(__u32 network, - __u32 netmask, - unsigned char prefixlen, - const struct fib_nh* nh); -static inline void multipath_set_nhinfo(__u32 network, - __u32 netmask, - unsigned char prefixlen, - const struct fib_nh* nh) -{ - __multipath_set_nhinfo(network, netmask, prefixlen, nh); -} -#else -static inline void multipath_set_nhinfo(__u32 network, - __u32 netmask, - unsigned char prefixlen, - const struct fib_nh* nh) -{ -} -#endif - - - -#if defined(CONFIG_IP_ROUTE_MULTIPATH_RR) || defined(CONFIG_IP_ROUTE_MULTIPATH_DRR) -extern void __multipath_remove(struct rtable *rt); -static inline void multipath_remove(struct rtable *rt) -{ - if ( rt->u.dst.flags & DST_BALANCED ) - __multipath_remove(rt); -} -#else /* CONFIG_IP_ROUTE_MULTIPATH_RR || CONFIG_IP_ROUTE_MULTIPATH_DRR */ -static inline void multipath_remove(struct rtable *rt) -{ -} -#endif /* CONFIG_IP_ROUTE_MULTIPATH_RR || CONFIG_IP_ROUTE_MULTIPATH_DRR */ - - -#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED -extern void __multipath_selectroute(const struct flowi *flp, - struct rtable *rth, - struct rtable **rp); -static inline int multipath_selectroute(const struct flowi *flp, - struct rtable *rth, - struct rtable **rp) -{ - if (rth->u.dst.flags & DST_BALANCED) { - __multipath_selectroute(flp, rth, rp); - return 1; - } else { - return 0; - } -} -#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ -static inline int multipath_selectroute(const struct flowi *flp, - struct rtable *rth, - struct rtable **rp) -{ - return 0; -} -#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ - #endif /* _ROUTE_H */ |
