From 5734509c0545ebd95a5b8e3f22a911c1a39ffa1b Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Sun, 25 Dec 2011 17:52:09 +0100 Subject: babeld: Initial import, for Babel routing protocol. * Initial import of the Babel routing protocol, ported to Quagga. * LICENCE: Update the original LICENCE file to include all known potentially applicable copyright claims. Ask that any future contributors to babeld/ grant MIT/X11 licence to their work. * *.{c,h}: Add GPL headers, in according with the SFLC guidance on dealing with potentially mixed GPL/other licensed work, at: https://www.softwarefreedom.org/resources/2007/gpl-non-gpl-collaboration.html --- babeld/babeld.c | 766 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 766 insertions(+) create mode 100644 babeld/babeld.c (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c new file mode 100644 index 00000000..18b4e34f --- /dev/null +++ b/babeld/babeld.c @@ -0,0 +1,766 @@ +/* + * This file is free software: you may copy, redistribute and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 2 of the License, or (at your + * option) any later version. + * + * This file 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 this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + +Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include "command.h" +#include "prefix.h" +#include "memory.h" +#include "memtypes.h" +#include "table.h" +#include "distribute.h" +#include "prefix.h" +#include "filter.h" +#include "plist.h" + +#include "babel_main.h" +#include "babeld.h" +#include "util.h" +#include "net.h" +#include "kernel.h" +#include "babel_interface.h" +#include "neighbour.h" +#include "route.h" +#include "message.h" +#include "resend.h" +#include "babel_filter.h" + + +static int babel_init_routing_process(struct thread *thread); +static void babel_get_myid(void); +static void babel_initial_noise(void); +static int babel_read_protocol (struct thread *thread); +static int babel_main_loop(struct thread *thread); +static void babel_set_timer(struct timeval *timeout); +static void babel_fill_with_next_timeout(struct timeval *tv); + + +/* Informations relative to the babel running daemon. */ +static struct babel *babel_routing_process = NULL; +static unsigned char *receive_buffer = NULL; +static int receive_buffer_size = 0; + +/* timeouts */ +struct timeval check_neighbours_timeout; +static time_t expiry_time; +static time_t source_expiry_time; + +/* Babel node structure. */ +static struct cmd_node cmd_babel_node = +{ + .node = BABEL_NODE, + .prompt = "%s(config-router)# ", + .vtysh = 1, +}; + +/* print current babel configuration on vty */ +static int +babel_config_write (struct vty *vty) +{ + return 0; +} + + +static int +babel_create_routing_process (void) +{ + assert (babel_routing_process == NULL); + + /* Allocaste Babel instance. */ + babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel)); + + /* Initialize timeouts */ + gettime(&babel_now); + expiry_time = babel_now.tv_sec + roughly(30); + source_expiry_time = babel_now.tv_sec + roughly(300); + + /* Make socket for Babel protocol. */ + protocol_socket = babel_socket(protocol_port); + if (protocol_socket < 0) { + zlog_err("Couldn't create link local socket: %s", safe_strerror(errno)); + goto fail; + } + + /* Threads. */ + babel_routing_process->t_read = + thread_add_read(master, &babel_read_protocol, NULL, protocol_socket); + /* wait a little: zebra will announce interfaces, addresses, routes... */ + babel_routing_process->t_update = + thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L); + return 0; + +fail: + XFREE(MTYPE_BABEL, babel_routing_process); + babel_routing_process = NULL; + return -1; +} + +/* thread reading entries form others babel daemons */ +static int +babel_read_protocol (struct thread *thread) +{ + int rc; + struct interface *ifp = NULL; + struct sockaddr_in6 sin6; + struct listnode *linklist_node = NULL; + + assert(babel_routing_process != NULL); + assert(protocol_socket >= 0); + + rc = babel_recv(protocol_socket, + receive_buffer, receive_buffer_size, + (struct sockaddr*)&sin6, sizeof(sin6)); + if(rc < 0) { + if(errno != EAGAIN && errno != EINTR) { + zlog_err("recv: %s", safe_strerror(errno)); + } + } else { + FOR_ALL_INTERFACES(ifp, linklist_node) { + if(!if_up(ifp)) + continue; + if(ifp->ifindex == sin6.sin6_scope_id) { + parse_packet((unsigned char*)&sin6.sin6_addr, ifp, + receive_buffer, rc); + break; + } + } + } + + /* re-add thread */ + babel_routing_process->t_read = + thread_add_read(master, &babel_read_protocol, NULL, protocol_socket); + return 0; +} + +/* Zebra will give some information, especially about interfaces. This function + must be call with a litte timeout wich may give zebra the time to do his job, + making these inits have sense. */ +static int +babel_init_routing_process(struct thread *thread) +{ + babel_get_myid(); + debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid)); + babel_initial_noise(); + babel_main_loop(thread);/* this function self-add to the t_update thread */ + return 0; +} + +/* fill "myid" with an unique id (only if myid != {0}). */ +static void +babel_get_myid(void) +{ + struct interface *ifp = NULL; + struct listnode *linklist_node = NULL; + int rc; + int i; + + /* if we already have an id (from state file), we return. */ + if (memcmp(myid, zeroes, 8) != 0) { + return; + } + + FOR_ALL_INTERFACES(ifp, linklist_node) { + /* ifp->ifindex is not necessarily valid at this point */ + int ifindex = if_nametoindex(ifp->name); + if(ifindex > 0) { + unsigned char eui[8]; + rc = if_eui64(ifp->name, ifindex, eui); + if(rc < 0) + continue; + memcpy(myid, eui, 8); + return; + } + } + + /* We failed to get a global EUI64 from the interfaces we were given. + Let's try to find an interface with a MAC address. */ + for(i = 1; i < 256; i++) { + char buf[IF_NAMESIZE], *ifname; + unsigned char eui[8]; + ifname = if_indextoname(i, buf); + if(ifname == NULL) + continue; + rc = if_eui64(ifname, i, eui); + if(rc < 0) + continue; + memcpy(myid, eui, 8); + return; + } + + zlog_err("Warning: couldn't find router id -- using random value."); + + rc = read_random_bytes(myid, 8); + if(rc < 0) { + zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno)); + exit(1); + } + /* Clear group and global bits */ + myid[0] &= ~3; +} + +/* Make some noise so that others notice us, and send retractions in + case we were restarted recently */ +static void +babel_initial_noise(void) +{ + struct interface *ifp = NULL; + struct listnode *linklist_node = NULL; + + FOR_ALL_INTERFACES(ifp, linklist_node) { + if(!if_up(ifp)) + continue; + /* Apply jitter before we send the first message. */ + usleep(roughly(10000)); + gettime(&babel_now); + send_hello(ifp); + send_wildcard_retraction(ifp); + } + + FOR_ALL_INTERFACES(ifp, linklist_node) { + if(!if_up(ifp)) + continue; + usleep(roughly(10000)); + gettime(&babel_now); + send_hello(ifp); + send_wildcard_retraction(ifp); + send_self_update(ifp); + send_request(ifp, NULL, 0); + flushupdates(ifp); + flushbuf(ifp); + } +} + +/* Delete all the added babel routes, make babeld only speak to zebra. */ +static void +babel_clean_routing_process() +{ + babel_uninstall_all_routes(); + babel_interface_close_all(); + + /* cancel threads */ + if (babel_routing_process->t_read != NULL) { + thread_cancel(babel_routing_process->t_read); + } + if (babel_routing_process->t_update != NULL) { + thread_cancel(babel_routing_process->t_update); + } + + XFREE(MTYPE_BABEL, babel_routing_process); + babel_routing_process = NULL; +} + +/* Function used with timeout. */ +static int +babel_main_loop(struct thread *thread) +{ + struct timeval tv; + struct interface *ifp = NULL; + struct listnode *linklist_node = NULL; + + while(1) { + gettime(&babel_now); + + /* timeouts --------------------------------------------------------- */ + /* get the next timeout */ + babel_fill_with_next_timeout(&tv); + /* if there is no timeout, we must wait. */ + if(timeval_compare(&tv, &babel_now) > 0) { + timeval_minus(&tv, &tv, &babel_now); + debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs", + tv.tv_sec * 1000 + tv.tv_usec / 1000); + /* it happens often to have less than 1 ms, it's bad. */ + timeval_add_msec(&tv, &tv, 300); + babel_set_timer(&tv); + return 0; + } + + gettime(&babel_now); + + /* update database -------------------------------------------------- */ + if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) { + int msecs; + msecs = check_neighbours(); + msecs = MAX(msecs, 10); + schedule_neighbours_check(msecs, 1); + } + + if(babel_now.tv_sec >= expiry_time) { + expire_routes(); + expire_resend(); + expiry_time = babel_now.tv_sec + roughly(30); + } + + if(babel_now.tv_sec >= source_expiry_time) { + expire_sources(); + source_expiry_time = babel_now.tv_sec + roughly(300); + } + + FOR_ALL_INTERFACES(ifp, linklist_node) { + babel_interface_nfo *babel_ifp = NULL; + if(!if_up(ifp)) + continue; + babel_ifp = babel_get_if_nfo(ifp); + if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0) + send_hello(ifp); + if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0) + send_update(ifp, 0, NULL, 0); + if(timeval_compare(&babel_now, + &babel_ifp->update_flush_timeout) >= 0) + flushupdates(ifp); + } + + if(resend_time.tv_sec != 0) { + if(timeval_compare(&babel_now, &resend_time) >= 0) + do_resend(); + } + + if(unicast_flush_timeout.tv_sec != 0) { + if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0) + flush_unicast(1); + } + + FOR_ALL_INTERFACES(ifp, linklist_node) { + babel_interface_nfo *babel_ifp = NULL; + if(!if_up(ifp)) + continue; + babel_ifp = babel_get_if_nfo(ifp); + if(babel_ifp->flush_timeout.tv_sec != 0) { + if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0) + flushbuf(ifp); + } + } + } + + assert(0); /* this line should never be reach */ +} + +static void +printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname) +{ + static struct timeval curr_tv; + static char buffer[200]; + static const char *curr_tag = NULL; + + switch (cmd) { + case 0: /* reset timeval */ + curr_tv = *tv; + if(ifname != NULL) { + snprintf(buffer, 200L, "interface: %s; %s", ifname, tag); + curr_tag = buffer; + } else { + curr_tag = tag; + } + break; + case 1: /* take the min */ + if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */ + break; + } + if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec && + tv->tv_usec < curr_tv.tv_usec)) { + curr_tv = *tv; + if(ifname != NULL) { + snprintf(buffer, 200L, "interface: %s; %s", ifname, tag); + curr_tag = buffer; + } else { + curr_tag = tag; + } + } + break; + case 2: /* print message */ + debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag); + break; + default: + break; + } +} + +static void +babel_fill_with_next_timeout(struct timeval *tv) +{ +#if (defined NO_DEBUG) +#define printIfMin(a,b,c,d) +#else +#define printIfMin(a,b,c,d) \ + if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);} + + struct interface *ifp = NULL; + struct listnode *linklist_node = NULL; + + *tv = check_neighbours_timeout; + printIfMin(tv, 0, "check_neighbours_timeout", NULL); + timeval_min_sec(tv, expiry_time); + printIfMin(tv, 1, "expiry_time", NULL); + timeval_min_sec(tv, source_expiry_time); + printIfMin(tv, 1, "source_expiry_time", NULL); + timeval_min(tv, &resend_time); + printIfMin(tv, 1, "resend_time", NULL); + FOR_ALL_INTERFACES(ifp, linklist_node) { + babel_interface_nfo *babel_ifp = NULL; + if(!if_up(ifp)) + continue; + babel_ifp = babel_get_if_nfo(ifp); + timeval_min(tv, &babel_ifp->flush_timeout); + printIfMin(tv, 1, "flush_timeout", ifp->name); + timeval_min(tv, &babel_ifp->hello_timeout); + printIfMin(tv, 1, "hello_timeout", ifp->name); + timeval_min(tv, &babel_ifp->update_timeout); + printIfMin(tv, 1, "update_timeout", ifp->name); + timeval_min(tv, &babel_ifp->update_flush_timeout); + printIfMin(tv, 1, "update_flush_timeout",ifp->name); + } + timeval_min(tv, &unicast_flush_timeout); + printIfMin(tv, 1, "unicast_flush_timeout", NULL); + printIfMin(tv, 2, NULL, NULL); +#undef printIfMin +#endif +} + +/* set the t_update thread of the babel routing process to be launch in + 'timeout' (approximate at the milisecond) */ +static void +babel_set_timer(struct timeval *timeout) +{ + long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + if (babel_routing_process->t_update != NULL) { + thread_cancel(babel_routing_process->t_update); + } + babel_routing_process->t_update = + thread_add_timer_msec(master, &babel_main_loop, NULL, msecs); +} + +/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */ +void +schedule_neighbours_check(int msecs, int override) +{ + struct timeval timeout; + + timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2)); + if(override) + check_neighbours_timeout = timeout; + else + timeval_min(&check_neighbours_timeout, &timeout); +} + +int +resize_receive_buffer(int size) +{ + if(size <= receive_buffer_size) + return 0; + + if(receive_buffer == NULL) { + receive_buffer = malloc(size); + if(receive_buffer == NULL) { + zlog_err("malloc(receive_buffer): %s", safe_strerror(errno)); + return -1; + } + receive_buffer_size = size; + } else { + unsigned char *new; + new = realloc(receive_buffer, size); + if(new == NULL) { + zlog_err("realloc(receive_buffer): %s", safe_strerror(errno)); + return -1; + } + receive_buffer = new; + receive_buffer_size = size; + } + return 1; +} + +static void +babel_distribute_update (struct distribute *dist) +{ + struct interface *ifp; + babel_interface_nfo *babel_ifp; + struct access_list *alist; + struct prefix_list *plist; + + if (! dist->ifname) + return; + + ifp = if_lookup_by_name (dist->ifname); + if (ifp == NULL) + return; + + babel_ifp = babel_get_if_nfo(ifp); + + if (dist->list[DISTRIBUTE_IN]) { + alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]); + if (alist) + babel_ifp->list[BABEL_FILTER_IN] = alist; + else + babel_ifp->list[BABEL_FILTER_IN] = NULL; + } else { + babel_ifp->list[BABEL_FILTER_IN] = NULL; + } + + if (dist->list[DISTRIBUTE_OUT]) { + alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]); + if (alist) + babel_ifp->list[BABEL_FILTER_OUT] = alist; + else + babel_ifp->list[BABEL_FILTER_OUT] = NULL; + } else { + babel_ifp->list[BABEL_FILTER_OUT] = NULL; + } + + if (dist->prefix[DISTRIBUTE_IN]) { + plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]); + if (plist) + babel_ifp->prefix[BABEL_FILTER_IN] = plist; + else + babel_ifp->prefix[BABEL_FILTER_IN] = NULL; + } else { + babel_ifp->prefix[BABEL_FILTER_IN] = NULL; + } + + if (dist->prefix[DISTRIBUTE_OUT]) { + plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]); + if (plist) + babel_ifp->prefix[BABEL_FILTER_OUT] = plist; + else + babel_ifp->prefix[BABEL_FILTER_OUT] = NULL; + } else { + babel_ifp->prefix[BABEL_FILTER_OUT] = NULL; + } +} + +void +babel_distribute_update_interface (struct interface *ifp) +{ + struct distribute *dist; + + dist = distribute_lookup (ifp->name); + if (dist) + babel_distribute_update (dist); +} + +/* Update all interface's distribute list. */ +static void +babel_distribute_update_all (struct prefix_list *notused) +{ + struct interface *ifp; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + babel_distribute_update_interface (ifp); +} + +static void +babel_distribute_update_all_wrapper (struct access_list *notused) +{ + babel_distribute_update_all(NULL); +} + + +/* [Command] */ +DEFUN (router_babel, + router_babel_cmd, + "router babel", + "Enable a routing process\n" + "Make Babel instance command\n") +{ + int ret; + + vty->node = BABEL_NODE; + + if (!babel_routing_process) { + ret = babel_create_routing_process (); + + /* Notice to user we couldn't create Babel. */ + if (ret < 0) { + zlog_warn ("can't create Babel"); + } + } + + return CMD_SUCCESS; +} + +/* [Command] */ +DEFUN (no_router_babel, + no_router_babel_cmd, + "no router babel", + NO_STR + "Disable a routing process\n" + "Remove Babel instance command\n") +{ + if(babel_routing_process) + babel_clean_routing_process(); + return CMD_SUCCESS; +} + +/* [Babel Command] */ +DEFUN (babel_set_protocol_group, + babel_set_protocol_group_cmd, + "protocol group ADDR", + "Set the protocol group, default is ff02::1:6.\n" + "IPv6 address") +{ + int ret; + struct prefix p; + + ret = str2prefix (argv[0], &p); + + /* Given string is: */ + if (ret) { /* an IPv4 or v6 network */ + if (p.family != AF_INET6) { + return CMD_WARNING; + } + in6addr_to_uchar(protocol_group, &p.u.prefix6); + } else { /* an interface name */ + return CMD_WARNING; + } + + if (ret < 0) { + vty_out (vty, "%s must be an ipv6 address%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +/* [Babel Command] */ +DEFUN (babel_set_protocol_port, + babel_set_protocol_port_cmd, + "protocol port <1-65535>", + "Set the protocol port (default is defined in RFC).\n" + "IPv6 address") +{ + int port = atoi(argv[0]); + protocol_port = port; + + return CMD_SUCCESS; +} + + +void +babeld_quagga_init(void) +{ + + install_node(&cmd_babel_node, &babel_config_write); + + install_element(CONFIG_NODE, &router_babel_cmd); + install_element(CONFIG_NODE, &no_router_babel_cmd); + + install_default(BABEL_NODE); + + babel_if_init(); + + /* Access list install. */ + access_list_init (); + access_list_add_hook (babel_distribute_update_all_wrapper); + access_list_delete_hook (babel_distribute_update_all_wrapper); + + /* Prefix list initialize.*/ + prefix_list_init (); + prefix_list_add_hook (babel_distribute_update_all); + prefix_list_delete_hook (babel_distribute_update_all); + + /* Distribute list install. */ + distribute_list_init (BABEL_NODE); + distribute_list_add_hook (babel_distribute_update); + distribute_list_delete_hook (babel_distribute_update); +} + +int /* DEPRECATED: for compatibility with old babeld (configuration.{c,h})*/ +input_filter(const unsigned char *id, + const unsigned char *prefix, unsigned short plen, + const unsigned char *neigh, unsigned int ifindex) +{ + struct interface *ifp = NULL; + struct prefix p; + p.family = v4mapped(prefix) ? AF_INET : AF_INET6; + p.prefixlen = plen; + if (p.family == AF_INET) { + uchar_to_inaddr(&p.u.prefix4, prefix); + } else { + uchar_to_in6addr(&p.u.prefix6, prefix); + } + + ifp = if_lookup_by_index(ifindex); + if (ifp != NULL) { + return babel_filter_in(&p, babel_get_if_nfo(ifp)); + } + + return babel_filter_in(&p, NULL); +} + +int /* DEPRECATED: for compatibility with old babeld */ +output_filter(const unsigned char *id, const unsigned char *prefix, + unsigned short plen, unsigned int ifindex) +{ + struct interface *ifp = NULL; + struct prefix p; + p.family = v4mapped(prefix) ? AF_INET : AF_INET6; + p.prefixlen = plen; + if (p.family == AF_INET) { + uchar_to_inaddr(&p.u.prefix4, prefix); + } else { + uchar_to_in6addr(&p.u.prefix6, prefix); + } + + ifp = if_lookup_by_index(ifindex); + if (ifp != NULL) { + return babel_filter_out(&p, babel_get_if_nfo(ifp)); + } + + return babel_filter_out(&p, NULL); +} + +int /* DEPRECATED: for compatibility with old babeld */ +redistribute_filter(const unsigned char *prefix, unsigned short plen, + unsigned int ifindex, int proto) +{ + struct interface *ifp = NULL; + struct prefix p; + p.family = v4mapped(prefix) ? AF_INET : AF_INET6; + p.prefixlen = plen; + if (p.family == AF_INET) { + uchar_to_inaddr(&p.u.prefix4, prefix); + } else { + uchar_to_in6addr(&p.u.prefix6, prefix); + } + + ifp = if_lookup_by_index(ifindex); + if (ifp != NULL) { + return babel_filter_redistribute(&p,babel_get_if_nfo(ifp)); + } + + return babel_filter_redistribute(&p, NULL); +} -- cgit v1.2.1 From 3dbda0ceebe369a1071600fe7d8d8ecf45f1027c Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Sun, 8 Jan 2012 16:52:36 +0400 Subject: babeld: address some compilation warnings Including system headers is not necessary with zebra.h included and sometimes results in "__ASSERT_FUNCTION redefined" compilation warning. * babeld.c * babel_distribute_update_interface(): make static * babel_interface.c * interface_config_write(): unused 'babel_ifp' * don't include system headers * message.c * send_request(): unused 'babel_ifp' * send_multihop_request(): idem * don't include system headers * route.c: don't include system headers * xroute.c: idem * source.h: newline at EOF * message.h: idem --- babeld/babeld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 18b4e34f..3dc35b5d 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -560,7 +560,7 @@ babel_distribute_update (struct distribute *dist) } } -void +static void babel_distribute_update_interface (struct interface *ifp) { struct distribute *dist; -- cgit v1.2.1 From d3351d1ebf99591cf436035bb148e4ae0b351ffc Mon Sep 17 00:00:00 2001 From: Matthieu Boutier Date: Thu, 19 Jan 2012 22:36:56 +0100 Subject: babeld: add command: "show_babel_running_config". --- babeld/babeld.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 3dc35b5d..9f2ab5d9 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -764,3 +764,10 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, return babel_filter_redistribute(&p, NULL); } + +void +show_babeld_configuration (struct vty *vty) +{ + vty_out(vty, "babeld running process %s.%s", + babel_routing_process ? "enable" : "disable", VTY_NEWLINE); +} -- cgit v1.2.1 From 3f031ed536cf96d44015cf49d1f734d15d194f0a Mon Sep 17 00:00:00 2001 From: Matthieu Boutier Date: Wed, 18 Jan 2012 23:03:00 +0100 Subject: babeld: fix commands informations messages. --- babeld/babeld.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 9f2ab5d9..6487bbe1 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -593,7 +593,8 @@ DEFUN (router_babel, router_babel_cmd, "router babel", "Enable a routing process\n" - "Make Babel instance command\n") + "Make Babel instance command\n" + "No attributes\n") { int ret; @@ -617,7 +618,8 @@ DEFUN (no_router_babel, "no router babel", NO_STR "Disable a routing process\n" - "Remove Babel instance command\n") + "Remove Babel instance command\n" + "No attributes\n") { if(babel_routing_process) babel_clean_routing_process(); -- cgit v1.2.1 From 6dfeb3f6cfaf89ce0e11421b48feb2965a43ffd6 Mon Sep 17 00:00:00 2001 From: Matthieu Boutier Date: Fri, 20 Jan 2012 17:53:57 +0100 Subject: babeld: fix bug due to v4mapped addresses. --- babeld/babeld.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 6487bbe1..0cf8c8a1 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -708,7 +708,7 @@ input_filter(const unsigned char *id, struct interface *ifp = NULL; struct prefix p; p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = plen; + p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; if (p.family == AF_INET) { uchar_to_inaddr(&p.u.prefix4, prefix); } else { @@ -730,7 +730,7 @@ output_filter(const unsigned char *id, const unsigned char *prefix, struct interface *ifp = NULL; struct prefix p; p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = plen; + p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; if (p.family == AF_INET) { uchar_to_inaddr(&p.u.prefix4, prefix); } else { @@ -752,7 +752,7 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, struct interface *ifp = NULL; struct prefix p; p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = plen; + p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; if (p.family == AF_INET) { uchar_to_inaddr(&p.u.prefix4, prefix); } else { -- cgit v1.2.1 From c35fafdf887aa32c5be6ad738d3a3b0140cea6e8 Mon Sep 17 00:00:00 2001 From: Matthieu Boutier Date: Mon, 23 Jan 2012 23:46:32 +0100 Subject: babeld: babelz merge. Babelz is the last version of the stand-alone babel daemon. In particular, it use multiple channels to diminuate interferences. Please refer to this one for more details. --- babeld/babeld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 0cf8c8a1..d69662c0 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -269,7 +269,7 @@ babel_initial_noise(void) static void babel_clean_routing_process() { - babel_uninstall_all_routes(); + flush_all_routes(); babel_interface_close_all(); /* cancel threads */ -- cgit v1.2.1 From 69394543597a0fd8c161c5c8a0d25c8b1cfa8a93 Mon Sep 17 00:00:00 2001 From: Matthieu Boutier Date: Sat, 28 Jan 2012 10:35:12 +0100 Subject: babeld: state-file was loaded too early. Initial seqno too. --- babeld/babeld.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index d69662c0..33b5d9e1 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -173,7 +173,9 @@ babel_read_protocol (struct thread *thread) static int babel_init_routing_process(struct thread *thread) { + myseqno = (random() & 0xFFFF); babel_get_myid(); + babel_load_state_file(); debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid)); babel_initial_noise(); babel_main_loop(thread);/* this function self-add to the t_update thread */ -- cgit v1.2.1 From 38846de1fd7fa9005933564de28360fb9bdf02bb Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Tue, 7 Feb 2012 05:43:36 +0100 Subject: babeld: Error handling and tweaks for babeld commands. --- babeld/babeld.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 33b5d9e1..da074349 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -608,6 +608,7 @@ DEFUN (router_babel, /* Notice to user we couldn't create Babel. */ if (ret < 0) { zlog_warn ("can't create Babel"); + return CMD_WARNING; } } @@ -666,9 +667,11 @@ DEFUN (babel_set_protocol_port, "Set the protocol port (default is defined in RFC).\n" "IPv6 address") { - int port = atoi(argv[0]); - protocol_port = port; + int port; + VTY_GET_INTEGER_RANGE("port", port, argv[0], 1, 0xFFFF); + + protocol_port = port; return CMD_SUCCESS; } -- cgit v1.2.1 From 31e2a19fd2b4aca34b1d2f5e2eb8c9a44b9ea6c9 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Thu, 9 Feb 2012 14:06:11 +0100 Subject: babeld: refactor filtering stubs. Factorise the common parts of the in/out filtering functions. This also fixes a bug with filtered out routes, which in babeld are signalled by a filter returing INFINITY, not -1. --- babeld/babeld.c | 61 ++++++++++----------------------------------------------- 1 file changed, 10 insertions(+), 51 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index da074349..14990a68 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -705,71 +705,30 @@ babeld_quagga_init(void) distribute_list_delete_hook (babel_distribute_update); } -int /* DEPRECATED: for compatibility with old babeld (configuration.{c,h})*/ +/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */ + +int input_filter(const unsigned char *id, const unsigned char *prefix, unsigned short plen, const unsigned char *neigh, unsigned int ifindex) { - struct interface *ifp = NULL; - struct prefix p; - p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; - if (p.family == AF_INET) { - uchar_to_inaddr(&p.u.prefix4, prefix); - } else { - uchar_to_in6addr(&p.u.prefix6, prefix); - } - - ifp = if_lookup_by_index(ifindex); - if (ifp != NULL) { - return babel_filter_in(&p, babel_get_if_nfo(ifp)); - } - - return babel_filter_in(&p, NULL); + return babel_filter(0, prefix, plen, ifindex); } -int /* DEPRECATED: for compatibility with old babeld */ +int output_filter(const unsigned char *id, const unsigned char *prefix, unsigned short plen, unsigned int ifindex) { - struct interface *ifp = NULL; - struct prefix p; - p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; - if (p.family == AF_INET) { - uchar_to_inaddr(&p.u.prefix4, prefix); - } else { - uchar_to_in6addr(&p.u.prefix6, prefix); - } - - ifp = if_lookup_by_index(ifindex); - if (ifp != NULL) { - return babel_filter_out(&p, babel_get_if_nfo(ifp)); - } - - return babel_filter_out(&p, NULL); + return babel_filter(1, prefix, plen, ifindex); } -int /* DEPRECATED: for compatibility with old babeld */ +/* There's no redistribute filter in Quagga -- the zebra daemon does its + own filtering. */ +int redistribute_filter(const unsigned char *prefix, unsigned short plen, unsigned int ifindex, int proto) { - struct interface *ifp = NULL; - struct prefix p; - p.family = v4mapped(prefix) ? AF_INET : AF_INET6; - p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; - if (p.family == AF_INET) { - uchar_to_inaddr(&p.u.prefix4, prefix); - } else { - uchar_to_in6addr(&p.u.prefix6, prefix); - } - - ifp = if_lookup_by_index(ifindex); - if (ifp != NULL) { - return babel_filter_redistribute(&p,babel_get_if_nfo(ifp)); - } - - return babel_filter_redistribute(&p, NULL); + return 0; } void -- cgit v1.2.1 From b58871ee4d54989c16a60a839a592c9c4ab19cc3 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 11 Feb 2012 13:34:30 +0100 Subject: babeld: remove port and group setting commands. They didn't work anyway, since they're called too late. --- babeld/babeld.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 14990a68..f42a81b6 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -629,53 +629,6 @@ DEFUN (no_router_babel, return CMD_SUCCESS; } -/* [Babel Command] */ -DEFUN (babel_set_protocol_group, - babel_set_protocol_group_cmd, - "protocol group ADDR", - "Set the protocol group, default is ff02::1:6.\n" - "IPv6 address") -{ - int ret; - struct prefix p; - - ret = str2prefix (argv[0], &p); - - /* Given string is: */ - if (ret) { /* an IPv4 or v6 network */ - if (p.family != AF_INET6) { - return CMD_WARNING; - } - in6addr_to_uchar(protocol_group, &p.u.prefix6); - } else { /* an interface name */ - return CMD_WARNING; - } - - if (ret < 0) { - vty_out (vty, "%s must be an ipv6 address%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -/* [Babel Command] */ -DEFUN (babel_set_protocol_port, - babel_set_protocol_port_cmd, - "protocol port <1-65535>", - "Set the protocol port (default is defined in RFC).\n" - "IPv6 address") -{ - int port; - - VTY_GET_INTEGER_RANGE("port", port, argv[0], 1, 0xFFFF); - - protocol_port = port; - return CMD_SUCCESS; -} - - void babeld_quagga_init(void) { -- cgit v1.2.1 From c428edba5fb151844d28fbb41fce1df466a74e42 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 11 Feb 2012 14:02:10 +0100 Subject: babeld: vty commands (hello-interval, update-interval, resend-delay). --- babeld/babeld.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index f42a81b6..07dd92a3 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -629,6 +629,22 @@ DEFUN (no_router_babel, return CMD_SUCCESS; } +/* [Babel Command] */ +DEFUN (babel_set_resend_delay, + babel_set_resend_delay_cmd, + "babel resend-delay <20-655340>", + "Babel commands\n" + "Time before resending a message\n" + "Milliseconds\n") +{ + int interval; + + VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); + + resend_delay = interval; + return CMD_SUCCESS; +} + void babeld_quagga_init(void) { @@ -639,6 +655,7 @@ babeld_quagga_init(void) install_element(CONFIG_NODE, &no_router_babel_cmd); install_default(BABEL_NODE); + install_element(BABEL_NODE, &babel_set_resend_delay_cmd); babel_if_init(); -- cgit v1.2.1 From a14ef5eeccc8c76c41830475bbe3c31c9e14faa5 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Sat, 11 Feb 2012 21:06:16 +0400 Subject: babeld: justify "running-config" meaning in CLI The primary focus of this commit is to make "show running-config" command display more current configuration, including some of the bits previously seen in the output of "show babel running-config". Besides that, the following commands were renamed for consistency with the syntax of other components: "debug *" to "debug babel *" (and moved to top level) "show babel running-config" to "show babel parameters" * babel_interface.c * show_babel_running_config(): rename to show_babel_parameters(), update syntax pattern, don't call show_babeld_configuration() * babel_if_init(): update respectively * babel_enable_if_config_write(): new VTY helper for static babel_enable_if * babel_interface.h: add extern declaration * babel_main.c: unset all debug options by default * show_babel_main_configuration(): remove debug options decoder * babel_zebra.c * babel_debug(): rename to debug_babel(), update syntax pattern * no_babel_debug(): rename to no_debug_babel(), update syntax pattern * babelz_zebra_init(): update respectively * debug_babel_config_write() new VTY helper for static debug_type * babel_zebra.h: add extern declaration * babeld.c * babel_config_write(): add the code to output "debug babel *", "router babel", "redistribute *" and "network *" statements * show_babeld_configuration(): dismiss * babeld.h: remove extern declaration * babeld.texi: update for renamed commands * babeld.conf.sample: idem, add debug statements block --- babeld/babeld.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 07dd92a3..9fea2e10 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -59,6 +59,7 @@ THE SOFTWARE. #include "message.h" #include "resend.h" #include "babel_filter.h" +#include "babel_zebra.h" static int babel_init_routing_process(struct thread *thread); @@ -92,7 +93,26 @@ static struct cmd_node cmd_babel_node = static int babel_config_write (struct vty *vty) { - return 0; + int lines = 0; + int i; + + /* list enabled debug modes */ + lines += debug_babel_config_write (vty); + + if (!babel_routing_process) + return lines; + vty_out (vty, "router babel%s", VTY_NEWLINE); + /* list enabled interfaces */ + lines = 1 + babel_enable_if_config_write (vty); + /* list redistributed protocols */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default && zclient->redist[i]) + { + vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE); + lines++; + } + + return lines; } @@ -701,9 +721,3 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, return 0; } -void -show_babeld_configuration (struct vty *vty) -{ - vty_out(vty, "babeld running process %s.%s", - babel_routing_process ? "enable" : "disable", VTY_NEWLINE); -} -- cgit v1.2.1 From cbde15513ba47f6e7f6d02fcafcfb12cd5b1df77 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Tue, 14 Feb 2012 15:12:03 +0400 Subject: babeld: 3 more timing statements in config text This commit makes the following lines visible in running-config text, when respective intervals are configured to non-default values: * babel hello-interval * babel update-interval * babel resend-delay --- babeld/babeld.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'babeld/babeld.c') diff --git a/babeld/babeld.c b/babeld/babeld.c index 9fea2e10..1ae3f042 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -102,6 +102,11 @@ babel_config_write (struct vty *vty) if (!babel_routing_process) return lines; vty_out (vty, "router babel%s", VTY_NEWLINE); + if (resend_delay != BABEL_DEFAULT_RESEND_DELAY) + { + vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE); + lines++; + } /* list enabled interfaces */ lines = 1 + babel_enable_if_config_write (vty); /* list redistributed protocols */ -- cgit v1.2.1