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