]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babeld.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[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 */
412}
413
414static void
415printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
416{
417 static struct timeval curr_tv;
418 static char buffer[200];
419 static const char *curr_tag = NULL;
420
421 switch (cmd) {
422 case 0: /* reset timeval */
423 curr_tv = *tv;
424 if(ifname != NULL) {
425 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
426 curr_tag = buffer;
427 } else {
428 curr_tag = tag;
429 }
430 break;
431 case 1: /* take the min */
432 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
433 break;
434 }
435 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
436 tv->tv_usec < curr_tv.tv_usec)) {
437 curr_tv = *tv;
438 if(ifname != NULL) {
439 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
440 curr_tag = buffer;
441 } else {
442 curr_tag = tag;
443 }
444 }
445 break;
446 case 2: /* print message */
447 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
448 break;
449 default:
450 break;
451 }
452}
453
454static void
455babel_fill_with_next_timeout(struct timeval *tv)
456{
457#if (defined NO_DEBUG)
458#define printIfMin(a,b,c,d)
459#else
460#define printIfMin(a,b,c,d) \
461 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
462
f4e14fdb 463 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 464 struct interface *ifp = NULL;
ca10883e
DS
465
466 *tv = check_neighbours_timeout;
467 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
468 timeval_min_sec(tv, expiry_time);
469 printIfMin(tv, 1, "expiry_time", NULL);
470 timeval_min_sec(tv, source_expiry_time);
471 printIfMin(tv, 1, "source_expiry_time", NULL);
472 timeval_min(tv, &resend_time);
473 printIfMin(tv, 1, "resend_time", NULL);
f4e14fdb 474 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
475 babel_interface_nfo *babel_ifp = NULL;
476 if(!if_up(ifp))
477 continue;
478 babel_ifp = babel_get_if_nfo(ifp);
479 timeval_min(tv, &babel_ifp->flush_timeout);
480 printIfMin(tv, 1, "flush_timeout", ifp->name);
481 timeval_min(tv, &babel_ifp->hello_timeout);
482 printIfMin(tv, 1, "hello_timeout", ifp->name);
483 timeval_min(tv, &babel_ifp->update_timeout);
484 printIfMin(tv, 1, "update_timeout", ifp->name);
485 timeval_min(tv, &babel_ifp->update_flush_timeout);
486 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
487 }
488 timeval_min(tv, &unicast_flush_timeout);
489 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
490 printIfMin(tv, 2, NULL, NULL);
491#undef printIfMin
492#endif
493}
494
495/* set the t_update thread of the babel routing process to be launch in
496 'timeout' (approximate at the milisecond) */
497static void
498babel_set_timer(struct timeval *timeout)
499{
500 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
501 if (babel_routing_process->t_update != NULL) {
502 thread_cancel(babel_routing_process->t_update);
503 }
504 thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
505}
506
507void
508schedule_neighbours_check(int msecs, int override)
509{
510 struct timeval timeout;
511
512 timeval_add_msec(&timeout, &babel_now, msecs);
513 if(override)
514 check_neighbours_timeout = timeout;
515 else
516 timeval_min(&check_neighbours_timeout, &timeout);
517}
518
519int
520resize_receive_buffer(int size)
521{
522 if(size <= receive_buffer_size)
523 return 0;
524
525 if(receive_buffer == NULL) {
526 receive_buffer = malloc(size);
527 if(receive_buffer == NULL) {
5b003f31 528 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
f135ba52 529 safe_strerror(errno));
ca10883e
DS
530 return -1;
531 }
532 receive_buffer_size = size;
533 } else {
534 unsigned char *new;
535 new = realloc(receive_buffer, size);
536 if(new == NULL) {
5b003f31 537 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
f135ba52 538 safe_strerror(errno));
ca10883e
DS
539 return -1;
540 }
541 receive_buffer = new;
542 receive_buffer_size = size;
543 }
544 return 1;
545}
546
547static void
03a38493 548babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
ca10883e
DS
549{
550 struct interface *ifp;
551 babel_interface_nfo *babel_ifp;
552 int type;
553 int family;
554
555 if (! dist->ifname)
556 return;
557
a36898e7 558 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
ca10883e
DS
559 if (ifp == NULL)
560 return;
561
562 babel_ifp = babel_get_if_nfo(ifp);
563
564 for (type = 0; type < DISTRIBUTE_MAX; type++) {
565 family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
566 AFI_IP : AFI_IP6;
567 if (dist->list[type])
568 babel_ifp->list[type] = access_list_lookup (family,
569 dist->list[type]);
570 else
571 babel_ifp->list[type] = NULL;
572 if (dist->prefix[type])
573 babel_ifp->prefix[type] = prefix_list_lookup (family,
574 dist->prefix[type]);
575 else
576 babel_ifp->prefix[type] = NULL;
577 }
578}
579
580static void
581babel_distribute_update_interface (struct interface *ifp)
582{
03a38493 583 struct distribute *dist = NULL;
ca10883e 584
03a38493
PG
585 if (babel_routing_process)
586 dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
ca10883e 587 if (dist)
03a38493 588 babel_distribute_update (babel_routing_process->distribute_ctx, dist);
ca10883e
DS
589}
590
591/* Update all interface's distribute list. */
592static void
593babel_distribute_update_all (struct prefix_list *notused)
594{
f4e14fdb 595 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 596 struct interface *ifp;
ca10883e 597
451fda4f 598 FOR_ALL_INTERFACES (vrf, ifp)
ca10883e
DS
599 babel_distribute_update_interface (ifp);
600}
601
602static void
603babel_distribute_update_all_wrapper (struct access_list *notused)
604{
605 babel_distribute_update_all(NULL);
606}
607
608
609/* [Command] */
f84d11d1
DS
610DEFUN_NOSH (router_babel,
611 router_babel_cmd,
612 "router babel",
613 "Enable a routing process\n"
614 "Make Babel instance command\n")
ca10883e
DS
615{
616 int ret;
617
618 vty->node = BABEL_NODE;
619
620 if (!babel_routing_process) {
621 ret = babel_create_routing_process ();
622
623 /* Notice to user we couldn't create Babel. */
624 if (ret < 0) {
625 zlog_warn ("can't create Babel");
626 return CMD_WARNING;
627 }
628 }
629
630 return CMD_SUCCESS;
631}
632
633/* [Command] */
634DEFUN (no_router_babel,
635 no_router_babel_cmd,
636 "no router babel",
637 NO_STR
638 "Disable a routing process\n"
7111c1a0 639 "Remove Babel instance command\n")
ca10883e
DS
640{
641 if(babel_routing_process)
642 babel_clean_routing_process();
643 return CMD_SUCCESS;
644}
645
646/* [Babel Command] */
647DEFUN (babel_diversity,
648 babel_diversity_cmd,
649 "babel diversity",
650 "Babel commands\n"
651 "Enable diversity-aware routing.\n")
652{
653 diversity_kind = DIVERSITY_CHANNEL;
654 return CMD_SUCCESS;
655}
656
657/* [Babel Command] */
658DEFUN (no_babel_diversity,
659 no_babel_diversity_cmd,
660 "no babel diversity",
661 NO_STR
662 "Babel commands\n"
663 "Disable diversity-aware routing.\n")
664{
665 diversity_kind = DIVERSITY_NONE;
666 return CMD_SUCCESS;
667}
668
669/* [Babel Command] */
670DEFUN (babel_diversity_factor,
671 babel_diversity_factor_cmd,
672 "babel diversity-factor (1-256)",
673 "Babel commands\n"
674 "Set the diversity factor.\n"
675 "Factor in units of 1/256.\n")
676{
677 int factor;
678
facfee22 679 factor = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
680
681 diversity_factor = factor;
682 return CMD_SUCCESS;
683}
684
685/* [Babel Command] */
686DEFUN (babel_set_resend_delay,
687 babel_set_resend_delay_cmd,
688 "babel resend-delay (20-655340)",
689 "Babel commands\n"
690 "Time before resending a message\n"
691 "Milliseconds\n")
692{
693 int interval;
694
facfee22 695 interval = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
696
697 resend_delay = interval;
698 return CMD_SUCCESS;
699}
700
701/* [Babel Command] */
702DEFUN (babel_set_smoothing_half_life,
703 babel_set_smoothing_half_life_cmd,
704 "babel smoothing-half-life (0-65534)",
705 "Babel commands\n"
706 "Smoothing half-life\n"
707 "Seconds (0 to disable)\n")
708{
709 int seconds;
710
facfee22 711 seconds = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
712
713 change_smoothing_half_life(seconds);
714 return CMD_SUCCESS;
715}
716
717void
718babeld_quagga_init(void)
719{
720
721 install_node(&cmd_babel_node, &babel_config_write);
722
723 install_element(CONFIG_NODE, &router_babel_cmd);
724 install_element(CONFIG_NODE, &no_router_babel_cmd);
725
726 install_default(BABEL_NODE);
727 install_element(BABEL_NODE, &babel_diversity_cmd);
728 install_element(BABEL_NODE, &no_babel_diversity_cmd);
729 install_element(BABEL_NODE, &babel_diversity_factor_cmd);
730 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
731 install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
732
733 babel_if_init();
734
735 /* Access list install. */
736 access_list_init ();
737 access_list_add_hook (babel_distribute_update_all_wrapper);
738 access_list_delete_hook (babel_distribute_update_all_wrapper);
739
740 /* Prefix list initialize.*/
741 prefix_list_init ();
742 prefix_list_add_hook (babel_distribute_update_all);
743 prefix_list_delete_hook (babel_distribute_update_all);
744
745 /* Distribute list install. */
03a38493 746 distribute_list_init(BABEL_NODE);
ca10883e
DS
747}
748
749/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
750
751int
752input_filter(const unsigned char *id,
753 const unsigned char *prefix, unsigned short plen,
754 const unsigned char *neigh, unsigned int ifindex)
755{
756 return babel_filter(0, prefix, plen, ifindex);
757}
758
759int
760output_filter(const unsigned char *id, const unsigned char *prefix,
761 unsigned short plen, unsigned int ifindex)
762{
763 return babel_filter(1, prefix, plen, ifindex);
764}
765
766/* There's no redistribute filter in Quagga -- the zebra daemon does its
767 own filtering. */
768int
769redistribute_filter(const unsigned char *prefix, unsigned short plen,
770 unsigned int ifindex, int proto)
771{
772 return 0;
773}
774
03a38493
PG
775struct babel *babel_lookup(void)
776{
777 return babel_routing_process;
778}