--- config.h.in.orig	2010-08-19 11:43:01.000000000 +0200
+++ config.h.in	2010-08-24 10:36:33.000000000 +0200
@@ -824,3 +824,6 @@
 /* Define to empty if the keyword `volatile' does not work. Warning: valid
    code using `volatile' can become incorrect without. Disable with care. */
 #undef volatile
+
+/* Define to 1 if multipath algorithm is supported */
+#undef HAVE_RT_MP_ALGO
--- configure.ac.orig	2010-08-19 11:36:29.000000000 +0200
+++ configure.ac	2010-08-24 10:36:33.000000000 +0200
@@ -397,7 +397,7 @@
 AC_CHECK_HEADERS([stropts.h sys/ksym.h sys/times.h sys/select.h \
 	sys/types.h linux/version.h netdb.h asm/types.h \
 	sys/param.h limits.h signal.h libutil.h \
-	sys/socket.h netinet/in.h time.h sys/time.h])
+	sys/socket.h netinet/in.h time.h sys/time.h linux/ip_mp_alg.h])
 
 dnl Utility macro to avoid retyping includes all the time
 m4_define([QUAGGA_INCLUDES],
@@ -779,6 +779,17 @@
 AC_SUBST(KERNEL_METHOD)
 AC_SUBST(OTHER_METHOD)
 
+dnl ----------
+dnl Check for RTA_MP_ALGO in linux/rtnetlink.h
+dnl ----------
+AC_MSG_CHECKING(for support of multipath alg. in netlink)
+  if grep RTA_MP_ALGO linux/rtnetlink.h >/dev/null 2>&1; then
+    AC_DEFINE(HAVE_RT_MP_ALGO,,RTA_MP exist in rtnetlink)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+
 dnl --------------------------
 dnl Determine IS-IS I/O method
 dnl --------------------------
--- configure.orig	2010-08-19 11:43:02.000000000 +0200
+++ configure	2010-08-24 10:36:33.000000000 +0200
@@ -12141,7 +12141,7 @@
 for ac_header in stropts.h sys/ksym.h sys/times.h sys/select.h \
 	sys/types.h linux/version.h netdb.h asm/types.h \
 	sys/param.h limits.h signal.h libutil.h \
-	sys/socket.h netinet/in.h time.h sys/time.h
+	sys/socket.h netinet/in.h time.h sys/time.h linux/ip_mp_alg.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -15193,6 +15193,21 @@
 
 $as_echo "#define ISIS_METHOD_BPF 3" >>confdefs.h
 
+{ $as_echo "$as_me:$LINENO: checking for support of multipath alg. in netlink" >&5
+$as_echo_n "checking for support of multipath alg. in netlink... " >&6; }
+  if grep RTA_MP_ALGO linux/rtnetlink.h >/dev/null 2>&1; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_RT_MP_ALGO /**/
+_ACEOF
+
+    { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+
 ac_fn_c_check_header_mongrel "$LINENO" "net/bpf.h" "ac_cv_header_net_bpf_h" "$ac_includes_default"
 if test "x$ac_cv_header_net_bpf_h" = x""yes; then :
 
--- lib/command.h.orig	2010-08-19 11:32:24.000000000 +0200
+++ lib/command.h	2010-08-24 10:36:33.000000000 +0200
@@ -101,6 +101,7 @@
   DUMP_NODE,			/* Packet dump node. */
   FORWARDING_NODE,		/* IP forwarding node. */
   PROTOCOL_NODE,                /* protocol filtering node */
+  MULTIPATH_NODE,		/* Multipath policy node */
   VTY_NODE,			/* Vty node. */
 };
 
@@ -272,6 +273,7 @@
 /* Common descriptions. */
 #define SHOW_STR "Show running system information\n"
 #define IP_STR "IP information\n"
+#define MULTIPATH_STR "Configure multipath policy\n"
 #define IPV6_STR "IPv6 information\n"
 #define NO_STR "Negate a command or set its defaults\n"
 #define REDIST_STR "Redistribute information from another routing protocol\n"
--- lib/zebra.h.orig	2010-08-19 11:32:24.000000000 +0200
+++ lib/zebra.h	2010-08-24 10:36:33.000000000 +0200
@@ -176,6 +176,10 @@
 #define RT_TABLE_MAIN		0
 #endif /* HAVE_NETLINK */
 
+#ifdef HAVE_LINUX_IP_MP_ALG_H
+#include <linux/ip_mp_alg.h>
+#endif /* HAVE_LINUX_IP_MP_ALG_H */
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif /* HAVE_NETDB_H */
--- zebra/main.c.orig	2010-08-19 11:32:24.000000000 +0200
+++ zebra/main.c	2010-08-24 10:36:33.000000000 +0200
@@ -44,6 +44,7 @@
 struct zebra_t zebrad =
 {
   .rtm_table_default = 0,
+  .mpath = 0,
 };
 
 /* process id. */
--- zebra/multipath.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ zebra/multipath.h	2010-08-24 10:36:33.000000000 +0200
@@ -0,0 +1,37 @@
+/*
+ * multipath policy names.
+ *
+ * This file is part of Quagga routing suite.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef ZEBRA_MULTIPATH_H
+#define ZEBRA_MULTIPATH_H
+#include <zebra.h>
+
+#ifdef HAVE_LINUX_IP_MP_ALG_H
+
+static char *mp_alg_names[IP_MP_ALG_MAX+1] = {
+                        [IP_MP_ALG_NONE] = "none",
+                        [IP_MP_ALG_RR] = "rr",
+                        [IP_MP_ALG_DRR] = "drr",
+                        [IP_MP_ALG_RANDOM] = "random",
+                        [IP_MP_ALG_WRANDOM] = "wrandom"
+			};
+#endif
+#endif
+
--- zebra/rt_netlink.c.orig	2010-08-19 11:32:24.000000000 +0200
+++ zebra/rt_netlink.c	2010-08-24 10:36:33.000000000 +0200
@@ -36,6 +36,7 @@
 #include "thread.h"
 #include "privs.h"
 
+#include "multipath.h"
 #include "zebra/zserv.h"
 #include "zebra/rt.h"
 #include "zebra/redistribute.h"
@@ -1694,6 +1695,16 @@
       if (src)
         addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
 
+#ifdef HAVE_RT_MP_ALGO
+       if (zebrad.mpath != IP_MP_ALG_NONE)
+       {
+             if (IS_ZEBRA_DEBUG_KERNEL)
+                        zlog_debug("netlink_route_multipath() (multihop): "
+	                           "multipath policy : %s",mp_alg_names[zebrad.mpath]);
+
+            addattr_l (&req.n, 1024, RTA_MP_ALGO, &zebrad.mpath, sizeof(zebrad.mpath));
+       }
+#endif 
       if (rta->rta_len > RTA_LENGTH (0))
         addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta),
                    RTA_PAYLOAD (rta));
--- zebra/zserv.c.orig	2010-08-19 11:32:24.000000000 +0200
+++ zebra/zserv.c	2010-08-24 10:36:33.000000000 +0200
@@ -36,6 +36,7 @@
 #include "privs.h"
 #include "network.h"
 #include "buffer.h"
+#include "multipath.h"
 
 #include "zebra/zserv.h"
 #include "zebra/router-id.h"
@@ -1120,6 +1121,9 @@
   /* Set table number. */
   client->rtm_table = zebrad.rtm_table_default;
 
+  /* Set multipath policy */
+  client->mpath = zebrad.mpath;
+
   /* Add this client to linked list. */
   listnode_add (zebrad.client_list, client);
   
@@ -1697,6 +1701,91 @@
 };
 
 
