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