summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-03-17 04:00:13 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2005-03-17 04:00:13 -0800
commitded97b801515e8a9c0c32000880fc865a0d2c6d3 (patch)
tree7c8a8d342628a365286ca64fd17952c4ede7c4d6 /include
parent59b51e70e85997a24a744f895255760894fac171 (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.h22
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--include/net/ip_fib.h10
-rw-r--r--include/net/ip_mp_alg.h79
-rw-r--r--include/net/route.h73
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 */