+#ifdef HAVE_RT_MP_ALGO
+DEFUN (multipath_rr,
+       multipath_rr_cmd,
+       "multipath rr",
+       MULTIPATH_STR
+       "Round Robin multipath policy")
+{
+	  zebrad.mpath=IP_MP_ALG_RR;
+	  return CMD_SUCCESS;
+}
+
+DEFUN (multipath_drr,
+       multipath_drr_cmd,
+       "multipath drr",
+       MULTIPATH_STR
+       "Device round robin multipath policy")
+{
+	  zebrad.mpath=IP_MP_ALG_DRR;
+	  return CMD_SUCCESS;
+}
+
+DEFUN (multipath_random,
+       multipath_random_cmd,
+       "multipath random",
+       MULTIPATH_STR
+       "Random multipath policy")
+{
+	  zebrad.mpath=IP_MP_ALG_RANDOM;
+	  return CMD_SUCCESS;
+}
+
+DEFUN (multipath_wrandom,
+       multipath_wrandom_cmd,
+       "multipath wrandom",
+	MULTIPATH_STR
+       "Weighted random multipath policy")
+{
+         zebrad.mpath=IP_MP_ALG_WRANDOM;
+         return CMD_SUCCESS;
+}
+
+DEFUN (no_multipath,
+	no_multipath_cmd,
+	"no multipath",
+	NO_STR
+	MULTIPATH_STR
+	"Remove multipath policy")
+{
+	zebrad.mpath=IP_MP_ALG_NONE;
+	return CMD_SUCCESS;
+}
+
+DEFUN (show_multipath,
+	show_multipath_cmd,
+	"show multipath",
+	SHOW_STR
+	"Show multipath policy")
+{
+        vty_out (vty, "multipath %s%s", mp_alg_names[zebrad.mpath],
+		             VTY_NEWLINE);
+	return CMD_SUCCESS;
+}
+
+/* multipath policy configuration write function. */
+static int
+config_write_multipath (struct vty *vty)
+{
+
+
+  if (zebrad.mpath)
+    vty_out (vty, "multipath %s%s", mp_alg_names[zebrad.mpath],
+	     VTY_NEWLINE);
+  return 0;
+}
+
+/* table node for multipath policy. */
+struct cmd_node multipath_node =
+{
+	  MULTIPATH_NODE,
+	  "",                           
+	  1
+};
+
+#endif /* HAVE_RT_MP_ALGO */
+
 /* Initialisation of zebra and installation of commands. */
 void
 zebra_init (void)
