]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babeld.c
Merge pull request #6282 from opensourcerouting/fix-isisd-sh-run
[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
8b7454e9
DL
49DEFINE_MGROUP(BABELD, "babeld")
50DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure")
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
5b003f31 268 flog_err(EC_BABEL_CONFIG,
e33b116c 269 "Warning: couldn't find router id -- using random value.");
ca10883e
DS
270
271 rc = read_random_bytes(myid, 8);
272 if(rc < 0) {
5b003f31 273 flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
e33b116c 274 safe_strerror(errno));
ca10883e
DS
275 exit(1);
276 }
277 /* Clear group and global bits */
278 myid[0] &= ~3;
279}
280
281/* Make some noise so that others notice us, and send retractions in
282 case we were restarted recently */
283static void
284babel_initial_noise(void)
285{
f4e14fdb 286 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 287 struct interface *ifp = NULL;
ca10883e 288
f4e14fdb 289 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
290 if(!if_up(ifp))
291 continue;
292 /* Apply jitter before we send the first message. */
293 usleep(roughly(10000));
294 gettime(&babel_now);
295 send_hello(ifp);
296 send_wildcard_retraction(ifp);
297 }
298
f4e14fdb 299 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
300 if(!if_up(ifp))
301 continue;
302 usleep(roughly(10000));
303 gettime(&babel_now);
304 send_hello(ifp);
305 send_wildcard_retraction(ifp);
306 send_self_update(ifp);
307 send_request(ifp, NULL, 0);
308 flushupdates(ifp);
309 flushbuf(ifp);
310 }
311}
312
313/* Delete all the added babel routes, make babeld only speak to zebra. */
314static void
4d762f26 315babel_clean_routing_process(void)
ca10883e
DS
316{
317 flush_all_routes();
318 babel_interface_close_all();
319
320 /* cancel threads */
321 if (babel_routing_process->t_read != NULL) {
322 thread_cancel(babel_routing_process->t_read);
323 }
324 if (babel_routing_process->t_update != NULL) {
325 thread_cancel(babel_routing_process->t_update);
326 }
327
03a38493 328 distribute_list_delete(&babel_routing_process->distribute_ctx);
ca10883e 329 XFREE(MTYPE_BABEL, babel_routing_process);
ca10883e
DS
330}
331
332/* Function used with timeout. */
333static int
334babel_main_loop(struct thread *thread)
335{
336 struct timeval tv;
f4e14fdb 337 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 338 struct interface *ifp = NULL;
ca10883e
DS
339
340 while(1) {
341 gettime(&babel_now);
342
343 /* timeouts --------------------------------------------------------- */
344 /* get the next timeout */
345 babel_fill_with_next_timeout(&tv);
346 /* if there is no timeout, we must wait. */
347 if(timeval_compare(&tv, &babel_now) > 0) {
348 timeval_minus(&tv, &tv, &babel_now);
a97986ff
DL
349 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
350 (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
ca10883e
DS
351 /* it happens often to have less than 1 ms, it's bad. */
352 timeval_add_msec(&tv, &tv, 300);
353 babel_set_timer(&tv);
354 return 0;
355 }
356
357 gettime(&babel_now);
358
359 /* update database -------------------------------------------------- */
360 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
361 int msecs;
362 msecs = check_neighbours();
363 /* Multiply by 3/2 to allow neighbours to expire. */
364 msecs = MAX(3 * msecs / 2, 10);
365 schedule_neighbours_check(msecs, 1);
366 }
367
368 if(babel_now.tv_sec >= expiry_time) {
369 expire_routes();
370 expire_resend();
371 expiry_time = babel_now.tv_sec + roughly(30);
372 }
373
374 if(babel_now.tv_sec >= source_expiry_time) {
375 expire_sources();
376 source_expiry_time = babel_now.tv_sec + roughly(300);
377 }
378
f4e14fdb 379 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
380 babel_interface_nfo *babel_ifp = NULL;
381 if(!if_up(ifp))
382 continue;
383 babel_ifp = babel_get_if_nfo(ifp);
384 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
385 send_hello(ifp);
386 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
387 send_update(ifp, 0, NULL, 0);
388 if(timeval_compare(&babel_now,
389 &babel_ifp->update_flush_timeout) >= 0)
390 flushupdates(ifp);
391 }
392
393 if(resend_time.tv_sec != 0) {
394 if(timeval_compare(&babel_now, &resend_time) >= 0)
395 do_resend();
396 }
397
398 if(unicast_flush_timeout.tv_sec != 0) {
399 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
400 flush_unicast(1);
401 }
402
f4e14fdb 403 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
404 babel_interface_nfo *babel_ifp = NULL;
405 if(!if_up(ifp))
406 continue;
407 babel_ifp = babel_get_if_nfo(ifp);
408 if(babel_ifp->flush_timeout.tv_sec != 0) {
409 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
410 flushbuf(ifp);
411 }
412 }
413 }
414
415 assert(0); /* this line should never be reach */
be04d148 416 return 0;
ca10883e
DS
417}
418
419static void
420printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
421{
422 static struct timeval curr_tv;
423 static char buffer[200];
424 static const char *curr_tag = NULL;
425
426 switch (cmd) {
427 case 0: /* reset timeval */
428 curr_tv = *tv;
429 if(ifname != NULL) {
430 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
431 curr_tag = buffer;
432 } else {
433 curr_tag = tag;
434 }
435 break;
436 case 1: /* take the min */
437 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
438 break;
439 }
440 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
441 tv->tv_usec < curr_tv.tv_usec)) {
442 curr_tv = *tv;
443 if(ifname != NULL) {
444 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
445 curr_tag = buffer;
446 } else {
447 curr_tag = tag;
448 }
449 }
450 break;
451 case 2: /* print message */
452 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
453 break;
454 default:
455 break;
456 }
457}
458
459static void
460babel_fill_with_next_timeout(struct timeval *tv)
461{
462#if (defined NO_DEBUG)
463#define printIfMin(a,b,c,d)
464#else
465#define printIfMin(a,b,c,d) \
466 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
467
f4e14fdb 468 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 469 struct interface *ifp = NULL;
ca10883e
DS
470
471 *tv = check_neighbours_timeout;
472 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
473 timeval_min_sec(tv, expiry_time);
474 printIfMin(tv, 1, "expiry_time", NULL);
475 timeval_min_sec(tv, source_expiry_time);
476 printIfMin(tv, 1, "source_expiry_time", NULL);
477 timeval_min(tv, &resend_time);
478 printIfMin(tv, 1, "resend_time", NULL);
f4e14fdb 479 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
480 babel_interface_nfo *babel_ifp = NULL;
481 if(!if_up(ifp))
482 continue;
483 babel_ifp = babel_get_if_nfo(ifp);
484 timeval_min(tv, &babel_ifp->flush_timeout);
485 printIfMin(tv, 1, "flush_timeout", ifp->name);
486 timeval_min(tv, &babel_ifp->hello_timeout);
487 printIfMin(tv, 1, "hello_timeout", ifp->name);
488 timeval_min(tv, &babel_ifp->update_timeout);
489 printIfMin(tv, 1, "update_timeout", ifp->name);
490 timeval_min(tv, &babel_ifp->update_flush_timeout);
491 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
492 }
493 timeval_min(tv, &unicast_flush_timeout);
494 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
495 printIfMin(tv, 2, NULL, NULL);
496#undef printIfMin
497#endif
498}
499
500/* set the t_update thread of the babel routing process to be launch in
501 'timeout' (approximate at the milisecond) */
502static void
503babel_set_timer(struct timeval *timeout)
504{
505 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
506 if (babel_routing_process->t_update != NULL) {
507 thread_cancel(babel_routing_process->t_update);
508 }
509 thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
510}
511
512void
513schedule_neighbours_check(int msecs, int override)
514{
515 struct timeval timeout;
516
517 timeval_add_msec(&timeout, &babel_now, msecs);
518 if(override)
519 check_neighbours_timeout = timeout;
520 else
521 timeval_min(&check_neighbours_timeout, &timeout);
522}
523
524int
525resize_receive_buffer(int size)
526{
527 if(size <= receive_buffer_size)
528 return 0;
529
530 if(receive_buffer == NULL) {
531 receive_buffer = malloc(size);
532 if(receive_buffer == NULL) {
5b003f31 533 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
f135ba52 534 safe_strerror(errno));
ca10883e
DS
535 return -1;
536 }
537 receive_buffer_size = size;
538 } else {
539 unsigned char *new;
540 new = realloc(receive_buffer, size);
541 if(new == NULL) {
5b003f31 542 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
f135ba52 543 safe_strerror(errno));
ca10883e
DS
544 return -1;
545 }
546 receive_buffer = new;
547 receive_buffer_size = size;
548 }
549 return 1;
550}
551
552static void
03a38493 553babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
ca10883e
DS
554{
555 struct interface *ifp;
556 babel_interface_nfo *babel_ifp;
557 int type;
558 int family;
559
560 if (! dist->ifname)
561 return;
562
a36898e7 563 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
ca10883e
DS
564 if (ifp == NULL)
565 return;
566
567 babel_ifp = babel_get_if_nfo(ifp);
568
569 for (type = 0; type < DISTRIBUTE_MAX; type++) {
570 family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
571 AFI_IP : AFI_IP6;
572 if (dist->list[type])
573 babel_ifp->list[type] = access_list_lookup (family,
574 dist->list[type]);
575 else
576 babel_ifp->list[type] = NULL;
577 if (dist->prefix[type])
578 babel_ifp->prefix[type] = prefix_list_lookup (family,
579 dist->prefix[type]);
580 else
581 babel_ifp->prefix[type] = NULL;
582 }
583}
584
585static void
586babel_distribute_update_interface (struct interface *ifp)
587{
03a38493 588 struct distribute *dist = NULL;
ca10883e 589
03a38493
PG
590 if (babel_routing_process)
591 dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
ca10883e 592 if (dist)
03a38493 593 babel_distribute_update (babel_routing_process->distribute_ctx, dist);
ca10883e
DS
594}
595
596/* Update all interface's distribute list. */
597static void
598babel_distribute_update_all (struct prefix_list *notused)
599{
f4e14fdb 600 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 601 struct interface *ifp;
ca10883e 602
451fda4f 603 FOR_ALL_INTERFACES (vrf, ifp)
ca10883e
DS
604 babel_distribute_update_interface (ifp);
605}
606
607static void
608babel_distribute_update_all_wrapper (struct access_list *notused)
609{
610 babel_distribute_update_all(NULL);
611}
612
613
614/* [Command] */
f84d11d1
DS
615DEFUN_NOSH (router_babel,
616 router_babel_cmd,
617 "router babel",
618 "Enable a routing process\n"
619 "Make Babel instance command\n")
ca10883e
DS
620{
621 int ret;
622
623 vty->node = BABEL_NODE;
624
625 if (!babel_routing_process) {
626 ret = babel_create_routing_process ();
627
628 /* Notice to user we couldn't create Babel. */
629 if (ret < 0) {
630 zlog_warn ("can't create Babel");
631 return CMD_WARNING;
632 }
633 }
634
635 return CMD_SUCCESS;
636}
637
638/* [Command] */
639DEFUN (no_router_babel,
640 no_router_babel_cmd,
641 "no router babel",
642 NO_STR
643 "Disable a routing process\n"
7111c1a0 644 "Remove Babel instance command\n")
ca10883e
DS
645{
646 if(babel_routing_process)
647 babel_clean_routing_process();
648 return CMD_SUCCESS;
649}
650
651/* [Babel Command] */
652DEFUN (babel_diversity,
653 babel_diversity_cmd,
654 "babel diversity",
655 "Babel commands\n"
656 "Enable diversity-aware routing.\n")
657{
658 diversity_kind = DIVERSITY_CHANNEL;
659 return CMD_SUCCESS;
660}
661
662/* [Babel Command] */
663DEFUN (no_babel_diversity,
664 no_babel_diversity_cmd,
665 "no babel diversity",
666 NO_STR
667 "Babel commands\n"
668 "Disable diversity-aware routing.\n")
669{
670 diversity_kind = DIVERSITY_NONE;
671 return CMD_SUCCESS;
672}
673
674/* [Babel Command] */
675DEFUN (babel_diversity_factor,
676 babel_diversity_factor_cmd,
677 "babel diversity-factor (1-256)",
678 "Babel commands\n"
679 "Set the diversity factor.\n"
680 "Factor in units of 1/256.\n")
681{
682 int factor;
683
facfee22 684 factor = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
685
686 diversity_factor = factor;
687 return CMD_SUCCESS;
688}
689
690/* [Babel Command] */
691DEFUN (babel_set_resend_delay,
692 babel_set_resend_delay_cmd,
693 "babel resend-delay (20-655340)",
694 "Babel commands\n"
695 "Time before resending a message\n"
696 "Milliseconds\n")
697{
698 int interval;
699
facfee22 700 interval = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
701
702 resend_delay = interval;
703 return CMD_SUCCESS;
704}
705
706/* [Babel Command] */
707DEFUN (babel_set_smoothing_half_life,
708 babel_set_smoothing_half_life_cmd,
709 "babel smoothing-half-life (0-65534)",
710 "Babel commands\n"
711 "Smoothing half-life\n"
712 "Seconds (0 to disable)\n")
713{
714 int seconds;
715
facfee22 716 seconds = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
717
718 change_smoothing_half_life(seconds);
719 return CMD_SUCCESS;
720}
721
722void
723babeld_quagga_init(void)
724{
725
612c2c15 726 install_node(&cmd_babel_node);
ca10883e
DS
727
728 install_element(CONFIG_NODE, &router_babel_cmd);
729 install_element(CONFIG_NODE, &no_router_babel_cmd);
730
731 install_default(BABEL_NODE);
732 install_element(BABEL_NODE, &babel_diversity_cmd);
733 install_element(BABEL_NODE, &no_babel_diversity_cmd);
734 install_element(BABEL_NODE, &babel_diversity_factor_cmd);
735 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
736 install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
737
738 babel_if_init();
739
740 /* Access list install. */
741 access_list_init ();
742 access_list_add_hook (babel_distribute_update_all_wrapper);
743 access_list_delete_hook (babel_distribute_update_all_wrapper);
744
745 /* Prefix list initialize.*/
746 prefix_list_init ();
747 prefix_list_add_hook (babel_distribute_update_all);
748 prefix_list_delete_hook (babel_distribute_update_all);
749
750 /* Distribute list install. */
03a38493 751 distribute_list_init(BABEL_NODE);
ca10883e
DS
752}
753
754/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
755
756int
757input_filter(const unsigned char *id,
758 const unsigned char *prefix, unsigned short plen,
759 const unsigned char *neigh, unsigned int ifindex)
760{
761 return babel_filter(0, prefix, plen, ifindex);
762}
763
764int
765output_filter(const unsigned char *id, const unsigned char *prefix,
766 unsigned short plen, unsigned int ifindex)
767{
768 return babel_filter(1, prefix, plen, ifindex);
769}
770
771/* There's no redistribute filter in Quagga -- the zebra daemon does its
772 own filtering. */
773int
774redistribute_filter(const unsigned char *prefix, unsigned short plen,
775 unsigned int ifindex, int proto)
776{
777 return 0;
778}
779
03a38493
PG
780struct babel *babel_lookup(void)
781{
782 return babel_routing_process;
783}