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