]> git.proxmox.com Git - mirror_frr.git/blobdiff - babeld/babeld.c
*: fix source file headers & includes for errcodes
[mirror_frr.git] / babeld / babeld.c
index 07dd92a37edfb136f34f471612de6d791159b826..dd076714286f1ab7c6845dbc645ab80ad425007f 100644 (file)
@@ -1,21 +1,4 @@
-/*  
- *  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 <http://www.gnu.org/licenses/>.  
- *  
- * 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
@@ -41,12 +24,12 @@ THE SOFTWARE.
 #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 "lib_errors.h"
 
 #include "babel_main.h"
 #include "babeld.h"
@@ -59,7 +42,9 @@ THE SOFTWARE.
 #include "message.h"
 #include "resend.h"
 #include "babel_filter.h"
-
+#include "babel_zebra.h"
+#include "babel_memory.h"
+#include "babel_errors.h"
 
 static int babel_init_routing_process(struct thread *thread);
 static void babel_get_myid(void);
@@ -92,7 +77,55 @@ static struct cmd_node cmd_babel_node =
 static int
 babel_config_write (struct vty *vty)
 {
-    return 0;
+    int lines = 0;
+    int afi;
+    int i;
+
+    /* list enabled debug modes */
+    lines += debug_babel_config_write (vty);
+
+    if (!babel_routing_process)
+        return lines;
+    vty_out (vty, "router babel\n");
+    if (diversity_kind != DIVERSITY_NONE)
+    {
+        vty_out (vty, " babel diversity\n");
+        lines++;
+    }
+    if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
+    {
+        vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
+        lines++;
+    }
+    if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
+    {
+        vty_out (vty, " babel resend-delay %u\n", resend_delay);
+        lines++;
+    }
+    if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
+    {
+        vty_out (vty, " babel smoothing-half-life %u\n",
+                 smoothing_half_life);
+        lines++;
+    }
+    /* list enabled interfaces */
+    lines = 1 + babel_enable_if_config_write (vty);
+    /* list redistributed protocols */
+    for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+            if (i != zclient->redist_default &&
+                vrf_bitmap_check (zclient->redist[afi][i], VRF_DEFAULT)) {
+                vty_out (vty, " redistribute %s %s\n",
+                         (afi == AFI_IP) ? "ipv4" : "ipv6",
+                         zebra_route_string(i));
+                lines++;
+            }
+        }
+    }
+
+    lines += config_write_distribute (vty);
+
+    return lines;
 }
 
 
@@ -112,16 +145,15 @@ babel_create_routing_process (void)
     /* 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));
+        zlog_ferr(LIB_ERR_SOCKET, "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);
+    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
     /* 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);
+    thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update);
     return 0;
 
 fail:
@@ -135,9 +167,9 @@ static int
 babel_read_protocol (struct thread *thread)
 {
     int rc;
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp = NULL;
     struct sockaddr_in6 sin6;
-    struct listnode *linklist_node = NULL;
 
     assert(babel_routing_process != NULL);
     assert(protocol_socket >= 0);
@@ -147,13 +179,13 @@ babel_read_protocol (struct thread *thread)
                     (struct sockaddr*)&sin6, sizeof(sin6));
     if(rc < 0) {
         if(errno != EAGAIN && errno != EINTR) {
-            zlog_err("recv: %s", safe_strerror(errno));
+            zlog_ferr(LIB_ERR_SOCKET, "recv: %s", safe_strerror(errno));
         }
     } else {
-        FOR_ALL_INTERFACES(ifp, linklist_node) {
+        FOR_ALL_INTERFACES(vrf, ifp) {
             if(!if_up(ifp))
                 continue;
-            if(ifp->ifindex == sin6.sin6_scope_id) {
+            if(ifp->ifindex == (ifindex_t)sin6.sin6_scope_id) {
                 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
                              receive_buffer, rc);
                 break;
@@ -162,8 +194,7 @@ babel_read_protocol (struct thread *thread)
     }
 
     /* re-add thread */
-    babel_routing_process->t_read =
-    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
+    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
     return 0;
 }
 
@@ -186,8 +217,8 @@ babel_init_routing_process(struct thread *thread)
 static void
 babel_get_myid(void)
 {
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp = NULL;
-    struct listnode *linklist_node = NULL;
     int rc;
     int i;
 
@@ -196,12 +227,12 @@ babel_get_myid(void)
         return;
     }
 
