Annotation of embedaddon/quagga/babeld/babeld.c, revision 1.1
1.1 ! misho 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>