@@ -1708,6 +1797,10 @@
   install_node (&table_node, config_write_table);
   install_node (&forwarding_node, config_write_forwarding);
 
+#ifdef HAVE_RT_MP_ALGO
+  install_node (&multipath_node, config_write_multipath);
+#endif
+
   install_element (VIEW_NODE, &show_ip_forwarding_cmd);
   install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
   install_element (CONFIG_NODE, &ip_forwarding_cmd);
@@ -1718,6 +1811,14 @@
   install_element (VIEW_NODE, &show_table_cmd);
   install_element (ENABLE_NODE, &show_table_cmd);
   install_element (CONFIG_NODE, &config_table_cmd);
+#ifdef HAVE_RT_MP_ALGO
+  install_element (CONFIG_NODE, &multipath_rr_cmd);
+  install_element (CONFIG_NODE, &multipath_drr_cmd);
+  install_element (CONFIG_NODE, &multipath_random_cmd);
+  install_element (CONFIG_NODE, &multipath_wrandom_cmd);
+  install_element (CONFIG_NODE, &no_multipath_cmd);
+  install_element (ENABLE_NODE, &show_multipath_cmd);
+#endif /* HAVE_RT_MP_ALGO */
 #endif /* HAVE_NETLINK */
 
 #ifdef HAVE_IPV6
--- zebra/zserv.h.orig	2010-08-19 11:32:24.000000000 +0200
+++ zebra/zserv.h	2010-08-24 10:36:33.000000000 +0200
@@ -55,6 +55,9 @@
   /* default routing table this client munges */
   int rtm_table;
 
+  /* multipath policy */
+  u_int32_t mpath;
+
   /* This client's redistribute flag. */
   u_char redist[ZEBRA_ROUTE_MAX];
 
@@ -78,6 +81,9 @@
   /* default table */
   int rtm_table_default;
 
+  /* multipath policy */
+  u_int32_t mpath;
+
   /* rib work queue */
   struct work_queue *ribq;
   struct meta_queue *mq;
