]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babeld.c
Merge pull request #12640 from vfreex/babel-no-commands
[mirror_frr.git] / babeld / babeld.c
1 /*
2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE 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"
32 #include "lib_errors.h"
33 #include "network.h"
34 #include "if.h"
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"
48 #include "babel_errors.h"
49
50 #ifndef VTYSH_EXTRACT_PL
51 #include "babeld/babeld_clippy.c"
52 #endif
53
54 DEFINE_MGROUP(BABELD, "babeld");
55 DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure");
56
57 static void babel_init_routing_process(struct thread *thread);
58 static void babel_get_myid(void);
59 static void babel_initial_noise(void);
60 static void babel_read_protocol(struct thread *thread);
61 static void babel_main_loop(struct thread *thread);
62 static void babel_set_timer(struct timeval *timeout);
63 static void babel_fill_with_next_timeout(struct timeval *tv);
64 static void
65 babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist);
66
67 /* Informations relative to the babel running daemon. */
68 static struct babel *babel_routing_process = NULL;
69 static unsigned char *receive_buffer = NULL;
70 static int receive_buffer_size = 0;
71
72 /* timeouts */
73 struct timeval check_neighbours_timeout;
74 static time_t expiry_time;
75 static time_t source_expiry_time;
76
77 /* Babel node structure. */
78 static int babel_config_write (struct vty *vty);
79 static struct cmd_node cmd_babel_node =
80 {
81 .name = "babel",
82 .node = BABEL_NODE,
83 .parent_node = CONFIG_NODE,
84 .prompt = "%s(config-router)# ",
85 .config_write = babel_config_write,
86 };
87
88 /* print current babel configuration on vty */
89 static int
90 babel_config_write (struct vty *vty)
91 {
92 int lines = 0;
93 int afi;
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;
101 vty_out (vty, "router babel\n");
102 if (diversity_kind != DIVERSITY_NONE)
103 {
104 vty_out (vty, " babel diversity\n");
105 lines++;
106 }
107 if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
108 {
109 vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
110 lines++;
111 }
112 if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
113 {
114 vty_out (vty, " babel resend-delay %u\n", resend_delay);
115 lines++;
116 }
117 if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
118 {
119 vty_out (vty, " babel smoothing-half-life %u\n",
120 smoothing_half_life);
121 lines++;
122 }
123 /* list enabled interfaces */
124 lines = 1 + babel_enable_if_config_write (vty);
125 /* list redistributed protocols */
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 }
135 }
136 }
137
138 lines += config_write_distribute (vty, babel_routing_process->distribute_ctx);
139
140 vty_out (vty, "exit\n");
141
142 return lines;
143 }
144
145
146 static int
147 babel_create_routing_process (void)
148 {
149 assert (babel_routing_process == NULL);
150
151 /* Allocaste Babel instance. */
152 babel_routing_process = XCALLOC(MTYPE_BABEL, sizeof(struct babel));
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) {
162 flog_err_sys(EC_LIB_SOCKET, "Couldn't create link local socket: %s",
163 safe_strerror(errno));
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);
171
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;
177 fail:
178 XFREE(MTYPE_BABEL, babel_routing_process);
179 return -1;
180 }
181
182 /* thread reading entries form others babel daemons */
183 static void babel_read_protocol(struct thread *thread)
184 {
185 int rc;
186 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
187 struct interface *ifp = NULL;
188 struct sockaddr_in6 sin6;
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) {
198 flog_err_sys(EC_LIB_SOCKET, "recv: %s", safe_strerror(errno));
199 }
200 } else {
201 FOR_ALL_INTERFACES(vrf, ifp) {
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);
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. */
219 static void babel_init_routing_process(struct thread *thread)
220 {
221 myseqno = (frr_weak_random() & 0xFFFF);
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 */
227 }
228
229 /* fill "myid" with an unique id (only if myid != {0}). */
230 static void
231 babel_get_myid(void)
232 {
233 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
234 struct interface *ifp = NULL;
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
243 FOR_ALL_INTERFACES(vrf, ifp) {
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];
248 rc = if_eui64(ifindex, eui);
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++) {
259 char buf[INTERFACE_NAMSIZ], *ifname;
260 unsigned char eui[8];
261 ifname = if_indextoname(i, buf);
262 if(ifname == NULL)
263 continue;
264 rc = if_eui64(i, eui);
265 if(rc < 0)
266 continue;
267 memcpy(myid, eui, 8);
268 return;
269 }
270
271 flog_err(EC_BABEL_CONFIG, "Couldn't find router id -- using random value.");
272
273 rc = read_random_bytes(myid, 8);
274 if(rc < 0) {
275 flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
276 safe_strerror(errno));
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 */
285 static void
286 babel_initial_noise(void)
287 {
288 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
289 struct interface *ifp = NULL;
290
291 FOR_ALL_INTERFACES(vrf, ifp) {
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
301 FOR_ALL_INTERFACES(vrf, ifp) {
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. */
316 static void
317 babel_clean_routing_process(void)
318 {
319 flush_all_routes();
320 babel_interface_close_all();
321
322 /* cancel events */
323 thread_cancel(&babel_routing_process->t_read);
324 thread_cancel(&babel_routing_process->t_update);
325
326 distribute_list_delete(&babel_routing_process->distribute_ctx);
327 XFREE(MTYPE_BABEL, babel_routing_process);
328 }
329
330 /* Function used with timeout. */
331 static void babel_main_loop(struct thread *thread)
332 {
333 struct timeval tv;
334 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
335 struct interface *ifp = NULL;
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);
346 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
347 (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
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);
351 return;
352 }
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
376 FOR_ALL_INTERFACES(vrf, ifp) {
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
400 FOR_ALL_INTERFACES(vrf, ifp) {
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
415 static void
416 printIfMin(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
455 static void
456 babel_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
464 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
465 struct interface *ifp = NULL;
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);
475 FOR_ALL_INTERFACES(vrf, ifp) {
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) */
498 static void
499 babel_set_timer(struct timeval *timeout)
500 {
501 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
502 thread_cancel(&(babel_routing_process->t_update));
503 thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
504 }
505
506 void
507 schedule_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
518 int
519 resize_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) {
527 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
528 safe_strerror(errno));
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) {
536 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
537 safe_strerror(errno));
538 return -1;
539 }
540 receive_buffer = new;
541 receive_buffer_size = size;
542 }
543 return 1;
544 }
545
546 static void
547 babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
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
557 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
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
579 static void
580 babel_distribute_update_interface (struct interface *ifp)
581 {
582 struct distribute *dist = NULL;
583
584 if (babel_routing_process)
585 dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
586 if (dist)
587 babel_distribute_update (babel_routing_process->distribute_ctx, dist);
588 }
589
590 /* Update all interface's distribute list. */
591 static void
592 babel_distribute_update_all (struct prefix_list *notused)
593 {
594 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
595 struct interface *ifp;
596
597 FOR_ALL_INTERFACES (vrf, ifp)
598 babel_distribute_update_interface (ifp);
599 }
600
601 static void
602 babel_distribute_update_all_wrapper (struct access_list *notused)
603 {
604 babel_distribute_update_all(NULL);
605 }
606
607
608 /* [Command] */
609 DEFUN_NOSH (router_babel,
610 router_babel_cmd,
611 "router babel",
612 "Enable a routing process\n"
613 "Make Babel instance command\n")
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] */
633 DEFUN (no_router_babel,
634 no_router_babel_cmd,
635 "no router babel",
636 NO_STR
637 "Disable a routing process\n"
638 "Remove Babel instance command\n")
639 {
640 if(babel_routing_process)
641 babel_clean_routing_process();
642 return CMD_SUCCESS;
643 }
644
645 /* [Babel Command] */
646 DEFUN (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] */
657 DEFUN (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] */
669 DEFPY (babel_diversity_factor,
670 babel_diversity_factor_cmd,
671 "[no] babel diversity-factor (1-256)$factor",
672 NO_STR
673 "Babel commands\n"
674 "Set the diversity factor.\n"
675 "Factor in units of 1/256.\n")
676 {
677 diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor;
678 return CMD_SUCCESS;
679 }
680
681 /* [Babel Command] */
682 DEFPY (babel_set_resend_delay,
683 babel_set_resend_delay_cmd,
684 "[no] babel resend-delay (20-655340)$delay",
685 NO_STR
686 "Babel commands\n"
687 "Time before resending a message\n"
688 "Milliseconds\n")
689 {
690 resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay;
691 return CMD_SUCCESS;
692 }
693
694 /* [Babel Command] */
695 DEFPY (babel_set_smoothing_half_life,
696 babel_set_smoothing_half_life_cmd,
697 "[no] babel smoothing-half-life (0-65534)$seconds",
698 NO_STR
699 "Babel commands\n"
700 "Smoothing half-life\n"
701 "Seconds (0 to disable)\n")
702 {
703 change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
704 : seconds);
705 return CMD_SUCCESS;
706 }
707
708 DEFUN (babel_distribute_list,
709 babel_distribute_list_cmd,
710 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
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
728 DEFUN (babel_no_distribute_list,
729 babel_no_distribute_list_cmd,
730 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
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
750 DEFUN (babel_ipv6_distribute_list,
751 babel_ipv6_distribute_list_cmd,
752 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
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
771 DEFUN (babel_no_ipv6_distribute_list,
772 babel_no_ipv6_distribute_list_cmd,
773 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
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
794 void
795 babeld_quagga_init(void)
796 {
797
798 install_node(&cmd_babel_node);
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
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
815 vrf_cmd_init(NULL);
816
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);
828 }
829
830 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
831
832 int
833 input_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
840 int
841 output_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. */
849 int
850 redistribute_filter(const unsigned char *prefix, unsigned short plen,
851 unsigned int ifindex, int proto)
852 {
853 return 0;
854 }
855
856 struct babel *babel_lookup(void)
857 {
858 return babel_routing_process;
859 }