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