[quagga-dev 4362] multipath policy support for quagga

Piotr Chytla pch at packetconsulting.pl
Mon Sep 18 23:13:30 BST 2006


Hi

In last few days or maybe more ;) I've been working on multipath routing ,
enable-multipath for quagga works great , routes inserted for ex. by ospf 
to routing table have 2 or more nexthops , but problem is that
packet distribiution is based on route cache. Route cache can't balance traffic 
between two or more connections (I've 2 machines connected with 2 ethernet connections, 
with ospf between them) , when route is cached , all 
flows will goes only via one connection.
I've write patch for quagga 0.99.4 (It will also fit to cvs), that
implement selection of multipath policy(multipath policy is in linux
kernel from 2.6.12) . 

My patch adds commands :

    to configure :
	multipath rr      - Round Robin multipath policy
	multipath drr     - Device round robin multipath policy
	multipath random  - Random multipath policy
	multipath wrandom - Weighted random multipath policy

    enable :
	show multipath    

>From now selection of multipath alg. work only in global mode, when
policy is selected it would be applayed to all multipath routes.
 
Ah the last think , kernel module for multipath must be loaded to kernel 
(multipath_rr/drr/random/wrandom  depends on what multipath policy we
want to use)

BUGS: when multipath policy is selected and no modules are loaded ,
      route will be added as normal route.

paul: my patch don't have configure/config.h.in and rest of the stuff 
      refreshed (needs aclocal and friends)

Of course consider it for inclusion .

/pch

-- 
Dyslexia bug unpatched since 1977 ...
exploit has been leaked to the underground.
-------------- next part --------------
diff -urNa quagga-0.99.4.old/ChangeLog quagga-0.99.4/ChangeLog
--- quagga-0.99.4.old/ChangeLog	2006-05-10 18:17:23.000000000 +0200
+++ quagga-0.99.4/ChangeLog	2006-09-18 22:44:47.000000000 +0200
@@ -1,3 +1,9 @@
+2006-09-19 Piotr Chytła <pch at packetconsulting.pl>
+
+	* configure.ac lib/commands.h lib/zebra.h zebra/zserv.c 
+	  zebra/zserv.h zebra/multipath.h - Multipath policy support 
+	  for zebra
+
 2006-05-10 Paul Jakma <paul.jakma at sun.com>
 
 	* configure.ac: Bump to 0.99.4
diff -urNa quagga-0.99.4.old/configure.ac quagga-0.99.4/configure.ac
--- quagga-0.99.4.old/configure.ac	2006-05-10 21:52:36.000000000 +0200
+++ quagga-0.99.4/configure.ac	2006-09-18 22:22:38.000000000 +0200
@@ -351,7 +351,7 @@
 
 AC_CHECK_HEADERS([sys/socket.h netinet/in_systm.h netinet/in.h \
 		 net/if_dl.h net/netopt.h inet/nd.h net/route.h \
-		 net/if.h net/if_var.h netinet/in_var.h])
+		 net/if.h net/if_var.h netinet/in_var.h linux/ip_mp_alg.h])
 
 dnl V6 headers are checked below, after we check for v6
 
@@ -591,6 +591,17 @@
 AC_SUBST(KERNEL_METHOD)
 AC_SUBST(OTHER_METHOD)
 
+dnl ----------
+dnl Check for RTA_MP_ALGO in /usr/include/linux/rtnetlink.h
+dnl ----------
+AC_MSG_CHECKING(for support of multipath alg. in netlink)
+  if grep RTA_MP_ALGO /usr/include/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 check for broken CMSG_FIRSTHDR macro
 dnl ------------------------------------
diff -urNa quagga-0.99.4.old/lib/command.h quagga-0.99.4/lib/command.h
--- quagga-0.99.4.old/lib/command.h	2006-03-30 16:57:42.000000000 +0200
+++ quagga-0.99.4/lib/command.h	2006-09-17 01:39:48.000000000 +0200
@@ -98,6 +98,7 @@
   SMUX_NODE,			/* SNMP configuration node. */
   DUMP_NODE,			/* Packet dump node. */
   FORWARDING_NODE,		/* IP forwarding node. */
+  MULTIPATH_NODE,		/* Multipath policy node */
   VTY_NODE			/* Vty node. */
 };
 
@@ -269,6 +270,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 CLEAR_STR "Reset functions\n"
diff -urNa quagga-0.99.4.old/lib/zebra.h quagga-0.99.4/lib/zebra.h
--- quagga-0.99.4.old/lib/zebra.h	2006-01-31 21:55:54.000000000 +0100
+++ quagga-0.99.4/lib/zebra.h	2006-09-18 21:26:09.000000000 +0200
@@ -167,6 +167,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 */
diff -urNa quagga-0.99.4.old/zebra/multipath.h quagga-0.99.4/zebra/multipath.h
--- quagga-0.99.4.old/zebra/multipath.h	1970-01-01 01:00:00.000000000 +0100
+++ quagga-0.99.4/zebra/multipath.h	2006-09-18 21:14:40.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
+
diff -urNa quagga-0.99.4.old/zebra/rt_netlink.c quagga-0.99.4/zebra/rt_netlink.c
--- quagga-0.99.4.old/zebra/rt_netlink.c	2006-01-31 21:56:03.000000000 +0100
+++ quagga-0.99.4/zebra/rt_netlink.c	2006-09-18 22:23:24.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"
@@ -1752,6 +1753,16 @@
             }
         }
 
+#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));
diff -urNa quagga-0.99.4.old/zebra/zserv.c quagga-0.99.4/zebra/zserv.c
--- quagga-0.99.4.old/zebra/zserv.c	2006-01-31 21:56:04.000000000 +0100
+++ quagga-0.99.4/zebra/zserv.c	2006-09-18 23:41:14.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"
@@ -1146,6 +1147,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);
   
@@ -1584,6 +1588,7 @@
   return CMD_SUCCESS;
 }
 
+
 /* Table configuration write function. */
 static int
 config_write_table (struct vty *vty)
@@ -1723,6 +1728,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)
@@ -1741,6 +1831,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);
@@ -1751,6 +1845,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
@@ -1759,4 +1861,5 @@
   install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
   install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
 #endif /* HAVE_IPV6 */
+
 }
diff -urNa quagga-0.99.4.old/zebra/zserv.h quagga-0.99.4/zebra/zserv.h
--- quagga-0.99.4.old/zebra/zserv.h	2005-11-24 08:47:14.000000000 +0100
+++ quagga-0.99.4/zebra/zserv.h	2006-09-17 15:53:45.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;
 };


More information about the Quagga-dev mailing list