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