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