]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babeld.c
eigrpd: eigrp usage of uint32_t to struct in_addr for router_id data
[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"
f135ba52 32#include "lib_errors.h"
ca10883e
DS
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"
f135ba52 47#include "babel_errors.h"
ca10883e
DS
48
49static int babel_init_routing_process(struct thread *thread);
50static void babel_get_myid(void);
51static void babel_initial_noise(void);
52static int babel_read_protocol (struct thread *thread);
53static int babel_main_loop(struct thread *thread);
54static void babel_set_timer(struct timeval *timeout);
55static void babel_fill_with_next_timeout(struct timeval *tv);
56
57
58/* Informations relative to the babel running daemon. */
59static struct babel *babel_routing_process = NULL;
60static unsigned char *receive_buffer = NULL;
61static int receive_buffer_size = 0;
62
63/* timeouts */
64struct timeval check_neighbours_timeout;
65static time_t expiry_time;
66static time_t source_expiry_time;
67
68/* Babel node structure. */
69static 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 */
77static int
78babel_config_write (struct vty *vty)
79{
80 int lines = 0;
dd8765ca 81 int afi;
ca10883e
DS
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;
5c7571d4 89 vty_out (vty, "router babel\n");
ca10883e
DS
90 if (diversity_kind != DIVERSITY_NONE)
91 {
5c7571d4 92 vty_out (vty, " babel diversity\n");
ca10883e
DS
93 lines++;
94 }
95 if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
96 {
5c7571d4 97 vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
ca10883e
DS
98 lines++;
99 }
100 if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
101 {
5c7571d4 102 vty_out (vty, " babel resend-delay %u\n", resend_delay);
ca10883e
DS
103 lines++;
104 }
105 if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
106 {
5c7571d4 107 vty_out (vty, " babel smoothing-half-life %u\n",
96ade3ed 108 smoothing_half_life);
ca10883e
DS
109 lines++;
110 }
111 /* list enabled interfaces */
112 lines = 1 + babel_enable_if_config_write (vty);
113 /* list redistributed protocols */
dd8765ca
RW
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 }
ca10883e 123 }
dd8765ca 124 }
ca10883e
DS
125
126 lines += config_write_distribute (vty);
127
128 return lines;
129}
130
131
132static int
133babel_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) {
450971aa 148 flog_err_sys(EC_LIB_SOCKET, "Couldn't create link local socket: %s",
f135ba52 149 safe_strerror(errno));
ca10883e
DS
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
159fail:
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 */
166static int
167babel_read_protocol (struct thread *thread)
168{
169 int rc;
f4e14fdb 170 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e
DS
171 struct interface *ifp = NULL;
172 struct sockaddr_in6 sin6;
ca10883e
DS
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) {
450971aa 182 flog_err_sys(EC_LIB_SOCKET, "recv: %s", safe_strerror(errno));
ca10883e
DS
183 }
184 } else {
f4e14fdb 185 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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. */
204static int
205babel_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}). */
217static void
218babel_get_myid(void)
219{
f4e14fdb 220 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 221 struct interface *ifp = NULL;
ca10883e
DS
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
f4e14fdb 230 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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];
edb1d4a0 235 rc = if_eui64(ifindex, eui);
ca10883e
DS
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;
edb1d4a0 251 rc = if_eui64(i, eui);
ca10883e
DS
252 if(rc < 0)
253 continue;
254 memcpy(myid, eui, 8);
255 return;
256 }
257
5b003f31 258 flog_err(EC_BABEL_CONFIG,
e33b116c 259 "Warning: couldn't find router id -- using random value.");
ca10883e
DS
260
261 rc = read_random_bytes(myid, 8);
262 if(rc < 0) {
5b003f31 263 flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
e33b116c 264 safe_strerror(errno));
ca10883e
DS
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 */
273static void
274babel_initial_noise(void)
275{
f4e14fdb 276 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 277 struct interface *ifp = NULL;
ca10883e 278
f4e14fdb 279 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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
f4e14fdb 289 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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. */
304static void
305babel_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. */
323static int
324babel_main_loop(struct thread *thread)
325{
326 struct timeval tv;
f4e14fdb 327 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 328 struct interface *ifp = NULL;
ca10883e
DS
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);
a97986ff
DL
339 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
340 (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
ca10883e
DS
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
f4e14fdb 369 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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
f4e14fdb 393 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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
408static void
409printIfMin(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
448static void
449babel_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
f4e14fdb 457 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 458 struct interface *ifp = NULL;
ca10883e
DS
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);
f4e14fdb 468 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
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) */
491static void
492babel_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
501void
502schedule_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
513int
514resize_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) {
5b003f31 522 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
f135ba52 523 safe_strerror(errno));
ca10883e
DS
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) {
5b003f31 531 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
f135ba52 532 safe_strerror(errno));
ca10883e
DS
533 return -1;
534 }
535 receive_buffer = new;
536 receive_buffer_size = size;
537 }
538 return 1;
539}
540
541static void
542babel_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
574static void
575babel_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. */
585static void
586babel_distribute_update_all (struct prefix_list *notused)
587{
f4e14fdb 588 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 589 struct interface *ifp;
ca10883e 590
451fda4f 591 FOR_ALL_INTERFACES (vrf, ifp)
ca10883e
DS
592 babel_distribute_update_interface (ifp);
593}
594
595static void
596babel_distribute_update_all_wrapper (struct access_list *notused)
597{
598 babel_distribute_update_all(NULL);
599}
600
601
602/* [Command] */
f84d11d1
DS
603DEFUN_NOSH (router_babel,
604 router_babel_cmd,
605 "router babel",
606 "Enable a routing process\n"
607 "Make Babel instance command\n")
ca10883e
DS
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] */
627DEFUN (no_router_babel,
628 no_router_babel_cmd,
629 "no router babel",
630 NO_STR
631 "Disable a routing process\n"
7111c1a0 632 "Remove Babel instance command\n")
ca10883e
DS
633{
634 if(babel_routing_process)
635 babel_clean_routing_process();
636 return CMD_SUCCESS;
637}
638
639/* [Babel Command] */
640DEFUN (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] */
651DEFUN (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] */
663DEFUN (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
facfee22 672 factor = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
673
674 diversity_factor = factor;
675 return CMD_SUCCESS;
676}
677
678/* [Babel Command] */
679DEFUN (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
facfee22 688 interval = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
689
690 resend_delay = interval;
691 return CMD_SUCCESS;
692}
693
694/* [Babel Command] */
695DEFUN (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
facfee22 704 seconds = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
705
706 change_smoothing_half_life(seconds);
707 return CMD_SUCCESS;
708}
709
710void
711babeld_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
746int
747input_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
754int
755output_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. */
763int
764redistribute_filter(const unsigned char *prefix, unsigned short plen,
765 unsigned int ifindex, int proto)
766{
767 return 0;
768}
769