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