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