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