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