--- 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 +#endif /* HAVE_LINUX_IP_MP_ALG_H */ + #ifdef HAVE_NETDB_H #include #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 + +#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;