File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / babeld / babeld.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (12 years, 5 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

    1: /*  
    2:  *  This file is free software: you may copy, redistribute and/or modify it  
    3:  *  under the terms of the GNU General Public License as published by the  
    4:  *  Free Software Foundation, either version 2 of the License, or (at your  
    5:  *  option) any later version.  
    6:  *  
    7:  *  This file is distributed in the hope that it will be useful, but  
    8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
    9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
   10:  *  General Public License for more details.  
   11:  *  
   12:  *  You should have received a copy of the GNU General Public License  
   13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
   14:  *  
   15:  * This file incorporates work covered by the following copyright and  
   16:  * permission notice:  
   17:  *  
   18: 
   19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
   20: 
   21: Permission is hereby granted, free of charge, to any person obtaining a copy
   22: of this software and associated documentation files (the "Software"), to deal
   23: in the Software without restriction, including without limitation the rights
   24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   25: copies of the Software, and to permit persons to whom the Software is
   26: furnished to do so, subject to the following conditions:
   27: 
   28: The above copyright notice and this permission notice shall be included in
   29: all copies or substantial portions of the Software.
   30: 
   31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   37: THE SOFTWARE.
   38: */
   39: 
   40: #include <zebra.h>
   41: #include "command.h"
   42: #include "prefix.h"
   43: #include "memory.h"
   44: #include "memtypes.h"
   45: #include "table.h"
   46: #include "distribute.h"
   47: #include "prefix.h"
   48: #include "filter.h"
   49: #include "plist.h"
   50: 
   51: #include "babel_main.h"
   52: #include "babeld.h"
   53: #include "util.h"
   54: #include "net.h"
   55: #include "kernel.h"
   56: #include "babel_interface.h"
   57: #include "neighbour.h"
   58: #include "route.h"
   59: #include "message.h"
   60: #include "resend.h"
   61: #include "babel_filter.h"
   62: #include "babel_zebra.h"
   63: 
   64: 
   65: static int babel_init_routing_process(struct thread *thread);
   66: static void babel_get_myid(void);
   67: static void babel_initial_noise(void);
   68: static int babel_read_protocol (struct thread *thread);
   69: static int babel_main_loop(struct thread *thread);
   70: static void babel_set_timer(struct timeval *timeout);
   71: static void babel_fill_with_next_timeout(struct timeval *tv);
   72: 
   73: 
   74: /* Informations relative to the babel running daemon. */
   75: static struct babel *babel_routing_process = NULL;
   76: static unsigned char *receive_buffer = NULL;
   77: static int receive_buffer_size = 0;
   78: 
   79: /* timeouts */
   80: struct timeval check_neighbours_timeout;
   81: static time_t expiry_time;
   82: static time_t source_expiry_time;
   83: 
   84: /* Babel node structure. */
   85: static struct cmd_node cmd_babel_node =
   86: {
   87:     .node   = BABEL_NODE,
   88:     .prompt = "%s(config-router)# ",
   89:     .vtysh  = 1,
   90: };
   91: 
   92: /* print current babel configuration on vty */
   93: static int
   94: babel_config_write (struct vty *vty)
   95: {
   96:     int lines = 0;
   97:     int i;
   98: 
   99:     /* list enabled debug modes */
  100:     lines += debug_babel_config_write (vty);
  101: 
  102:     if (!babel_routing_process)
  103:         return lines;
  104:     vty_out (vty, "router babel%s", VTY_NEWLINE);
  105:     if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
  106:     {
  107:         vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE);
  108:         lines++;
  109:     }
  110:     /* list enabled interfaces */
  111:     lines = 1 + babel_enable_if_config_write (vty);
  112:     /* list redistributed protocols */
  113:     for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
  114:         if (i != zclient->redist_default && zclient->redist[i])
  115:         {
  116:             vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
  117:             lines++;
  118:         }
  119: 
  120:     return lines;
  121: }
  122: 
  123: 
  124: static int
  125: babel_create_routing_process (void)
  126: {
  127:     assert (babel_routing_process == NULL);
  128: 
  129:     /* Allocaste Babel instance. */
  130:     babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
  131: 
  132:     /* Initialize timeouts */
  133:     gettime(&babel_now);
  134:     expiry_time = babel_now.tv_sec + roughly(30);
  135:     source_expiry_time = babel_now.tv_sec + roughly(300);
  136: 
  137:     /* Make socket for Babel protocol. */
  138:     protocol_socket = babel_socket(protocol_port);
  139:     if (protocol_socket < 0) {
  140:         zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
  141:         goto fail;
  142:     }
  143: 
  144:     /* Threads. */
  145:     babel_routing_process->t_read =
  146:     thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
  147:     /* wait a little: zebra will announce interfaces, addresses, routes... */
  148:     babel_routing_process->t_update =
  149:     thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
  150:     return 0;
  151: 
  152: fail:
  153:     XFREE(MTYPE_BABEL, babel_routing_process);
  154:     babel_routing_process = NULL;
  155:     return -1;
  156: }
  157: 
  158: /* thread reading entries form others babel daemons */
  159: static int
  160: babel_read_protocol (struct thread *thread)
  161: {
  162:     int rc;
  163:     struct interface *ifp = NULL;
  164:     struct sockaddr_in6 sin6;
  165:     struct listnode *linklist_node = NULL;
  166: 
  167:     assert(babel_routing_process != NULL);
  168:     assert(protocol_socket >= 0);
  169: 
  170:     rc = babel_recv(protocol_socket,
  171:                     receive_buffer, receive_buffer_size,
  172:                     (struct sockaddr*)&sin6, sizeof(sin6));
  173:     if(rc < 0) {
  174:         if(errno != EAGAIN && errno != EINTR) {
  175:             zlog_err("recv: %s", safe_strerror(errno));
  176:         }
  177:     } else {
  178:         FOR_ALL_INTERFACES(ifp, linklist_node) {
  179:             if(!if_up(ifp))
  180:                 continue;
  181:             if(ifp->ifindex == sin6.sin6_scope_id) {
  182:                 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
  183:                              receive_buffer, rc);
  184:                 break;
  185:             }
  186:         }
  187:     }
  188: 
  189:     /* re-add thread */
  190:     babel_routing_process->t_read =
  191:     thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
  192:     return 0;
  193: }
  194: 
  195: /* Zebra will give some information, especially about interfaces. This function
  196:  must be call with a litte timeout wich may give zebra the time to do his job,
  197:  making these inits have sense. */
  198: static int
  199: babel_init_routing_process(struct thread *thread)
  200: {
  201:     myseqno = (random() & 0xFFFF);
  202:     babel_get_myid();
  203:     babel_load_state_file();
  204:     debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
  205:     babel_initial_noise();
  206:     babel_main_loop(thread);/* this function self-add to the t_update thread */
  207:     return 0;
  208: }
  209: 
  210: /* fill "myid" with an unique id (only if myid != {0}). */
  211: static void
  212: babel_get_myid(void)
  213: {
  214:     struct interface *ifp = NULL;
  215:     struct listnode *linklist_node = NULL;
  216:     int rc;
  217:     int i;
  218: 
  219:     /* if we already have an id (from state file), we return. */
  220:     if (memcmp(myid, zeroes, 8) != 0) {
  221:         return;
  222:     }
  223: 
  224:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  225:         /* ifp->ifindex is not necessarily valid at this point */
  226:         int ifindex = if_nametoindex(ifp->name);
  227:         if(ifindex > 0) {
  228:             unsigned char eui[8];
  229:             rc = if_eui64(ifp->name, ifindex, eui);
  230:             if(rc < 0)
  231:                 continue;
  232:             memcpy(myid, eui, 8);
  233:             return;
  234:         }
  235:     }
  236: 
  237:     /* We failed to get a global EUI64 from the interfaces we were given.
  238:      Let's try to find an interface with a MAC address. */
  239:     for(i = 1; i < 256; i++) {
  240:         char buf[IF_NAMESIZE], *ifname;
  241:         unsigned char eui[8];
  242:         ifname = if_indextoname(i, buf);
  243:         if(ifname == NULL)
  244:             continue;
  245:         rc = if_eui64(ifname, i, eui);
  246:         if(rc < 0)
  247:             continue;
  248:         memcpy(myid, eui, 8);
  249:         return;
  250:     }
  251: 
  252:     zlog_err("Warning: couldn't find router id -- using random value.");
  253: 
  254:     rc = read_random_bytes(myid, 8);
  255:     if(rc < 0) {
  256:         zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
  257:         exit(1);
  258:     }
  259:     /* Clear group and global bits */
  260:     myid[0] &= ~3;
  261: }
  262: 
  263: /* Make some noise so that others notice us, and send retractions in
  264:  case we were restarted recently */
  265: static void
  266: babel_initial_noise(void)
  267: {
  268:     struct interface *ifp = NULL;
  269:     struct listnode *linklist_node = NULL;
  270: 
  271:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  272:         if(!if_up(ifp))
  273:             continue;
  274:         /* Apply jitter before we send the first message. */
  275:         usleep(roughly(10000));
  276:         gettime(&babel_now);
  277:         send_hello(ifp);
  278:         send_wildcard_retraction(ifp);
  279:     }
  280: 
  281:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  282:         if(!if_up(ifp))
  283:             continue;
  284:         usleep(roughly(10000));
  285:         gettime(&babel_now);
  286:         send_hello(ifp);
  287:         send_wildcard_retraction(ifp);
  288:         send_self_update(ifp);
  289:         send_request(ifp, NULL, 0);
  290:         flushupdates(ifp);
  291:         flushbuf(ifp);
  292:     }
  293: }
  294: 
  295: /* Delete all the added babel routes, make babeld only speak to zebra. */
  296: static void
  297: babel_clean_routing_process()
  298: {
  299:     flush_all_routes();
  300:     babel_interface_close_all();
  301: 
  302:     /* cancel threads */
  303:     if (babel_routing_process->t_read != NULL) {
  304:         thread_cancel(babel_routing_process->t_read);
  305:     }
  306:     if (babel_routing_process->t_update != NULL) {
  307:         thread_cancel(babel_routing_process->t_update);
  308:     }
  309: 
  310:     XFREE(MTYPE_BABEL, babel_routing_process);
  311:     babel_routing_process = NULL;
  312: }
  313: 
  314: /* Function used with timeout. */
  315: static int
  316: babel_main_loop(struct thread *thread)
  317: {
  318:     struct timeval tv;
  319:     struct interface *ifp = NULL;
  320:     struct listnode *linklist_node = NULL;
  321: 
  322:     while(1) {
  323:         gettime(&babel_now);
  324: 
  325:         /* timeouts --------------------------------------------------------- */
  326:         /* get the next timeout */
  327:         babel_fill_with_next_timeout(&tv);
  328:         /* if there is no timeout, we must wait. */
  329:         if(timeval_compare(&tv, &babel_now) > 0) {
  330:             timeval_minus(&tv, &tv, &babel_now);
  331:             debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
  332:                    tv.tv_sec * 1000 + tv.tv_usec / 1000);
  333:             /* it happens often to have less than 1 ms, it's bad. */
  334:             timeval_add_msec(&tv, &tv, 300);
  335:             babel_set_timer(&tv);
  336:             return 0;
  337:         }
  338: 
  339:         gettime(&babel_now);
  340: 
  341:         /* update database -------------------------------------------------- */
  342:         if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
  343:             int msecs;
  344:             msecs = check_neighbours();
  345:             msecs = MAX(msecs, 10);
  346:             schedule_neighbours_check(msecs, 1);
  347:         }
  348: 
  349:         if(babel_now.tv_sec >= expiry_time) {
  350:             expire_routes();
  351:             expire_resend();
  352:             expiry_time = babel_now.tv_sec + roughly(30);
  353:         }
  354: 
  355:         if(babel_now.tv_sec >= source_expiry_time) {
  356:             expire_sources();
  357:             source_expiry_time = babel_now.tv_sec + roughly(300);
  358:         }
  359: 
  360:         FOR_ALL_INTERFACES(ifp, linklist_node) {
  361:             babel_interface_nfo *babel_ifp = NULL;
  362:             if(!if_up(ifp))
  363:                 continue;
  364:             babel_ifp = babel_get_if_nfo(ifp);
  365:             if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
  366:                 send_hello(ifp);
  367:             if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
  368:                 send_update(ifp, 0, NULL, 0);
  369:             if(timeval_compare(&babel_now,
  370:                                &babel_ifp->update_flush_timeout) >= 0)
  371:                 flushupdates(ifp);
  372:         }
  373: 
  374:         if(resend_time.tv_sec != 0) {
  375:             if(timeval_compare(&babel_now, &resend_time) >= 0)
  376:                 do_resend();
  377:         }
  378: 
  379:         if(unicast_flush_timeout.tv_sec != 0) {
  380:             if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
  381:                 flush_unicast(1);
  382:         }
  383: 
  384:         FOR_ALL_INTERFACES(ifp, linklist_node) {
  385:             babel_interface_nfo *babel_ifp = NULL;
  386:             if(!if_up(ifp))
  387:                 continue;
  388:             babel_ifp = babel_get_if_nfo(ifp);
  389:             if(babel_ifp->flush_timeout.tv_sec != 0) {
  390:                 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
  391:                     flushbuf(ifp);
  392:             }
  393:         }
  394:     }
  395: 
  396:     assert(0); /* this line should never be reach */
  397: }
  398: 
  399: static void
  400: printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
  401: {
  402:     static struct timeval curr_tv;
  403:     static char buffer[200];
  404:     static const char *curr_tag = NULL;
  405: 
  406:     switch (cmd) {
  407:         case 0: /* reset timeval */
  408:             curr_tv = *tv;
  409:             if(ifname != NULL) {
  410:                 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
  411:                 curr_tag = buffer;
  412:             } else {
  413:                 curr_tag = tag;
  414:             }
  415:             break;
  416:         case 1: /* take the min */
  417:             if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
  418:                 break;
  419:             }
  420:             if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
  421:                                                tv->tv_usec < curr_tv.tv_usec)) {
  422:                 curr_tv = *tv;
  423:                 if(ifname != NULL) {
  424:                     snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
  425:                     curr_tag = buffer;
  426:                 } else {
  427:                     curr_tag = tag;
  428:                 }
  429:             }
  430:             break;
  431:         case 2: /* print message */
  432:             debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
  433:             break;
  434:         default:
  435:             break;
  436:     }
  437: }
  438: 
  439: static void
  440: babel_fill_with_next_timeout(struct timeval *tv)
  441: {
  442: #if (defined NO_DEBUG)
  443: #define printIfMin(a,b,c,d)
  444: #else
  445: #define printIfMin(a,b,c,d) \
  446:   if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
  447: 
  448:     struct interface *ifp = NULL;
  449:     struct listnode *linklist_node = NULL;
  450: 
  451:     *tv = check_neighbours_timeout;
  452:     printIfMin(tv, 0, "check_neighbours_timeout", NULL);
  453:     timeval_min_sec(tv, expiry_time);
  454:     printIfMin(tv, 1, "expiry_time", NULL);
  455:     timeval_min_sec(tv, source_expiry_time);
  456:     printIfMin(tv, 1, "source_expiry_time", NULL);
  457:     timeval_min(tv, &resend_time);
  458:     printIfMin(tv, 1, "resend_time", NULL);
  459:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  460:         babel_interface_nfo *babel_ifp = NULL;
  461:         if(!if_up(ifp))
  462:             continue;
  463:         babel_ifp = babel_get_if_nfo(ifp);
  464:         timeval_min(tv, &babel_ifp->flush_timeout);
  465:         printIfMin(tv, 1, "flush_timeout", ifp->name);
  466:         timeval_min(tv, &babel_ifp->hello_timeout);
  467:         printIfMin(tv, 1, "hello_timeout", ifp->name);
  468:         timeval_min(tv, &babel_ifp->update_timeout);
  469:         printIfMin(tv, 1, "update_timeout", ifp->name);
  470:         timeval_min(tv, &babel_ifp->update_flush_timeout);
  471:         printIfMin(tv, 1, "update_flush_timeout",ifp->name);
  472:     }
  473:     timeval_min(tv, &unicast_flush_timeout);
  474:     printIfMin(tv, 1, "unicast_flush_timeout", NULL);
  475:     printIfMin(tv, 2, NULL, NULL);
  476: #undef printIfMin
  477: #endif
  478: }
  479: 
  480: /* set the t_update thread of the babel routing process to be launch in
  481:  'timeout' (approximate at the milisecond) */
  482: static void
  483: babel_set_timer(struct timeval *timeout)
  484: {
  485:     long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
  486:     if (babel_routing_process->t_update != NULL) {
  487:         thread_cancel(babel_routing_process->t_update);
  488:     }
  489:     babel_routing_process->t_update =
  490:     thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
  491: }
  492: 
  493: /* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
  494: void
  495: schedule_neighbours_check(int msecs, int override)
  496: {
  497:     struct timeval timeout;
  498: 
  499:     timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
  500:     if(override)
  501:         check_neighbours_timeout = timeout;
  502:     else
  503:         timeval_min(&check_neighbours_timeout, &timeout);
  504: }
  505: 
  506: int
  507: resize_receive_buffer(int size)
  508: {
  509:     if(size <= receive_buffer_size)
  510:         return 0;
  511: 
  512:     if(receive_buffer == NULL) {
  513:         receive_buffer = malloc(size);
  514:         if(receive_buffer == NULL) {
  515:             zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
  516:             return -1;
  517:         }
  518:         receive_buffer_size = size;
  519:     } else {
  520:         unsigned char *new;
  521:         new = realloc(receive_buffer, size);
  522:         if(new == NULL) {
  523:             zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
  524:             return -1;
  525:         }
  526:         receive_buffer = new;
  527:         receive_buffer_size = size;
  528:     }
  529:     return 1;
  530: }
  531: 
  532: static void
  533: babel_distribute_update (struct distribute *dist)
  534: {
  535:     struct interface *ifp;
  536:     babel_interface_nfo *babel_ifp;
  537:     struct access_list *alist;
  538:     struct prefix_list *plist;
  539: 
  540:     if (! dist->ifname)
  541:         return;
  542: 
  543:     ifp = if_lookup_by_name (dist->ifname);
  544:     if (ifp == NULL)
  545:         return;
  546: 
  547:     babel_ifp = babel_get_if_nfo(ifp);
  548: 
  549:     if (dist->list[DISTRIBUTE_IN]) {
  550:         alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
  551:         if (alist)
  552:             babel_ifp->list[BABEL_FILTER_IN] = alist;
  553:         else
  554:             babel_ifp->list[BABEL_FILTER_IN] = NULL;
  555:     } else {
  556:         babel_ifp->list[BABEL_FILTER_IN] = NULL;
  557:     }
  558: 
  559:     if (dist->list[DISTRIBUTE_OUT]) {
  560:         alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
  561:         if (alist)
  562:             babel_ifp->list[BABEL_FILTER_OUT] = alist;
  563:         else
  564:             babel_ifp->list[BABEL_FILTER_OUT] = NULL;
  565:     } else {
  566:         babel_ifp->list[BABEL_FILTER_OUT] = NULL;
  567:     }
  568: 
  569:     if (dist->prefix[DISTRIBUTE_IN]) {
  570:         plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
  571:         if (plist)
  572:             babel_ifp->prefix[BABEL_FILTER_IN] = plist;
  573:         else
  574:             babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
  575:     } else {
  576:         babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
  577:     }
  578: 
  579:     if (dist->prefix[DISTRIBUTE_OUT]) {
  580:         plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
  581:         if (plist)
  582:             babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
  583:         else
  584:             babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
  585:     } else {
  586:         babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
  587:     }
  588: }
  589: 
  590: static void
  591: babel_distribute_update_interface (struct interface *ifp)
  592: {
  593:     struct distribute *dist;
  594: 
  595:     dist = distribute_lookup (ifp->name);
  596:     if (dist)
  597:         babel_distribute_update (dist);
  598: }
  599: 
  600: /* Update all interface's distribute list. */
  601: static void
  602: babel_distribute_update_all (struct prefix_list *notused)
  603: {
  604:     struct interface *ifp;
  605:     struct listnode *node;
  606: 
  607:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  608:         babel_distribute_update_interface (ifp);
  609: }
  610: 
  611: static void
  612: babel_distribute_update_all_wrapper (struct access_list *notused)
  613: {
  614:     babel_distribute_update_all(NULL);
  615: }
  616: 
  617: 
  618: /* [Command] */
  619: DEFUN (router_babel,
  620:        router_babel_cmd,
  621:        "router babel",
  622:        "Enable a routing process\n"
  623:        "Make Babel instance command\n"
  624:        "No attributes\n")
  625: {
  626:     int ret;
  627: 
  628:     vty->node = BABEL_NODE;
  629: 
  630:     if (!babel_routing_process) {
  631:         ret = babel_create_routing_process ();
  632: 
  633:         /* Notice to user we couldn't create Babel. */
  634:         if (ret < 0) {
  635:             zlog_warn ("can't create Babel");
  636:             return CMD_WARNING;
  637:         }
  638:     }
  639: 
  640:     return CMD_SUCCESS;
  641: }
  642: 
  643: /* [Command] */
  644: DEFUN (no_router_babel,
  645:        no_router_babel_cmd,
  646:        "no router babel",
  647:        NO_STR
  648:        "Disable a routing process\n"
  649:        "Remove Babel instance command\n"
  650:        "No attributes\n")
  651: {
  652:     if(babel_routing_process)
  653:         babel_clean_routing_process();
  654:     return CMD_SUCCESS;
  655: }
  656: 
  657: /* [Babel Command] */
  658: DEFUN (babel_set_resend_delay,
  659:        babel_set_resend_delay_cmd,
  660:        "babel resend-delay <20-655340>",
  661:        "Babel commands\n"
  662:        "Time before resending a message\n"
  663:        "Milliseconds\n")
  664: {
  665:     int interval;
  666: 
  667:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
  668: 
  669:     resend_delay = interval;
  670:     return CMD_SUCCESS;
  671: }
  672: 
  673: void
  674: babeld_quagga_init(void)
  675: {
  676: 
  677:     install_node(&cmd_babel_node, &babel_config_write);
  678: 
  679:     install_element(CONFIG_NODE, &router_babel_cmd);
  680:     install_element(CONFIG_NODE, &no_router_babel_cmd);
  681: 
  682:     install_default(BABEL_NODE);
  683:     install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
  684: 
  685:     babel_if_init();
  686: 
  687:     /* Access list install. */
  688:     access_list_init ();
  689:     access_list_add_hook (babel_distribute_update_all_wrapper);
  690:     access_list_delete_hook (babel_distribute_update_all_wrapper);
  691: 
  692:     /* Prefix list initialize.*/
  693:     prefix_list_init ();
  694:     prefix_list_add_hook (babel_distribute_update_all);
  695:     prefix_list_delete_hook (babel_distribute_update_all);
  696: 
  697:     /* Distribute list install. */
  698:     distribute_list_init (BABEL_NODE);
  699:     distribute_list_add_hook (babel_distribute_update);
  700:     distribute_list_delete_hook (babel_distribute_update);
  701: }
  702: 
  703: /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
  704: 
  705: int
  706: input_filter(const unsigned char *id,
  707:              const unsigned char *prefix, unsigned short plen,
  708:              const unsigned char *neigh, unsigned int ifindex)
  709: {
  710:     return babel_filter(0, prefix, plen, ifindex);
  711: }
  712: 
  713: int
  714: output_filter(const unsigned char *id, const unsigned char *prefix,
  715:               unsigned short plen, unsigned int ifindex)
  716: {
  717:     return babel_filter(1, prefix, plen, ifindex);
  718: }
  719: 
  720: /* There's no redistribute filter in Quagga -- the zebra daemon does its
  721:    own filtering. */
  722: int
  723: redistribute_filter(const unsigned char *prefix, unsigned short plen,
  724:                     unsigned int ifindex, int proto)
  725: {
  726:     return 0;
  727: }
  728: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>