]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babeld.c
*: Change thread->func to return void instead of int
[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
cc9f21da 52static void babel_init_routing_process(struct thread *thread);
ca10883e
DS
53static void babel_get_myid(void);
54static void babel_initial_noise(void);
cc9f21da
DS
55static void babel_read_protocol(struct thread *thread);
56static void babel_main_loop(struct thread *thread);
ca10883e
DS
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 134
07679ad9
IR
135 vty_out (vty, "exit\n");
136
ca10883e
DS
137 return lines;
138}
139
140
141static int
142babel_create_routing_process (void)
143{
144 assert (babel_routing_process == NULL);
145
146 /* Allocaste Babel instance. */
0d6f7fd6 147 babel_routing_process = XCALLOC(MTYPE_BABEL, sizeof(struct babel));
ca10883e
DS
148
149 /* Initialize timeouts */
150 gettime(&babel_now);
151 expiry_time = babel_now.tv_sec + roughly(30);
152 source_expiry_time = babel_now.tv_sec + roughly(300);
153
154 /* Make socket for Babel protocol. */
155 protocol_socket = babel_socket(protocol_port);
156 if (protocol_socket < 0) {
450971aa 157 flog_err_sys(EC_LIB_SOCKET, "Couldn't create link local socket: %s",
f135ba52 158 safe_strerror(errno));
ca10883e
DS
159 goto fail;
160 }
161
162 /* Threads. */
163 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
164 /* wait a little: zebra will announce interfaces, addresses, routes... */
165 thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update);
ca10883e 166
03a38493
PG
167 /* Distribute list install. */
168 babel_routing_process->distribute_ctx = distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT));
169 distribute_list_add_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
170 distribute_list_delete_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
171 return 0;
ca10883e
DS
172fail:
173 XFREE(MTYPE_BABEL, babel_routing_process);
ca10883e
DS
174 return -1;
175}
176
177/* thread reading entries form others babel daemons */
cc9f21da 178static void babel_read_protocol(struct thread *thread)
ca10883e
DS
179{
180 int rc;
f4e14fdb 181 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e
DS
182 struct interface *ifp = NULL;
183 struct sockaddr_in6 sin6;
ca10883e
DS
184
185 assert(babel_routing_process != NULL);
186 assert(protocol_socket >= 0);
187
188 rc = babel_recv(protocol_socket,
189 receive_buffer, receive_buffer_size,
190 (struct sockaddr*)&sin6, sizeof(sin6));
191 if(rc < 0) {
192 if(errno != EAGAIN && errno != EINTR) {
450971aa 193 flog_err_sys(EC_LIB_SOCKET, "recv: %s", safe_strerror(errno));
ca10883e
DS
194 }
195 } else {
f4e14fdb 196 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
197 if(!if_up(ifp))
198 continue;
199 if(ifp->ifindex == (ifindex_t)sin6.sin6_scope_id) {
200 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
201 receive_buffer, rc);
202 break;
203 }
204 }
205 }
206
207 /* re-add thread */
208 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
ca10883e
DS
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. */
cc9f21da 214static void babel_init_routing_process(struct thread *thread)
ca10883e 215{
5920b3eb 216 myseqno = (frr_weak_random() & 0xFFFF);
ca10883e
DS
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 */
ca10883e
DS
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
5c997d29 266 flog_err(EC_BABEL_CONFIG, "Couldn't find router id -- using random value.");
ca10883e
DS
267
268 rc = read_random_bytes(myid, 8);
269 if(rc < 0) {
5b003f31 270 flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
e33b116c 271 safe_strerror(errno));
ca10883e
DS
272 exit(1);
273 }
274 /* Clear group and global bits */
275 myid[0] &= ~3;
276}
277
278/* Make some noise so that others notice us, and send retractions in
279 case we were restarted recently */
280static void
281babel_initial_noise(void)
282{
f4e14fdb 283 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 284 struct interface *ifp = NULL;
ca10883e 285
f4e14fdb 286 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
287 if(!if_up(ifp))
288 continue;
289 /* Apply jitter before we send the first message. */
290 usleep(roughly(10000));
291 gettime(&babel_now);
292 send_hello(ifp);
293 send_wildcard_retraction(ifp);
294 }
295
f4e14fdb 296 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
297 if(!if_up(ifp))
298 continue;
299 usleep(roughly(10000));
300 gettime(&babel_now);
301 send_hello(ifp);
302 send_wildcard_retraction(ifp);
303 send_self_update(ifp);
304 send_request(ifp, NULL, 0);
305 flushupdates(ifp);
306 flushbuf(ifp);
307 }
308}
309
310/* Delete all the added babel routes, make babeld only speak to zebra. */
311static void
4d762f26 312babel_clean_routing_process(void)
ca10883e
DS
313{
314 flush_all_routes();
315 babel_interface_close_all();
316
b3d6bc6e
MS
317 /* cancel events */
318 thread_cancel(&babel_routing_process->t_read);
319 thread_cancel(&babel_routing_process->t_update);
ca10883e 320
03a38493 321 distribute_list_delete(&babel_routing_process->distribute_ctx);
ca10883e 322 XFREE(MTYPE_BABEL, babel_routing_process);
ca10883e
DS
323}
324
325/* Function used with timeout. */
cc9f21da 326static void babel_main_loop(struct thread *thread)
ca10883e
DS
327{
328 struct timeval tv;
f4e14fdb 329 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 330 struct interface *ifp = NULL;
ca10883e
DS
331
332 while(1) {
333 gettime(&babel_now);
334
335 /* timeouts --------------------------------------------------------- */
336 /* get the next timeout */
337 babel_fill_with_next_timeout(&tv);
338 /* if there is no timeout, we must wait. */
339 if(timeval_compare(&tv, &babel_now) > 0) {
340 timeval_minus(&tv, &tv, &babel_now);
a97986ff
DL
341 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
342 (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
ca10883e
DS
343 /* it happens often to have less than 1 ms, it's bad. */
344 timeval_add_msec(&tv, &tv, 300);
345 babel_set_timer(&tv);
cc9f21da
DS
346 return;
347 }
ca10883e
DS
348
349 gettime(&babel_now);
350
351 /* update database -------------------------------------------------- */
352 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
353 int msecs;
354 msecs = check_neighbours();
355 /* Multiply by 3/2 to allow neighbours to expire. */
356 msecs = MAX(3 * msecs / 2, 10);
357 schedule_neighbours_check(msecs, 1);
358 }
359
360 if(babel_now.tv_sec >= expiry_time) {
361 expire_routes();
362 expire_resend();
363 expiry_time = babel_now.tv_sec + roughly(30);
364 }
365
366 if(babel_now.tv_sec >= source_expiry_time) {
367 expire_sources();
368 source_expiry_time = babel_now.tv_sec + roughly(300);
369 }
370
f4e14fdb 371 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
372 babel_interface_nfo *babel_ifp = NULL;
373 if(!if_up(ifp))
374 continue;
375 babel_ifp = babel_get_if_nfo(ifp);
376 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
377 send_hello(ifp);
378 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
379 send_update(ifp, 0, NULL, 0);
380 if(timeval_compare(&babel_now,
381 &babel_ifp->update_flush_timeout) >= 0)
382 flushupdates(ifp);
383 }
384
385 if(resend_time.tv_sec != 0) {
386 if(timeval_compare(&babel_now, &resend_time) >= 0)
387 do_resend();
388 }
389
390 if(unicast_flush_timeout.tv_sec != 0) {
391 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
392 flush_unicast(1);
393 }
394
f4e14fdb 395 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
396 babel_interface_nfo *babel_ifp = NULL;
397 if(!if_up(ifp))
398 continue;
399 babel_ifp = babel_get_if_nfo(ifp);
400 if(babel_ifp->flush_timeout.tv_sec != 0) {
401 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
402 flushbuf(ifp);
403 }
404 }
405 }
406
407 assert(0); /* this line should never be reach */
408}
409
410static void
411printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
412{
413 static struct timeval curr_tv;
414 static char buffer[200];
415 static const char *curr_tag = NULL;
416
417 switch (cmd) {
418 case 0: /* reset timeval */
419 curr_tv = *tv;
420 if(ifname != NULL) {
421 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
422 curr_tag = buffer;
423 } else {
424 curr_tag = tag;
425 }
426 break;
427 case 1: /* take the min */
428 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
429 break;
430 }
431 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
432 tv->tv_usec < curr_tv.tv_usec)) {
433 curr_tv = *tv;
434 if(ifname != NULL) {
435 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
436 curr_tag = buffer;
437 } else {
438 curr_tag = tag;
439 }
440 }
441 break;
442 case 2: /* print message */
443 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
444 break;
445 default:
446 break;
447 }
448}
449
450static void
451babel_fill_with_next_timeout(struct timeval *tv)
452{
453#if (defined NO_DEBUG)
454#define printIfMin(a,b,c,d)
455#else
456#define printIfMin(a,b,c,d) \
457 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
458
f4e14fdb 459 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 460 struct interface *ifp = NULL;
ca10883e
DS
461
462 *tv = check_neighbours_timeout;
463 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
464 timeval_min_sec(tv, expiry_time);
465 printIfMin(tv, 1, "expiry_time", NULL);
466 timeval_min_sec(tv, source_expiry_time);
467 printIfMin(tv, 1, "source_expiry_time", NULL);
468 timeval_min(tv, &resend_time);
469 printIfMin(tv, 1, "resend_time", NULL);
f4e14fdb 470 FOR_ALL_INTERFACES(vrf, ifp) {
ca10883e
DS
471 babel_interface_nfo *babel_ifp = NULL;
472 if(!if_up(ifp))
473 continue;
474 babel_ifp = babel_get_if_nfo(ifp);
475 timeval_min(tv, &babel_ifp->flush_timeout);
476 printIfMin(tv, 1, "flush_timeout", ifp->name);
477 timeval_min(tv, &babel_ifp->hello_timeout);
478 printIfMin(tv, 1, "hello_timeout", ifp->name);
479 timeval_min(tv, &babel_ifp->update_timeout);
480 printIfMin(tv, 1, "update_timeout", ifp->name);
481 timeval_min(tv, &babel_ifp->update_flush_timeout);
482 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
483 }
484 timeval_min(tv, &unicast_flush_timeout);
485 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
486 printIfMin(tv, 2, NULL, NULL);
487#undef printIfMin
488#endif
489}
490
491/* set the t_update thread of the babel routing process to be launch in
492 'timeout' (approximate at the milisecond) */
493static void
494babel_set_timer(struct timeval *timeout)
495{
496 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
b3d6bc6e 497 thread_cancel(&(babel_routing_process->t_update));
ca10883e
DS
498 thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
499}
500
501void
502schedule_neighbours_check(int msecs, int override)
503{
504 struct timeval timeout;
505
506 timeval_add_msec(&timeout, &babel_now, msecs);
507 if(override)
508 check_neighbours_timeout = timeout;
509 else
510 timeval_min(&check_neighbours_timeout, &timeout);
511}
512
513int
514resize_receive_buffer(int size)
515{
516 if(size <= receive_buffer_size)
517 return 0;
518
519 if(receive_buffer == NULL) {
520 receive_buffer = malloc(size);
521 if(receive_buffer == NULL) {
5b003f31 522 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
f135ba52 523 safe_strerror(errno));
ca10883e
DS
524 return -1;
525 }
526 receive_buffer_size = size;
527 } else {
528 unsigned char *new;
529 new = realloc(receive_buffer, size);
530 if(new == NULL) {
5b003f31 531 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
f135ba52 532 safe_strerror(errno));
ca10883e
DS
533 return -1;
534 }
535 receive_buffer = new;
536 receive_buffer_size = size;
537 }
538 return 1;
539}
540
541static void
03a38493 542babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
ca10883e
DS
543{
544 struct interface *ifp;
545 babel_interface_nfo *babel_ifp;
546 int type;
547 int family;
548
549 if (! dist->ifname)
550 return;
551
a36898e7 552 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
ca10883e
DS
553 if (ifp == NULL)
554 return;
555
556 babel_ifp = babel_get_if_nfo(ifp);
557
558 for (type = 0; type < DISTRIBUTE_MAX; type++) {
559 family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
560 AFI_IP : AFI_IP6;
561 if (dist->list[type])
562 babel_ifp->list[type] = access_list_lookup (family,
563 dist->list[type]);
564 else
565 babel_ifp->list[type] = NULL;
566 if (dist->prefix[type])
567 babel_ifp->prefix[type] = prefix_list_lookup (family,
568 dist->prefix[type]);
569 else
570 babel_ifp->prefix[type] = NULL;
571 }
572}
573
574static void
575babel_distribute_update_interface (struct interface *ifp)
576{
03a38493 577 struct distribute *dist = NULL;
ca10883e 578
03a38493
PG
579 if (babel_routing_process)
580 dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
ca10883e 581 if (dist)
03a38493 582 babel_distribute_update (babel_routing_process->distribute_ctx, dist);
ca10883e
DS
583}
584
585/* Update all interface's distribute list. */
586static void
587babel_distribute_update_all (struct prefix_list *notused)
588{
f4e14fdb 589 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
ca10883e 590 struct interface *ifp;
ca10883e 591
451fda4f 592 FOR_ALL_INTERFACES (vrf, ifp)
ca10883e
DS
593 babel_distribute_update_interface (ifp);
594}
595
596static void
597babel_distribute_update_all_wrapper (struct access_list *notused)
598{
599 babel_distribute_update_all(NULL);
600}
601
602
603/* [Command] */
f84d11d1
DS
604DEFUN_NOSH (router_babel,
605 router_babel_cmd,
606 "router babel",
607 "Enable a routing process\n"
608 "Make Babel instance command\n")
ca10883e
DS
609{
610 int ret;
611
612 vty->node = BABEL_NODE;
613
614 if (!babel_routing_process) {
615 ret = babel_create_routing_process ();
616
617 /* Notice to user we couldn't create Babel. */
618 if (ret < 0) {
619 zlog_warn ("can't create Babel");
620 return CMD_WARNING;
621 }
622 }
623
624 return CMD_SUCCESS;
625}
626
627/* [Command] */
628DEFUN (no_router_babel,
629 no_router_babel_cmd,
630 "no router babel",
631 NO_STR
632 "Disable a routing process\n"
7111c1a0 633 "Remove Babel instance command\n")
ca10883e
DS
634{
635 if(babel_routing_process)
636 babel_clean_routing_process();
637 return CMD_SUCCESS;
638}
639
640/* [Babel Command] */
641DEFUN (babel_diversity,
642 babel_diversity_cmd,
643 "babel diversity",
644 "Babel commands\n"
645 "Enable diversity-aware routing.\n")
646{
647 diversity_kind = DIVERSITY_CHANNEL;
648 return CMD_SUCCESS;
649}
650
651/* [Babel Command] */
652DEFUN (no_babel_diversity,
653 no_babel_diversity_cmd,
654 "no babel diversity",
655 NO_STR
656 "Babel commands\n"
657 "Disable diversity-aware routing.\n")
658{
659 diversity_kind = DIVERSITY_NONE;
660 return CMD_SUCCESS;
661}
662
663/* [Babel Command] */
664DEFUN (babel_diversity_factor,
665 babel_diversity_factor_cmd,
666 "babel diversity-factor (1-256)",
667 "Babel commands\n"
668 "Set the diversity factor.\n"
669 "Factor in units of 1/256.\n")
670{
671 int factor;
672
facfee22 673 factor = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
674
675 diversity_factor = factor;
676 return CMD_SUCCESS;
677}
678
679/* [Babel Command] */
680DEFUN (babel_set_resend_delay,
681 babel_set_resend_delay_cmd,
682 "babel resend-delay (20-655340)",
683 "Babel commands\n"
684 "Time before resending a message\n"
685 "Milliseconds\n")
686{
687 int interval;
688
facfee22 689 interval = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
690
691 resend_delay = interval;
692 return CMD_SUCCESS;
693}
694
695/* [Babel Command] */
696DEFUN (babel_set_smoothing_half_life,
697 babel_set_smoothing_half_life_cmd,
698 "babel smoothing-half-life (0-65534)",
699 "Babel commands\n"
700 "Smoothing half-life\n"
701 "Seconds (0 to disable)\n")
702{
703 int seconds;
704
facfee22 705 seconds = strtoul(argv[2]->arg, NULL, 10);
ca10883e
DS
706
707 change_smoothing_half_life(seconds);
708 return CMD_SUCCESS;
709}
710
32282a6e
DS
711DEFUN (babel_distribute_list,
712 babel_distribute_list_cmd,
c60dec36 713 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
32282a6e
DS
714 "Filter networks in routing updates\n"
715 "Specify a prefix\n"
716 "Access-list name\n"
717 "Filter incoming routing updates\n"
718 "Filter outgoing routing updates\n"
719 "Interface name\n")
720{
721 const char *ifname = NULL;
722 int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
723
724 if (argv[argc - 1]->type == VARIABLE_TKN)
725 ifname = argv[argc - 1]->arg;
726
727 return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
728 argv[1 + prefix]->arg, ifname);
729}
730
731DEFUN (babel_no_distribute_list,
732 babel_no_distribute_list_cmd,
c60dec36 733 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
32282a6e
DS
734 NO_STR
735 "Filter networks in routing updates\n"
736 "Specify a prefix\n"
737 "Access-list name\n"
738 "Filter incoming routing updates\n"
739 "Filter outgoing routing updates\n"
740 "Interface name\n")
741{
742 const char *ifname = NULL;
743 int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
744
745 if (argv[argc - 1]->type == VARIABLE_TKN)
746 ifname = argv[argc - 1]->arg;
747
748 return distribute_list_no_parser(vty, prefix, true,
749 argv[3 + prefix]->text,
750 argv[2 + prefix]->arg, ifname);
751}
752
753DEFUN (babel_ipv6_distribute_list,
754 babel_ipv6_distribute_list_cmd,
c60dec36 755 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
32282a6e
DS
756 "IPv6\n"
757 "Filter networks in routing updates\n"
758 "Specify a prefix\n"
759 "Access-list name\n"
760 "Filter incoming routing updates\n"
761 "Filter outgoing routing updates\n"
762 "Interface name\n")
763{
764 const char *ifname = NULL;
765 int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
766
767 if (argv[argc - 1]->type == VARIABLE_TKN)
768 ifname = argv[argc - 1]->arg;
769
770 return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
771 argv[2 + prefix]->arg, ifname);
772}
773
774DEFUN (babel_no_ipv6_distribute_list,
775 babel_no_ipv6_distribute_list_cmd,
c60dec36 776 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
32282a6e
DS
777 NO_STR
778 "IPv6\n"
779 "Filter networks in routing updates\n"
780 "Specify a prefix\n"
781 "Access-list name\n"
782 "Filter incoming routing updates\n"
783 "Filter outgoing routing updates\n"
784 "Interface name\n")
785{
786 const char *ifname = NULL;
787 int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
788
789 if (argv[argc - 1]->type == VARIABLE_TKN)
790 ifname = argv[argc - 1]->arg;
791
792 return distribute_list_no_parser(vty, prefix, false,
793 argv[4 + prefix]->text,
794 argv[3 + prefix]->arg, ifname);
795}
796
ca10883e
DS
797void
798babeld_quagga_init(void)
799{
800
612c2c15 801 install_node(&cmd_babel_node);
ca10883e
DS
802
803 install_element(CONFIG_NODE, &router_babel_cmd);
804 install_element(CONFIG_NODE, &no_router_babel_cmd);
805
806 install_default(BABEL_NODE);
807 install_element(BABEL_NODE, &babel_diversity_cmd);
808 install_element(BABEL_NODE, &no_babel_diversity_cmd);
809 install_element(BABEL_NODE, &babel_diversity_factor_cmd);
810 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
811 install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
812
32282a6e
DS
813 install_element(BABEL_NODE, &babel_distribute_list_cmd);
814 install_element(BABEL_NODE, &babel_no_distribute_list_cmd);
815 install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd);
816 install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd);
817
cfc369c4 818 vrf_cmd_init(NULL);
f5eef2d5 819
ca10883e
DS
820 babel_if_init();
821
822 /* Access list install. */
823 access_list_init ();
824 access_list_add_hook (babel_distribute_update_all_wrapper);
825 access_list_delete_hook (babel_distribute_update_all_wrapper);
826
827 /* Prefix list initialize.*/
828 prefix_list_init ();
829 prefix_list_add_hook (babel_distribute_update_all);
830 prefix_list_delete_hook (babel_distribute_update_all);
ca10883e
DS
831}
832
833/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
834
835int
836input_filter(const unsigned char *id,
837 const unsigned char *prefix, unsigned short plen,
838 const unsigned char *neigh, unsigned int ifindex)
839{
840 return babel_filter(0, prefix, plen, ifindex);
841}
842
843int
844output_filter(const unsigned char *id, const unsigned char *prefix,
845 unsigned short plen, unsigned int ifindex)
846{
847 return babel_filter(1, prefix, plen, ifindex);
848}
849
850/* There's no redistribute filter in Quagga -- the zebra daemon does its
851 own filtering. */
852int
853redistribute_filter(const unsigned char *prefix, unsigned short plen,
854 unsigned int ifindex, int proto)
855{
856 return 0;
857}
858
03a38493
PG
859struct babel *babel_lookup(void)
860{
861 return babel_routing_process;
862}