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