1 // SPDX-License-Identifier: MIT
3 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
12 #include "distribute.h"
13 #include "lib_errors.h"
16 #include "babel_main.h"
19 #include "babel_interface.h"
22 #include "babel_zebra.h"
23 #include "neighbour.h"
26 #include "babel_errors.h"
28 #ifndef VTYSH_EXTRACT_PL
29 #include "babeld/babel_interface_clippy.c"
32 DEFINE_MTYPE_STATIC(BABELD
, BABEL_IF
, "Babel Interface");
34 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
36 static int babel_enable_if_lookup (const char *ifname
);
37 static int babel_enable_if_add (const char *ifname
);
38 static int babel_enable_if_delete (const char *ifname
);
39 static int interface_recalculate(struct interface
*ifp
);
40 static int interface_reset(struct interface
*ifp
);
41 static int babel_if_new_hook (struct interface
*ifp
);
42 static int babel_if_delete_hook (struct interface
*ifp
);
43 static int interface_config_write (struct vty
*vty
);
44 static babel_interface_nfo
* babel_interface_allocate (void);
45 static void babel_interface_free (babel_interface_nfo
*bi
);
48 static vector babel_enable_if
; /* enable interfaces (by cmd). */
50 int babel_ifp_up(struct interface
*ifp
)
52 debugf(BABEL_DEBUG_IF
, "receive an 'interface up'");
54 interface_recalculate(ifp
);
59 babel_ifp_down(struct interface
*ifp
)
61 debugf(BABEL_DEBUG_IF
, "receive an 'interface down'");
71 int babel_ifp_create (struct interface
*ifp
)
73 debugf(BABEL_DEBUG_IF
, "receive an 'interface add'");
75 interface_recalculate(ifp
);
81 babel_ifp_destroy(struct interface
*ifp
)
83 debugf(BABEL_DEBUG_IF
, "receive an 'interface delete'");
92 babel_interface_address_add (ZAPI_CALLBACK_ARGS
)
94 babel_interface_nfo
*babel_ifp
;
95 struct connected
*ifc
;
96 struct prefix
*prefix
;
98 debugf(BABEL_DEBUG_IF
, "receive an 'interface address add'");
100 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
101 zclient
->ibuf
, vrf_id
);
106 prefix
= ifc
->address
;
108 if (prefix
->family
== AF_INET
) {
109 flush_interface_routes(ifc
->ifp
, 0);
110 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
111 if (babel_ifp
->ipv4
== NULL
) {
112 babel_ifp
->ipv4
= malloc(4);
113 if (babel_ifp
->ipv4
== NULL
) {
114 flog_err(EC_BABEL_MEMORY
, "not enough memory");
116 memcpy(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, 4);
121 send_request(ifc
->ifp
, NULL
, 0);
122 send_update(ifc
->ifp
, 0, NULL
, 0);
128 babel_interface_address_delete (ZAPI_CALLBACK_ARGS
)
130 babel_interface_nfo
*babel_ifp
;
131 struct connected
*ifc
;
132 struct prefix
*prefix
;
134 debugf(BABEL_DEBUG_IF
, "receive an 'interface address delete'");
136 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
137 zclient
->ibuf
, vrf_id
);
142 prefix
= ifc
->address
;
144 if (prefix
->family
== AF_INET
) {
145 flush_interface_routes(ifc
->ifp
, 0);
146 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
147 if (babel_ifp
->ipv4
!= NULL
148 && memcmp(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, IPV4_MAX_BYTELEN
)
150 free(babel_ifp
->ipv4
);
151 babel_ifp
->ipv4
= NULL
;
155 send_request(ifc
->ifp
, NULL
, 0);
156 send_update(ifc
->ifp
, 0, NULL
, 0);
158 connected_free(&ifc
);
162 /* Lookup function. */
164 babel_enable_if_lookup (const char *ifname
)
169 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
170 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
171 if (strcmp (str
, ifname
) == 0)
176 /* Add interface to babel_enable_if. */
178 babel_enable_if_add (const char *ifname
)
181 struct interface
*ifp
= NULL
;
183 ret
= babel_enable_if_lookup (ifname
);
187 vector_set (babel_enable_if
, strdup (ifname
));
189 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
191 interface_recalculate(ifp
);
196 /* Delete interface from babel_enable_if. */
198 babel_enable_if_delete (const char *ifname
)
200 int babel_enable_if_index
;
202 struct interface
*ifp
= NULL
;
204 babel_enable_if_index
= babel_enable_if_lookup (ifname
);
205 if (babel_enable_if_index
< 0)
208 str
= vector_slot (babel_enable_if
, babel_enable_if_index
);
210 vector_unset (babel_enable_if
, babel_enable_if_index
);
212 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
214 interface_reset(ifp
);
219 /* [Babel Command] Babel enable on specified interface or matched network. */
220 DEFUN (babel_network
,
222 "network IF_OR_ADDR",
223 "Enable Babel protocol on specified interface or network.\n"
224 "Interface or address\n")
229 ret
= str2prefix (argv
[1]->arg
, &p
);
231 /* Given string is: */
232 if (ret
) /* an IPv4 or v6 network */
233 return CMD_ERR_NO_MATCH
; /* not implemented yet */
234 else /* an interface name */
235 ret
= babel_enable_if_add (argv
[1]->arg
);
238 vty_out (vty
, "There is same network configuration %s\n",
246 /* [Babel Command] Babel enable on specified interface or matched network. */
247 DEFUN (no_babel_network
,
248 no_babel_network_cmd
,
249 "no network IF_OR_ADDR",
251 "Disable Babel protocol on specified interface or network.\n"
252 "Interface or address\n")
257 ret
= str2prefix (argv
[2]->arg
, &p
);
259 /* Given string is: */
260 if (ret
) /* an IPv4 or v6 network */
261 return CMD_ERR_NO_MATCH
; /* not implemented yet */
262 else /* an interface name */
263 ret
= babel_enable_if_delete (argv
[2]->arg
);
266 vty_out (vty
, "can't find network %s\n",argv
[2]->arg
);
267 return CMD_WARNING_CONFIG_FAILED
;
273 /* There are a number of interface parameters that must be changed when
274 an interface becomes wired/wireless. In Quagga, they cannot be
275 configured separately. */
278 babel_set_wired_internal(babel_interface_nfo
*babel_ifp
, int wired
)
281 SET_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
);
282 SET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
283 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRED
;
284 babel_ifp
->channel
= BABEL_IF_CHANNEL_NONINTERFERING
;
285 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_LQ
);
288 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
);
289 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
290 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRELESS
;
291 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
292 SET_FLAG(babel_ifp
->flags
, BABEL_IF_LQ
);
297 /* [Interface Command] Tell the interface is wire. */
298 DEFPY (babel_set_wired
,
302 "Babel interface commands\n"
303 "Enable wired optimizations\n")
305 VTY_DECLVAR_CONTEXT(interface
, ifp
);
306 babel_interface_nfo
*babel_ifp
;
308 babel_ifp
= babel_get_if_nfo(ifp
);
310 assert (babel_ifp
!= NULL
);
311 babel_set_wired_internal(babel_ifp
, no
? 0 : 1);
315 /* [Interface Command] Tell the interface is wireless (default). */
316 DEFPY (babel_set_wireless
,
317 babel_set_wireless_cmd
,
318 "[no] babel wireless",
320 "Babel interface commands\n"
321 "Disable wired optimizations (assume wireless)\n")
323 VTY_DECLVAR_CONTEXT(interface
, ifp
);
324 babel_interface_nfo
*babel_ifp
;
326 babel_ifp
= babel_get_if_nfo(ifp
);
328 assert (babel_ifp
!= NULL
);
329 babel_set_wired_internal(babel_ifp
, no
? 1 : 0);
333 /* [Interface Command] Enable split horizon. */
334 DEFPY (babel_split_horizon
,
335 babel_split_horizon_cmd
,
336 "[no] babel split-horizon",
338 "Babel interface commands\n"
339 "Enable split horizon processing\n")
341 VTY_DECLVAR_CONTEXT(interface
, ifp
);
342 babel_interface_nfo
*babel_ifp
;
344 babel_ifp
= babel_get_if_nfo(ifp
);
346 assert (babel_ifp
!= NULL
);
348 SET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
350 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
354 /* [Interface Command]. */
355 DEFPY (babel_set_hello_interval
,
356 babel_set_hello_interval_cmd
,
357 "[no] babel hello-interval (20-655340)",
359 "Babel interface commands\n"
360 "Time between scheduled hellos\n"
363 VTY_DECLVAR_CONTEXT(interface
, ifp
);
364 babel_interface_nfo
*babel_ifp
;
366 babel_ifp
= babel_get_if_nfo(ifp
);
367 assert (babel_ifp
!= NULL
);
369 babel_ifp
->hello_interval
= no
?
370 BABEL_DEFAULT_HELLO_INTERVAL
: hello_interval
;
374 /* [Interface Command]. */
375 DEFPY (babel_set_update_interval
,
376 babel_set_update_interval_cmd
,
377 "[no] babel update-interval (20-655340)",
379 "Babel interface commands\n"
380 "Time between scheduled updates\n"
383 VTY_DECLVAR_CONTEXT(interface
, ifp
);
384 babel_interface_nfo
*babel_ifp
;
386 babel_ifp
= babel_get_if_nfo(ifp
);
387 assert (babel_ifp
!= NULL
);
389 babel_ifp
->update_interval
= no
?
390 BABEL_DEFAULT_UPDATE_INTERVAL
: update_interval
;
394 DEFPY (babel_set_rxcost
,
395 babel_set_rxcost_cmd
,
396 "[no] babel rxcost (1-65534)",
398 "Babel interface commands\n"
399 "Rxcost multiplier\n"
402 VTY_DECLVAR_CONTEXT(interface
, ifp
);
403 babel_interface_nfo
*babel_ifp
;
405 babel_ifp
= babel_get_if_nfo(ifp
);
406 assert (babel_ifp
!= NULL
);
409 rxcost
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
410 BABEL_DEFAULT_RXCOST_WIRED
: BABEL_DEFAULT_RXCOST_WIRELESS
;
412 babel_ifp
->cost
= rxcost
;
416 DEFPY (babel_set_rtt_decay
,
417 babel_set_rtt_decay_cmd
,
418 "[no] babel rtt-decay (1-256)",
420 "Babel interface commands\n"
421 "Decay factor for exponential moving average of RTT samples\n"
424 VTY_DECLVAR_CONTEXT(interface
, ifp
);
425 babel_interface_nfo
*babel_ifp
;
427 babel_ifp
= babel_get_if_nfo(ifp
);
428 assert (babel_ifp
!= NULL
);
430 babel_ifp
->rtt_decay
= no
? BABEL_DEFAULT_RTT_DECAY
: rtt_decay
;
434 DEFPY (babel_set_rtt_min
,
435 babel_set_rtt_min_cmd
,
436 "[no] babel rtt-min (1-65535)",
438 "Babel interface commands\n"
439 "Minimum RTT starting for increasing cost\n"
442 VTY_DECLVAR_CONTEXT(interface
, ifp
);
443 babel_interface_nfo
*babel_ifp
;
445 babel_ifp
= babel_get_if_nfo(ifp
);
446 assert (babel_ifp
!= NULL
);
448 /* The value is entered in milliseconds but stored as microseconds. */
449 babel_ifp
->rtt_min
= no
? BABEL_DEFAULT_RTT_MIN
: rtt_min
* 1000;
453 DEFPY (babel_set_rtt_max
,
454 babel_set_rtt_max_cmd
,
455 "[no] babel rtt-max (1-65535)",
457 "Babel interface commands\n"
461 VTY_DECLVAR_CONTEXT(interface
, ifp
);
462 babel_interface_nfo
*babel_ifp
;
464 babel_ifp
= babel_get_if_nfo(ifp
);
465 assert (babel_ifp
!= NULL
);
467 /* The value is entered in milliseconds but stored as microseconds. */
468 babel_ifp
->rtt_max
= no
? BABEL_DEFAULT_RTT_MAX
: rtt_max
* 1000;
472 DEFPY (babel_set_max_rtt_penalty
,
473 babel_set_max_rtt_penalty_cmd
,
474 "[no] babel max-rtt-penalty (0-65535)",
476 "Babel interface commands\n"
477 "Maximum additional cost due to RTT\n"
480 VTY_DECLVAR_CONTEXT(interface
, ifp
);
481 babel_interface_nfo
*babel_ifp
;
483 babel_ifp
= babel_get_if_nfo(ifp
);
484 assert (babel_ifp
!= NULL
);
486 babel_ifp
->max_rtt_penalty
= no
?
487 BABEL_DEFAULT_MAX_RTT_PENALTY
: max_rtt_penalty
;
491 DEFPY (babel_set_enable_timestamps
,
492 babel_set_enable_timestamps_cmd
,
493 "[no] babel enable-timestamps",
495 "Babel interface commands\n"
496 "Enable timestamps\n")
498 VTY_DECLVAR_CONTEXT(interface
, ifp
);
499 babel_interface_nfo
*babel_ifp
;
501 babel_ifp
= babel_get_if_nfo(ifp
);
502 assert (babel_ifp
!= NULL
);
504 SET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
506 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
510 DEFPY (babel_set_channel
,
511 babel_set_channel_cmd
,
512 "[no] babel channel <(1-254)$ch|interfering$interfering|"
513 "noninterfering$noninterfering>",
515 "Babel interface commands\n"
516 "Channel number for diversity routing\n"
518 "Mark channel as interfering\n"
519 "Mark channel as noninterfering\n"
522 VTY_DECLVAR_CONTEXT(interface
, ifp
);
523 babel_interface_nfo
*babel_ifp
;
525 babel_ifp
= babel_get_if_nfo(ifp
);
526 assert (babel_ifp
!= NULL
);
529 ch
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
530 BABEL_IF_CHANNEL_NONINTERFERING
: BABEL_IF_CHANNEL_INTERFERING
;
531 else if (interfering
)
532 ch
= BABEL_IF_CHANNEL_INTERFERING
;
533 else if (noninterfering
)
534 ch
= BABEL_IF_CHANNEL_NONINTERFERING
;
536 babel_ifp
->channel
= ch
;
540 /* This should be no more than half the hello interval, so that hellos
541 aren't sent late. The result is in milliseconds. */
543 jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
545 unsigned interval
= babel_ifp
->hello_interval
;
547 interval
= MIN(interval
, 100);
549 interval
= MIN(interval
, 4000);
550 return roughly(interval
) / 4;
554 update_jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
556 unsigned interval
= babel_ifp
->hello_interval
;
558 interval
= MIN(interval
, 100);
560 interval
= MIN(interval
, 4000);
561 return roughly(interval
);
564 /* calculate babeld's specific datas of an interface (change when the interface
567 interface_recalculate(struct interface
*ifp
)
569 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
570 unsigned char *tmp
= NULL
;
572 struct ipv6_mreq mreq
;
577 if (!if_is_operative(ifp
) || !CHECK_FLAG(ifp
->flags
, IFF_RUNNING
)) {
578 interface_reset(ifp
);
582 SET_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
);
584 mtu
= MIN(ifp
->mtu
, ifp
->mtu6
);
586 /* We need to be able to fit at least two messages into a packet,
587 so MTUs below 116 require lower layer fragmentation. */
588 /* In IPv6, the minimum MTU is 1280, and every host must be able
589 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
591 debugf(BABEL_DEBUG_IF
, "Suspiciously low MTU %d on interface %s (%d).",
592 mtu
, ifp
->name
, ifp
->ifindex
);
596 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
597 babel_ifp
->bufsize
= mtu
- 4 - 60;
598 tmp
= babel_ifp
->sendbuf
;
599 babel_ifp
->sendbuf
= realloc(babel_ifp
->sendbuf
, babel_ifp
->bufsize
);
600 if(babel_ifp
->sendbuf
== NULL
) {
601 flog_err(EC_BABEL_MEMORY
, "Couldn't reallocate sendbuf.");
603 babel_ifp
->bufsize
= 0;
608 rc
= resize_receive_buffer(mtu
);
610 zlog_warn("couldn't resize receive buffer for interface %s (%d) (%d bytes).",
611 ifp
->name
, ifp
->ifindex
, mtu
);
613 memset(&mreq
, 0, sizeof(mreq
));
614 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
615 mreq
.ipv6mr_interface
= ifp
->ifindex
;
617 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
618 (char*)&mreq
, sizeof(mreq
));
619 if (rc
< 0 && errno
!= EADDRINUSE
) {
620 flog_err_sys(EC_LIB_SOCKET
,
621 "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
622 ifp
->name
, safe_strerror(errno
));
623 /* This is probably due to a missing link-local address,
624 so down this interface, and wait until the main loop
625 tries to up it again. */
626 interface_reset(ifp
);
630 set_timeout(&babel_ifp
->hello_timeout
, babel_ifp
->hello_interval
);
631 set_timeout(&babel_ifp
->update_timeout
, babel_ifp
->update_interval
);
633 send_request(ifp
, NULL
, 0);
635 update_interface_metric(ifp
);
637 debugf(BABEL_DEBUG_COMMON
,
638 "Upped interface %s (%s, cost=%d, channel=%d%s).",
640 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless",
643 babel_ifp
->ipv4
? ", IPv4" : "");
646 send_update(ifp
, 0, NULL
, 0);
651 /* Reset the interface as it was new: it's not removed from the interface list,
652 and may be considered as a upped interface. */
654 interface_reset(struct interface
*ifp
)
657 struct ipv6_mreq mreq
;
658 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
660 if (!CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
))
663 debugf(BABEL_DEBUG_IF
, "interface reset: %s", ifp
->name
);
665 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
);
667 flush_interface_routes(ifp
, 0);
668 babel_ifp
->buffered
= 0;
669 babel_ifp
->bufsize
= 0;
670 free(babel_ifp
->sendbuf
);
671 babel_ifp
->num_buffered_updates
= 0;
672 babel_ifp
->update_bufsize
= 0;
673 if(babel_ifp
->buffered_updates
)
674 free(babel_ifp
->buffered_updates
);
675 babel_ifp
->buffered_updates
= NULL
;
676 babel_ifp
->sendbuf
= NULL
;
678 if(ifp
->ifindex
> 0) {
679 memset(&mreq
, 0, sizeof(mreq
));
680 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
681 mreq
.ipv6mr_interface
= ifp
->ifindex
;
682 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
683 (char*)&mreq
, sizeof(mreq
));
685 flog_err_sys(EC_LIB_SOCKET
,
686 "setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
687 ifp
->name
, safe_strerror(errno
));
690 update_interface_metric(ifp
);
692 debugf(BABEL_DEBUG_COMMON
,"Upped network %s (%s, cost=%d%s).",
694 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless",
696 babel_ifp
->ipv4
? ", IPv4" : "");
701 /* Send retraction to all, and reset all interfaces statistics. */
703 babel_interface_close_all(void)
705 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
706 struct interface
*ifp
= NULL
;
708 FOR_ALL_INTERFACES(vrf
, ifp
) {
711 send_wildcard_retraction(ifp
);
712 /* Make sure that we expire quickly from our neighbours'
713 association caches. */
714 send_hello_noupdate(ifp
, 10);
716 usleep(roughly(1000));
719 FOR_ALL_INTERFACES(vrf
, ifp
) {
722 /* Make sure they got it. */
723 send_wildcard_retraction(ifp
);
724 send_hello_noupdate(ifp
, 1);
726 usleep(roughly(10000));
728 interface_reset(ifp
);
732 /* return "true" if address is one of our ipv6 addresses */
734 is_interface_ll_address(struct interface
*ifp
, const unsigned char *address
)
736 struct connected
*connected
;
737 struct listnode
*node
;
742 FOR_ALL_INTERFACES_ADDRESSES(ifp
, connected
, node
) {
743 if (connected
->address
->family
== AF_INET6
744 && memcmp(&connected
->address
->u
.prefix6
, address
,
754 show_babel_interface_sub (struct vty
*vty
, struct interface
*ifp
)
757 babel_interface_nfo
*babel_ifp
;
759 vty_out (vty
, "%s is %s\n", ifp
->name
,
760 ((is_up
= if_is_operative(ifp
)) ? "up" : "down"));
761 vty_out (vty
, " ifindex %u, MTU %u bytes %s\n",
762 ifp
->ifindex
, MIN(ifp
->mtu
, ifp
->mtu6
), if_flag_dump(ifp
->flags
));
766 vty_out (vty
, " Babel protocol is not enabled on this interface\n");
772 " Babel protocol is enabled, but not running on this interface\n");
775 babel_ifp
= babel_get_if_nfo (ifp
);
776 vty_out (vty
, " Babel protocol is running on this interface\n");
777 vty_out (vty
, " Operating mode is \"%s\"\n",
778 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless");
779 vty_out (vty
, " Split horizon mode is %s\n",
780 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
) ? "On" : "Off");
781 vty_out (vty
, " Hello interval is %u ms\n", babel_ifp
->hello_interval
);
782 vty_out (vty
, " Update interval is %u ms\n", babel_ifp
->update_interval
);
783 vty_out (vty
, " Rxcost multiplier is %u\n", babel_ifp
->cost
);
786 DEFUN (show_babel_interface
,
787 show_babel_interface_cmd
,
788 "show babel interface [IFNAME]",
790 "Babel information\n"
791 "Interface information\n"
794 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
795 struct interface
*ifp
;
799 FOR_ALL_INTERFACES (vrf
, ifp
)
800 show_babel_interface_sub (vty
, ifp
);
803 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
805 vty_out (vty
, "No such interface name\n");
808 show_babel_interface_sub (vty
, ifp
);
813 show_babel_neighbour_sub (struct vty
*vty
, struct neighbour
*neigh
)
816 "Neighbour %s dev %s reach %04x rxcost %d txcost %d rtt %s rttcost %d%s.\n",
817 format_address(neigh
->address
),
820 neighbour_rxcost(neigh
),
822 format_thousands(neigh
->rtt
),
823 neighbour_rttcost(neigh
),
824 if_up(neigh
->ifp
) ? "" : " (down)");
827 DEFUN (show_babel_neighbour
,
828 show_babel_neighbour_cmd
,
829 "show babel neighbor [IFNAME]",
831 "Babel information\n"
835 struct neighbour
*neigh
;
836 struct interface
*ifp
;
839 FOR_ALL_NEIGHBOURS(neigh
) {
840 show_babel_neighbour_sub(vty
, neigh
);
844 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
846 vty_out (vty
, "No such interface name\n");
849 FOR_ALL_NEIGHBOURS(neigh
) {
850 if(ifp
->ifindex
== neigh
->ifp
->ifindex
) {
851 show_babel_neighbour_sub(vty
, neigh
);
858 babel_prefix_eq(struct prefix
*prefix
, unsigned char *p
, int plen
)
860 if(prefix
->family
== AF_INET6
) {
861 if (prefix
->prefixlen
!= plen
862 || memcmp(&prefix
->u
.prefix6
, p
, IPV6_MAX_BYTELEN
) != 0)
864 } else if(prefix
->family
== AF_INET
) {
865 if (plen
< 96 || !v4mapped(p
) || prefix
->prefixlen
!= plen
- 96
866 || memcmp(&prefix
->u
.prefix4
, p
+ 12, IPV4_MAX_BYTELEN
) != 0)
876 show_babel_routes_sub(struct babel_route
*route
, struct vty
*vty
,
877 struct prefix
*prefix
)
879 const unsigned char *nexthop
=
880 memcmp(route
->nexthop
, route
->neigh
->address
, IPV6_MAX_BYTELEN
)
887 && !babel_prefix_eq(prefix
, route
->src
->prefix
, route
->src
->plen
))
890 if (route
->channels
[0] == 0)
894 snprintf(channels
, sizeof(channels
), " chan (");
895 j
= strlen(channels
);
896 for (k
= 0; k
< DIVERSITY_HOPS
; k
++) {
897 if (route
->channels
[k
] == 0)
901 snprintf(channels
+ j
, 100 - j
, "%u",
903 j
= strlen(channels
);
905 snprintf(channels
+ j
, 100 - j
, ")");
911 "%s metric %d refmetric %d id %s seqno %d%s age %d via %s neigh %s%s%s%s\n",
912 format_prefix(route
->src
->prefix
, route
->src
->plen
),
913 route_metric(route
), route
->refmetric
,
914 format_eui64(route
->src
->id
),
917 (int)(babel_now
.tv_sec
- route
->time
),
918 route
->neigh
->ifp
->name
,
919 format_address(route
->neigh
->address
),
920 nexthop
? " nexthop " : "",
921 nexthop
? format_address(nexthop
) : "",
922 route
->installed
? " (installed)" : route_feasible(route
) ? " (feasible)" : "");
926 show_babel_xroutes_sub (struct xroute
*xroute
, struct vty
*vty
,
927 struct prefix
*prefix
)
929 if(prefix
&& !babel_prefix_eq(prefix
, xroute
->prefix
, xroute
->plen
))
932 vty_out (vty
, "%s metric %d (exported)\n",
933 format_prefix(xroute
->prefix
, xroute
->plen
),
937 DEFUN (show_babel_route
,
938 show_babel_route_cmd
,
941 "Babel information\n"
942 "Babel internal routing table\n")
944 struct route_stream
*routes
= NULL
;
945 struct xroute_stream
*xroutes
= NULL
;
946 routes
= route_stream(0);
949 struct babel_route
*route
= route_stream_next(routes
);
952 show_babel_routes_sub(route
, vty
, NULL
);
954 route_stream_done(routes
);
956 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
958 xroutes
= xroute_stream();
961 struct xroute
*xroute
= xroute_stream_next(xroutes
);
964 show_babel_xroutes_sub(xroute
, vty
, NULL
);
966 xroute_stream_done(xroutes
);
968 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
973 DEFUN (show_babel_route_prefix
,
974 show_babel_route_prefix_cmd
,
975 "show babel route <A.B.C.D/M|X:X::X:X/M>",
977 "Babel information\n"
978 "Babel internal routing table\n"
979 "IPv4 prefix <network>/<length>\n"
980 "IPv6 prefix <network>/<length>\n")
982 struct route_stream
*routes
= NULL
;
983 struct xroute_stream
*xroutes
= NULL
;
984 struct prefix prefix
;
987 ret
= str2prefix(argv
[3]->arg
, &prefix
);
989 vty_out (vty
, "%% Malformed address\n");
993 routes
= route_stream(0);
996 struct babel_route
*route
= route_stream_next(routes
);
999 show_babel_routes_sub(route
, vty
, &prefix
);
1001 route_stream_done(routes
);
1003 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1005 xroutes
= xroute_stream();
1008 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1011 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1013 xroute_stream_done(xroutes
);
1015 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1021 DEFUN (show_babel_route_addr
,
1022 show_babel_route_addr_cmd
,
1023 "show babel route A.B.C.D",
1025 "Babel information\n"
1026 "Babel internal routing table\n"
1027 "IPv4 address <network>/<length>\n")
1029 struct in_addr addr
;
1030 char buf
[INET_ADDRSTRLEN
+ 8];
1031 char buf1
[INET_ADDRSTRLEN
+ 8];
1032 struct route_stream
*routes
= NULL
;
1033 struct xroute_stream
*xroutes
= NULL
;
1034 struct prefix prefix
;
1037 ret
= inet_aton (argv
[3]->arg
, &addr
);
1039 vty_out (vty
, "%% Malformed address\n");
1043 /* Quagga has no convenient prefix constructors. */
1044 snprintf(buf
, sizeof(buf
), "%s/%d",
1045 inet_ntop(AF_INET
, &addr
, buf1
, sizeof(buf1
)), 32);
1047 ret
= str2prefix(buf
, &prefix
);
1049 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1053 routes
= route_stream(0);
1056 struct babel_route
*route
= route_stream_next(routes
);
1059 show_babel_routes_sub(route
, vty
, &prefix
);
1061 route_stream_done(routes
);
1063 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1065 xroutes
= xroute_stream();
1068 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1071 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1073 xroute_stream_done(xroutes
);
1075 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1080 DEFUN (show_babel_route_addr6
,
1081 show_babel_route_addr6_cmd
,
1082 "show babel route X:X::X:X",
1084 "Babel information\n"
1085 "Babel internal routing table\n"
1086 "IPv6 address <network>/<length>\n")
1088 struct in6_addr addr
;
1089 char buf1
[INET6_ADDRSTRLEN
];
1090 char buf
[INET6_ADDRSTRLEN
+ 8];
1091 struct route_stream
*routes
= NULL
;
1092 struct xroute_stream
*xroutes
= NULL
;
1093 struct prefix prefix
;
1096 ret
= inet_pton (AF_INET6
, argv
[3]->arg
, &addr
);
1098 vty_out (vty
, "%% Malformed address\n");
1102 /* Quagga has no convenient prefix constructors. */
1103 snprintf(buf
, sizeof(buf
), "%s/%d",
1104 inet_ntop(AF_INET6
, &addr
, buf1
, sizeof(buf1
)), 128);
1106 ret
= str2prefix(buf
, &prefix
);
1108 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1112 routes
= route_stream(0);
1115 struct babel_route
*route
= route_stream_next(routes
);
1118 show_babel_routes_sub(route
, vty
, &prefix
);
1120 route_stream_done(routes
);
1122 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1124 xroutes
= xroute_stream();
1127 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1130 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1132 xroute_stream_done(xroutes
);
1134 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1139 DEFUN (show_babel_parameters
,
1140 show_babel_parameters_cmd
,
1141 "show babel parameters",
1143 "Babel information\n"
1144 "Configuration information\n")
1146 struct babel
*babel_ctx
;
1148 vty_out (vty
, " -- Babel running configuration --\n");
1149 show_babel_main_configuration(vty
);
1151 babel_ctx
= babel_lookup();
1153 vty_out (vty
, " -- distribution lists --\n");
1154 config_show_distribute(vty
, babel_ctx
->distribute_ctx
);
1162 /* initialize interface list */
1163 hook_register_prio(if_add
, 0, babel_if_new_hook
);
1164 hook_register_prio(if_del
, 0, babel_if_delete_hook
);
1166 babel_enable_if
= vector_init (1);
1168 /* install interface node and commands */
1169 if_cmd_init(interface_config_write
);
1171 install_element(BABEL_NODE
, &babel_network_cmd
);
1172 install_element(BABEL_NODE
, &no_babel_network_cmd
);
1173 install_element(INTERFACE_NODE
, &babel_split_horizon_cmd
);
1174 install_element(INTERFACE_NODE
, &babel_set_wired_cmd
);
1175 install_element(INTERFACE_NODE
, &babel_set_wireless_cmd
);
1176 install_element(INTERFACE_NODE
, &babel_set_hello_interval_cmd
);
1177 install_element(INTERFACE_NODE
, &babel_set_update_interval_cmd
);
1178 install_element(INTERFACE_NODE
, &babel_set_rxcost_cmd
);
1179 install_element(INTERFACE_NODE
, &babel_set_channel_cmd
);
1180 install_element(INTERFACE_NODE
, &babel_set_rtt_decay_cmd
);
1181 install_element(INTERFACE_NODE
, &babel_set_rtt_min_cmd
);
1182 install_element(INTERFACE_NODE
, &babel_set_rtt_max_cmd
);
1183 install_element(INTERFACE_NODE
, &babel_set_max_rtt_penalty_cmd
);
1184 install_element(INTERFACE_NODE
, &babel_set_enable_timestamps_cmd
);
1186 /* "show babel ..." commands */
1187 install_element(VIEW_NODE
, &show_babel_interface_cmd
);
1188 install_element(VIEW_NODE
, &show_babel_neighbour_cmd
);
1189 install_element(VIEW_NODE
, &show_babel_route_cmd
);
1190 install_element(VIEW_NODE
, &show_babel_route_prefix_cmd
);
1191 install_element(VIEW_NODE
, &show_babel_route_addr_cmd
);
1192 install_element(VIEW_NODE
, &show_babel_route_addr6_cmd
);
1193 install_element(VIEW_NODE
, &show_babel_parameters_cmd
);
1196 /* hooks: functions called respectively when struct interface is
1197 created or deleted. */
1199 babel_if_new_hook (struct interface
*ifp
)
1201 ifp
->info
= babel_interface_allocate();
1206 babel_if_delete_hook (struct interface
*ifp
)
1208 babel_interface_free(ifp
->info
);
1213 /* Output an "interface" section for each of the known interfaces with
1214 babeld-specific statement lines where appropriate. */
1216 interface_config_write (struct vty
*vty
)
1218 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1219 struct interface
*ifp
;
1222 FOR_ALL_INTERFACES (vrf
, ifp
) {
1223 if_vty_config_start(vty
, ifp
);
1225 vty_out (vty
, " description %s\n",ifp
->desc
);
1226 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo (ifp
);
1227 /* wireless is the default*/
1228 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
))
1230 vty_out (vty
, " babel wired\n");
1233 if (babel_ifp
->hello_interval
!= BABEL_DEFAULT_HELLO_INTERVAL
)
1235 vty_out (vty
, " babel hello-interval %u\n",
1236 babel_ifp
->hello_interval
);
1239 if (babel_ifp
->update_interval
!= BABEL_DEFAULT_UPDATE_INTERVAL
)
1241 vty_out (vty
, " babel update-interval %u\n",
1242 babel_ifp
->update_interval
);
1245 if (CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
)) {
1246 vty_out(vty
, " babel enable-timestamps\n");
1249 if (babel_ifp
->max_rtt_penalty
!= BABEL_DEFAULT_MAX_RTT_PENALTY
) {
1250 vty_out(vty
, " babel max-rtt-penalty %u\n",
1251 babel_ifp
->max_rtt_penalty
);
1254 if (babel_ifp
->rtt_decay
!= BABEL_DEFAULT_RTT_DECAY
) {
1255 vty_out(vty
, " babel rtt-decay %u\n", babel_ifp
->rtt_decay
);
1258 if (babel_ifp
->rtt_min
!= BABEL_DEFAULT_RTT_MIN
) {
1259 vty_out(vty
, " babel rtt-min %u\n", babel_ifp
->rtt_min
/ 1000);
1262 if (babel_ifp
->rtt_max
!= BABEL_DEFAULT_RTT_MAX
) {
1263 vty_out(vty
, " babel rtt-max %u\n", babel_ifp
->rtt_max
/ 1000);
1266 /* Some parameters have different defaults for wired/wireless. */
1267 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
)) {
1268 if (!CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1269 vty_out (vty
, " no babel split-horizon\n");
1272 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRED
) {
1273 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1276 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_INTERFERING
) {
1277 vty_out (vty
, " babel channel interfering\n");
1279 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_NONINTERFERING
) {
1280 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1284 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1285 vty_out (vty
, " babel split-horizon\n");
1288 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRELESS
) {
1289 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1292 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_NONINTERFERING
) {
1293 vty_out (vty
, " babel channel noninterfering\n");
1295 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_INTERFERING
) {
1296 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1300 if_vty_config_end(vty
);
1306 /* Output a "network" statement line for each of the enabled interfaces. */
1308 babel_enable_if_config_write (struct vty
* vty
)
1310 unsigned int i
, lines
= 0;
1313 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
1314 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
1316 vty_out (vty
, " network %s\n", str
);
1322 /* functions to allocate or free memory for a babel_interface_nfo, filling
1324 static babel_interface_nfo
*
1325 babel_interface_allocate (void)
1327 babel_interface_nfo
*babel_ifp
;
1328 babel_ifp
= XCALLOC(MTYPE_BABEL_IF
, sizeof(babel_interface_nfo
));
1329 /* All flags are unset */
1330 babel_ifp
->bucket_time
= babel_now
.tv_sec
;
1331 babel_ifp
->bucket
= BUCKET_TOKENS_MAX
;
1332 babel_ifp
->hello_seqno
= (frr_weak_random() & 0xFFFF);
1333 babel_ifp
->rtt_decay
= BABEL_DEFAULT_RTT_DECAY
;
1334 babel_ifp
->rtt_min
= BABEL_DEFAULT_RTT_MIN
;
1335 babel_ifp
->rtt_max
= BABEL_DEFAULT_RTT_MAX
;
1336 babel_ifp
->max_rtt_penalty
= BABEL_DEFAULT_MAX_RTT_PENALTY
;
1337 babel_ifp
->hello_interval
= BABEL_DEFAULT_HELLO_INTERVAL
;
1338 babel_ifp
->update_interval
= BABEL_DEFAULT_UPDATE_INTERVAL
;
1339 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
1340 babel_set_wired_internal(babel_ifp
, 0);
1346 babel_interface_free (babel_interface_nfo
*babel_ifp
)
1348 XFREE(MTYPE_BABEL_IF
, babel_ifp
);