Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
new file mode 100644
index 0000000..7722573
--- /dev/null
+++ b/include/net/ip_mp_alg.h
@@ -0,0 +1,99 @@
+/* ip_mp_alg.h: IPV4 multipath algorithm support.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#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>
+
+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];
+
+	/* mp_alg_select_route _MUST_ be implemented */
+	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)
+			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)
+		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 && ops->mp_alg_remove &&
+	    (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 &&
+		flp1->fl4_src == flp2->fl4_src &&
+		flp1->oif == flp2->oif &&
+#ifdef CONFIG_IP_ROUTE_FWMARK
+		flp1->fl4_fwmark == flp2->fl4_fwmark &&
+#endif
+		!((flp1->fl4_tos ^ flp2->fl4_tos) &
+		  (IPTOS_RT_MASK | RTO_ONLINK));
+}
+
+#endif /* _NET_IP_MP_ALG_H */