-    FOR_ALL_INTERFACES(ifp, linklist_node) {
+    FOR_ALL_INTERFACES(vrf, ifp) {
         /* 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);
+            rc = if_eui64(ifindex, eui);
             if(rc < 0)
                 continue;
             memcpy(myid, eui, 8);
@@ -217,18 +248,20 @@ babel_get_myid(void)
         ifname = if_indextoname(i, buf);
         if(ifname == NULL)
             continue;
-        rc = if_eui64(ifname, i, eui);
+        rc = if_eui64(i, eui);
         if(rc < 0)
             continue;
         memcpy(myid, eui, 8);
         return;
     }
 
-    zlog_err("Warning: couldn't find router id -- using random value.");
+    zlog_ferr(BABEL_ERR_CONFIG,
+             "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));
+        zlog_ferr(BABEL_ERR_CONFIG, "read(random): %s (cannot assign an ID)",
+                 safe_strerror(errno));
         exit(1);
     }
     /* Clear group and global bits */
@@ -240,10 +273,10 @@ babel_get_myid(void)
 static void
 babel_initial_noise(void)
 {
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp = NULL;
-    struct listnode *linklist_node = NULL;
 
-    FOR_ALL_INTERFACES(ifp, linklist_node) {
+    FOR_ALL_INTERFACES(vrf, ifp) {
         if(!if_up(ifp))
             continue;
         /* Apply jitter before we send the first message. */
@@ -253,7 +286,7 @@ babel_initial_noise(void)
         send_wildcard_retraction(ifp);
     }
 
-    FOR_ALL_INTERFACES(ifp, linklist_node) {
+    FOR_ALL_INTERFACES(vrf, ifp) {
         if(!if_up(ifp))
             continue;
         usleep(roughly(10000));
@@ -291,8 +324,8 @@ static int
 babel_main_loop(struct thread *thread)
 {
     struct timeval tv;
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp = NULL;
-    struct listnode *linklist_node = NULL;
 
     while(1) {
         gettime(&babel_now);
@@ -303,8 +336,8 @@ babel_main_loop(struct thread *thread)
         /* 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);
+            debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
+                   (long long)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);
@@ -317,7 +350,8 @@ babel_main_loop(struct thread *thread)
         if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
             int msecs;
             msecs = check_neighbours();
-            msecs = MAX(msecs, 10);
+            /* Multiply by 3/2 to allow neighbours to expire. */
+            msecs = MAX(3 * msecs / 2, 10);
             schedule_neighbours_check(msecs, 1);
         }
 
@@ -332,7 +366,7 @@ babel_main_loop(struct thread *thread)
             source_expiry_time = babel_now.tv_sec + roughly(300);
         }
 
-        FOR_ALL_INTERFACES(ifp, linklist_node) {
+        FOR_ALL_INTERFACES(vrf, ifp) {
             babel_interface_nfo *babel_ifp = NULL;
             if(!if_up(ifp))
                 continue;
@@ -356,7 +390,7 @@ babel_main_loop(struct thread *thread)
                 flush_unicast(1);
         }
 
-        FOR_ALL_INTERFACES(ifp, linklist_node) {
+        FOR_ALL_INTERFACES(vrf, ifp) {
             babel_interface_nfo *babel_ifp = NULL;
             if(!if_up(ifp))
                 continue;
@@ -420,8 +454,8 @@ babel_fill_with_next_timeout(struct timeval *tv)
 #define printIfMin(a,b,c,d) \
   if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
 
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp = NULL;
-    struct listnode *linklist_node = NULL;
 
     *tv = check_neighbours_timeout;
     printIfMin(tv, 0, "check_neighbours_timeout", NULL);
@@ -431,7 +465,7 @@ babel_fill_with_next_timeout(struct timeval *tv)
     printIfMin(tv, 1, "source_expiry_time", NULL);
     timeval_min(tv, &resend_time);
     printIfMin(tv, 1, "resend_time", NULL);
-    FOR_ALL_INTERFACES(ifp, linklist_node) {
+    FOR_ALL_INTERFACES(vrf, ifp) {
         babel_interface_nfo *babel_ifp = NULL;
         if(!if_up(ifp))
             continue;
@@ -461,17 +495,15 @@ babel_set_timer(struct timeval *timeout)
     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);
+    thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
 }
 
-/* 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));
+    timeval_add_msec(&timeout, &babel_now, msecs);
     if(override)
         check_neighbours_timeout = timeout;
     else
@@ -487,7 +519,8 @@ resize_receive_buffer(int size)
     if(receive_buffer == NULL) {
         receive_buffer = malloc(size);
         if(receive_buffer == NULL) {
-            zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
+            zlog_ferr(BABEL_ERR_MEMORY, "malloc(receive_buffer): %s",
+                     safe_strerror(errno));
             return -1;
         }
         receive_buffer_size = size;
@@ -495,7 +528,8 @@ resize_receive_buffer(int size)
         unsigned char *new;
         new = realloc(receive_buffer, size);
         if(new == NULL) {
-            zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
+            zlog_ferr(BABEL_ERR_MEMORY, "realloc(receive_buffer): %s",
+                     safe_strerror(errno));
             return -1;
         }
         receive_buffer = new;
@@ -509,56 +543,31 @@ babel_distribute_update (struct distribute *dist)
 {
     struct interface *ifp;
     babel_interface_nfo *babel_ifp;
-    struct access_list *alist;
-    struct prefix_list *plist;
+    int type;
+    int family;
 
     if (! dist->ifname)
         return;
 
-    ifp = if_lookup_by_name (dist->ifname);
+    ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
     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;
+    for (type = 0; type < DISTRIBUTE_MAX; type++) {
+        family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
+                  AFI_IP : AFI_IP6;
+        if (dist->list[type])
+            babel_ifp->list[type] = access_list_lookup (family,
+                                                        dist->list[type]);
         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;
+            babel_ifp->list[type] = NULL;
+        if (dist->prefix[type])
+            babel_ifp->prefix[type] = prefix_list_lookup (family,
+                                                          dist->prefix[type]);
         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;
+            babel_ifp->prefix[type] = NULL;
     }
 }
 
@@ -576,10 +585,10 @@ babel_distribute_update_interface (struct interface *ifp)
 static void
 babel_distribute_update_all (struct prefix_list *notused)
 {
+    struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
     struct interface *ifp;
-    struct listnode *node;
 
-    for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
+    FOR_ALL_INTERFACES (vrf, ifp)
         babel_distribute_update_interface (ifp);
 }
 
@@ -591,12 +600,11 @@ babel_distribute_update_all_wrapper (struct access_list *notused)
 
 
 /* [Command] */
-DEFUN (router_babel,
-       router_babel_cmd,
-       "router babel",
-       "Enable a routing process\n"
-       "Make Babel instance command\n"
-       "No attributes\n")
+DEFUN_NOSH (router_babel,
+           router_babel_cmd,
+           "router babel",
+           "Enable a routing process\n"
+           "Make Babel instance command\n")
 {
     int ret;
 
@@ -621,30 +629,84 @@ DEFUN (no_router_babel,
        "no router babel",
        NO_STR
        "Disable a routing process\n"
-       "Remove Babel instance command\n"
-       "No attributes\n")
+       "Remove Babel instance command\n")
 {
     if(babel_routing_process)
         babel_clean_routing_process();
     return CMD_SUCCESS;
 }
 
+/* [Babel Command] */
+DEFUN (babel_diversity,
+       babel_diversity_cmd,
+       "babel diversity",
+       "Babel commands\n"
+       "Enable diversity-aware routing.\n")
+{
+    diversity_kind = DIVERSITY_CHANNEL;
+    return CMD_SUCCESS;
+}
+
+/* [Babel Command] */
+DEFUN (no_babel_diversity,
+       no_babel_diversity_cmd,
+       "no babel diversity",
+       NO_STR
+       "Babel commands\n"
+       "Disable diversity-aware routing.\n")
+{
+    diversity_kind = DIVERSITY_NONE;
+    return CMD_SUCCESS;
+}
+
+/* [Babel Command] */
+DEFUN (babel_diversity_factor,
+       babel_diversity_factor_cmd,
+       "babel diversity-factor (1-256)",
+       "Babel commands\n"
+       "Set the diversity factor.\n"
+       "Factor in units of 1/256.\n")
+{
+    int factor;
+
+    factor = strtoul(argv[2]->arg, NULL, 10);
+
+    diversity_factor = factor;
+    return CMD_SUCCESS;
+}
+
 /* [Babel Command] */
 DEFUN (babel_set_resend_delay,
        babel_set_resend_delay_cmd,
-       "babel resend-delay <20-655340>",
+       "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);
+    interval = strtoul(argv[2]->arg, NULL, 10);
 
     resend_delay = interval;
     return CMD_SUCCESS;
 }
 
+/* [Babel Command] */
+DEFUN (babel_set_smoothing_half_life,
+       babel_set_smoothing_half_life_cmd,
+       "babel smoothing-half-life (0-65534)",
+       "Babel commands\n"
+       "Smoothing half-life\n"
+       "Seconds (0 to disable)\n")
+{
+    int seconds;
+
+    seconds = strtoul(argv[2]->arg, NULL, 10);
+
+    change_smoothing_half_life(seconds);
+    return CMD_SUCCESS;
+}
+
 void
 babeld_quagga_init(void)
 {
@@ -655,7 +717,11 @@ babeld_quagga_init(void)
     install_element(CONFIG_NODE, &no_router_babel_cmd);
 
     install_default(BABEL_NODE);
+    install_element(BABEL_NODE, &babel_diversity_cmd);
+    install_element(BABEL_NODE, &no_babel_diversity_cmd);
+    install_element(BABEL_NODE, &babel_diversity_factor_cmd);
     install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
+    install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
 
     babel_if_init();
 
@@ -701,9 +767,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);
-}