--- a/configure.ac +++ b/configure.ac @@ -397,7 +397,7 @@ dnl ------------------------- 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(RT_METHOD) 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 -------------------------- --- a/lib/command.h +++ b/lib/command.h @@ -101,6 +101,7 @@ enum node_type 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 @@ struct desc /* 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" --- a/lib/zebra.h +++ b/lib/zebra.h @@ -176,6 +176,10 @@ typedef int socklen_t; #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 */ --- a/zebra/main.c +++ b/zebra/main.c @@ -44,6 +44,7 @@ struct zebra_t zebrad = { .rtm_table_default = 0, + .mpath = 0, }; /* process id. */ --- /dev/null +++ b/zebra/multipath.h @@ -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 + --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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 @@ netlink_route_multipath (int cmd, struct 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)); --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -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 @@ zebra_client_create (int sock) /* 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 @@ static struct cmd_node forwarding_node = }; +#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 @@ zebra_init (void) 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 @@ zebra_init (void) 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 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -55,6 +55,9 @@ struct zserv /* 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 @@ struct zebra_t /* default table */ int rtm_table_default; + /* multipath policy */ + u_int32_t mpath; + /* rib work queue */ struct work_queue *ribq; struct meta_queue *mq;