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