2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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
29 #include "distribute.h"
30 #include "lib_errors.h"
33 #include "babel_main.h"
36 #include "babel_interface.h"
39 #include "babel_zebra.h"
40 #include "neighbour.h"
43 #include "babel_errors.h"
45 #ifndef VTYSH_EXTRACT_PL
46 #include "babeld/babel_interface_clippy.c"
49 DEFINE_MTYPE_STATIC(BABELD
, BABEL_IF
, "Babel Interface");
51 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
53 static int babel_enable_if_lookup (const char *ifname
);
54 static int babel_enable_if_add (const char *ifname
);
55 static int babel_enable_if_delete (const char *ifname
);
56 static int interface_recalculate(struct interface
*ifp
);
57 static int interface_reset(struct interface
*ifp
);
58 static int babel_if_new_hook (struct interface
*ifp
);
59 static int babel_if_delete_hook (struct interface
*ifp
);
60 static int interface_config_write (struct vty
*vty
);
61 static babel_interface_nfo
* babel_interface_allocate (void);
62 static void babel_interface_free (babel_interface_nfo
*bi
);
65 static vector babel_enable_if
; /* enable interfaces (by cmd). */
67 int babel_ifp_up(struct interface
*ifp
)
69 debugf(BABEL_DEBUG_IF
, "receive an 'interface up'");
71 interface_recalculate(ifp
);
76 babel_ifp_down(struct interface
*ifp
)
78 debugf(BABEL_DEBUG_IF
, "receive an 'interface down'");
88 int babel_ifp_create (struct interface
*ifp
)
90 debugf(BABEL_DEBUG_IF
, "receive an 'interface add'");
92 interface_recalculate(ifp
);
98 babel_ifp_destroy(struct interface
*ifp
)
100 debugf(BABEL_DEBUG_IF
, "receive an 'interface delete'");
103 interface_reset(ifp
);
109 babel_interface_address_add (ZAPI_CALLBACK_ARGS
)
111 babel_interface_nfo
*babel_ifp
;
112 struct connected
*ifc
;
113 struct prefix
*prefix
;
115 debugf(BABEL_DEBUG_IF
, "receive an 'interface address add'");
117 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
118 zclient
->ibuf
, vrf_id
);
123 prefix
= ifc
->address
;
125 if (prefix
->family
== AF_INET
) {
126 flush_interface_routes(ifc
->ifp
, 0);
127 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
128 if (babel_ifp
->ipv4
== NULL
) {
129 babel_ifp
->ipv4
= malloc(4);
130 if (babel_ifp
->ipv4
== NULL
) {
131 flog_err(EC_BABEL_MEMORY
, "not enough memory");
133 memcpy(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, 4);
138 send_request(ifc
->ifp
, NULL
, 0);
139 send_update(ifc
->ifp
, 0, NULL
, 0);
145 babel_interface_address_delete (ZAPI_CALLBACK_ARGS
)
147 babel_interface_nfo
*babel_ifp
;
148 struct connected
*ifc
;
149 struct prefix
*prefix
;
151 debugf(BABEL_DEBUG_IF
, "receive an 'interface address delete'");
153 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
154 zclient
->ibuf
, vrf_id
);
159 prefix
= ifc
->address
;
161 if (prefix
->family
== AF_INET
) {
162 flush_interface_routes(ifc
->ifp
, 0);
163 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
164 if (babel_ifp
->ipv4
!= NULL
165 && memcmp(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, IPV4_MAX_BYTELEN
)
167 free(babel_ifp
->ipv4
);
168 babel_ifp
->ipv4
= NULL
;
172 send_request(ifc
->ifp
, NULL
, 0);
173 send_update(ifc
->ifp
, 0, NULL
, 0);
175 connected_free(&ifc
);
179 /* Lookup function. */
181 babel_enable_if_lookup (const char *ifname
)
186 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
187 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
188 if (strcmp (str
, ifname
) == 0)
193 /* Add interface to babel_enable_if. */
195 babel_enable_if_add (const char *ifname
)
198 struct interface
*ifp
= NULL
;
200 ret
= babel_enable_if_lookup (ifname
);
204 vector_set (babel_enable_if
, strdup (ifname
));
206 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
208 interface_recalculate(ifp
);
213 /* Delete interface from babel_enable_if. */
215 babel_enable_if_delete (const char *ifname
)
217 int babel_enable_if_index
;
219 struct interface
*ifp
= NULL
;
221 babel_enable_if_index
= babel_enable_if_lookup (ifname
);
222 if (babel_enable_if_index
< 0)
225 str
= vector_slot (babel_enable_if
, babel_enable_if_index
);
227 vector_unset (babel_enable_if
, babel_enable_if_index
);
229 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
231 interface_reset(ifp
);
236 /* [Babel Command] Babel enable on specified interface or matched network. */
237 DEFUN (babel_network
,
239 "network IF_OR_ADDR",
240 "Enable Babel protocol on specified interface or network.\n"
241 "Interface or address\n")
246 ret
= str2prefix (argv
[1]->arg
, &p
);
248 /* Given string is: */
249 if (ret
) /* an IPv4 or v6 network */
250 return CMD_ERR_NO_MATCH
; /* not implemented yet */
251 else /* an interface name */
252 ret
= babel_enable_if_add (argv
[1]->arg
);
255 vty_out (vty
, "There is same network configuration %s\n",
263 /* [Babel Command] Babel enable on specified interface or matched network. */
264 DEFUN (no_babel_network
,
265 no_babel_network_cmd
,
266 "no network IF_OR_ADDR",
268 "Disable Babel protocol on specified interface or network.\n"
269 "Interface or address\n")
274 ret
= str2prefix (argv
[2]->arg
, &p
);
276 /* Given string is: */
277 if (ret
) /* an IPv4 or v6 network */
278 return CMD_ERR_NO_MATCH
; /* not implemented yet */
279 else /* an interface name */
280 ret
= babel_enable_if_delete (argv
[2]->arg
);
283 vty_out (vty
, "can't find network %s\n",argv
[2]->arg
);
284 return CMD_WARNING_CONFIG_FAILED
;
290 /* There are a number of interface parameters that must be changed when
291 an interface becomes wired/wireless. In Quagga, they cannot be
292 configured separately. */
295 babel_set_wired_internal(babel_interface_nfo
*babel_ifp
, int wired
)
298 SET_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
);
299 SET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
300 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRED
;
301 babel_ifp
->channel
= BABEL_IF_CHANNEL_NONINTERFERING
;
302 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_LQ
);
305 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
);
306 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
307 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRELESS
;
308 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
309 SET_FLAG(babel_ifp
->flags
, BABEL_IF_LQ
);
314 /* [Interface Command] Tell the interface is wire. */
315 DEFPY (babel_set_wired
,
319 "Babel interface commands\n"
320 "Enable wired optimizations\n")
322 VTY_DECLVAR_CONTEXT(interface
, ifp
);
323 babel_interface_nfo
*babel_ifp
;
325 babel_ifp
= babel_get_if_nfo(ifp
);
327 assert (babel_ifp
!= NULL
);
328 babel_set_wired_internal(babel_ifp
, no
? 0 : 1);
332 /* [Interface Command] Tell the interface is wireless (default). */
333 DEFPY (babel_set_wireless
,
334 babel_set_wireless_cmd
,
335 "[no] babel wireless",
337 "Babel interface commands\n"
338 "Disable wired optimizations (assume wireless)\n")
340 VTY_DECLVAR_CONTEXT(interface
, ifp
);
341 babel_interface_nfo
*babel_ifp
;
343 babel_ifp
= babel_get_if_nfo(ifp
);
345 assert (babel_ifp
!= NULL
);
346 babel_set_wired_internal(babel_ifp
, no
? 1 : 0);
350 /* [Interface Command] Enable split horizon. */
351 DEFPY (babel_split_horizon
,
352 babel_split_horizon_cmd
,
353 "[no] babel split-horizon",
355 "Babel interface commands\n"
356 "Enable split horizon processing\n")
358 VTY_DECLVAR_CONTEXT(interface
, ifp
);
359 babel_interface_nfo
*babel_ifp
;
361 babel_ifp
= babel_get_if_nfo(ifp
);
363 assert (babel_ifp
!= NULL
);
365 SET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
367 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
371 /* [Interface Command]. */
372 DEFPY (babel_set_hello_interval
,
373 babel_set_hello_interval_cmd
,
374 "[no] babel hello-interval (20-655340)",
376 "Babel interface commands\n"
377 "Time between scheduled hellos\n"
380 VTY_DECLVAR_CONTEXT(interface
, ifp
);
381 babel_interface_nfo
*babel_ifp
;
383 babel_ifp
= babel_get_if_nfo(ifp
);
384 assert (babel_ifp
!= NULL
);
386 babel_ifp
->hello_interval
= no
?
387 BABEL_DEFAULT_HELLO_INTERVAL
: hello_interval
;
391 /* [Interface Command]. */
392 DEFPY (babel_set_update_interval
,
393 babel_set_update_interval_cmd
,
394 "[no] babel update-interval (20-655340)",
396 "Babel interface commands\n"
397 "Time between scheduled updates\n"
400 VTY_DECLVAR_CONTEXT(interface
, ifp
);
401 babel_interface_nfo
*babel_ifp
;
403 babel_ifp
= babel_get_if_nfo(ifp
);
404 assert (babel_ifp
!= NULL
);
406 babel_ifp
->update_interval
= no
?
407 BABEL_DEFAULT_UPDATE_INTERVAL
: update_interval
;
411 DEFPY (babel_set_rxcost
,
412 babel_set_rxcost_cmd
,
413 "[no] babel rxcost (1-65534)",
415 "Babel interface commands\n"
416 "Rxcost multiplier\n"
419 VTY_DECLVAR_CONTEXT(interface
, ifp
);
420 babel_interface_nfo
*babel_ifp
;
422 babel_ifp
= babel_get_if_nfo(ifp
);
423 assert (babel_ifp
!= NULL
);
426 rxcost
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
427 BABEL_DEFAULT_RXCOST_WIRED
: BABEL_DEFAULT_RXCOST_WIRELESS
;
429 babel_ifp
->cost
= rxcost
;
433 DEFPY (babel_set_rtt_decay
,
434 babel_set_rtt_decay_cmd
,
435 "[no] babel rtt-decay (1-256)",
437 "Babel interface commands\n"
438 "Decay factor for exponential moving average of RTT samples\n"
441 VTY_DECLVAR_CONTEXT(interface
, ifp
);
442 babel_interface_nfo
*babel_ifp
;
444 babel_ifp
= babel_get_if_nfo(ifp
);
445 assert (babel_ifp
!= NULL
);
447 babel_ifp
->rtt_decay
= no
? BABEL_DEFAULT_RTT_DECAY
: rtt_decay
;
451 DEFPY (babel_set_rtt_min
,
452 babel_set_rtt_min_cmd
,
453 "[no] babel rtt-min (1-65535)",
455 "Babel interface commands\n"
456 "Minimum RTT starting for increasing cost\n"
459 VTY_DECLVAR_CONTEXT(interface
, ifp
);
460 babel_interface_nfo
*babel_ifp
;
462 babel_ifp
= babel_get_if_nfo(ifp
);
463 assert (babel_ifp
!= NULL
);
465 /* The value is entered in milliseconds but stored as microseconds. */
466 babel_ifp
->rtt_min
= no
? BABEL_DEFAULT_RTT_MIN
: rtt_min
* 1000;
470 DEFPY (babel_set_rtt_max
,
471 babel_set_rtt_max_cmd
,
472 "[no] babel rtt-max (1-65535)",
474 "Babel interface commands\n"
478 VTY_DECLVAR_CONTEXT(interface
, ifp
);
479 babel_interface_nfo
*babel_ifp
;
481 babel_ifp
= babel_get_if_nfo(ifp
);
482 assert (babel_ifp
!= NULL
);
484 /* The value is entered in milliseconds but stored as microseconds. */
485 babel_ifp
->rtt_max
= no
? BABEL_DEFAULT_RTT_MAX
: rtt_max
* 1000;
489 DEFPY (babel_set_max_rtt_penalty
,
490 babel_set_max_rtt_penalty_cmd
,
491 "[no] babel max-rtt-penalty (0-65535)",
493 "Babel interface commands\n"
494 "Maximum additional cost due to RTT\n"
497 VTY_DECLVAR_CONTEXT(interface
, ifp
);
498 babel_interface_nfo
*babel_ifp
;
500 babel_ifp
= babel_get_if_nfo(ifp
);
501 assert (babel_ifp
!= NULL
);
503 babel_ifp
->max_rtt_penalty
= no
?
504 BABEL_DEFAULT_MAX_RTT_PENALTY
: max_rtt_penalty
;
508 DEFPY (babel_set_enable_timestamps
,
509 babel_set_enable_timestamps_cmd
,
510 "[no] babel enable-timestamps",
512 "Babel interface commands\n"
513 "Enable timestamps\n")
515 VTY_DECLVAR_CONTEXT(interface
, ifp
);
516 babel_interface_nfo
*babel_ifp
;
518 babel_ifp
= babel_get_if_nfo(ifp
);
519 assert (babel_ifp
!= NULL
);
521 SET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
523 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
527 DEFPY (babel_set_channel
,
528 babel_set_channel_cmd
,
529 "[no] babel channel <(1-254)$ch|interfering$interfering|"
530 "noninterfering$noninterfering>",
532 "Babel interface commands\n"
533 "Channel number for diversity routing\n"
535 "Mark channel as interfering\n"
536 "Mark channel as noninterfering\n"
539 VTY_DECLVAR_CONTEXT(interface
, ifp
);
540 babel_interface_nfo
*babel_ifp
;
542 babel_ifp
= babel_get_if_nfo(ifp
);
543 assert (babel_ifp
!= NULL
);
546 ch
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
547 BABEL_IF_CHANNEL_NONINTERFERING
: BABEL_IF_CHANNEL_INTERFERING
;
548 else if (interfering
)
549 ch
= BABEL_IF_CHANNEL_INTERFERING
;
550 else if (noninterfering
)
551 ch
= BABEL_IF_CHANNEL_NONINTERFERING
;
553 babel_ifp
->channel
= ch
;
557 /* This should be no more than half the hello interval, so that hellos
558 aren't sent late. The result is in milliseconds. */
560 jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
562 unsigned interval
= babel_ifp
->hello_interval
;
564 interval
= MIN(interval
, 100);
566 interval
= MIN(interval
, 4000);
567 return roughly(interval
) / 4;
571 update_jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
573 unsigned interval
= babel_ifp
->hello_interval
;
575 interval
= MIN(interval
, 100);
577 interval
= MIN(interval
, 4000);
578 return roughly(interval
);
581 /* calculate babeld's specific datas of an interface (change when the interface
584 interface_recalculate(struct interface
*ifp
)
586 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
587 unsigned char *tmp
= NULL
;
589 struct ipv6_mreq mreq
;
594 if (!if_is_operative(ifp
) || !CHECK_FLAG(ifp
->flags
, IFF_RUNNING
)) {
595 interface_reset(ifp
);
599 SET_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
);
601 mtu
= MIN(ifp
->mtu
, ifp
->mtu6
);
603 /* We need to be able to fit at least two messages into a packet,
604 so MTUs below 116 require lower layer fragmentation. */
605 /* In IPv6, the minimum MTU is 1280, and every host must be able
606 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
608 debugf(BABEL_DEBUG_IF
, "Suspiciously low MTU %d on interface %s (%d).",
609 mtu
, ifp
->name
, ifp
->ifindex
);
613 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
614 babel_ifp
->bufsize
= mtu
- 4 - 60;
615 tmp
= babel_ifp
->sendbuf
;
616 babel_ifp
->sendbuf
= realloc(babel_ifp
->sendbuf
, babel_ifp
->bufsize
);
617 if(babel_ifp
->sendbuf
== NULL
) {
618 flog_err(EC_BABEL_MEMORY
, "Couldn't reallocate sendbuf.");
620 babel_ifp
->bufsize
= 0;
625 rc
= resize_receive_buffer(mtu
);
627 zlog_warn("couldn't resize receive buffer for interface %s (%d) (%d bytes).",
628 ifp
->name
, ifp
->ifindex
, mtu
);
630 memset(&mreq
, 0, sizeof(mreq
));
631 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
632 mreq
.ipv6mr_interface
= ifp
->ifindex
;
634 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
635 (char*)&mreq
, sizeof(mreq
));
636 if (rc
< 0 && errno
!= EADDRINUSE
) {
637 flog_err_sys(EC_LIB_SOCKET
,
638 "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
639 ifp
->name
, safe_strerror(errno
));
640 /* This is probably due to a missing link-local address,
641 so down this interface, and wait until the main loop
642 tries to up it again. */
643 interface_reset(ifp
);
647 set_timeout(&babel_ifp
->hello_timeout
, babel_ifp
->hello_interval
);
648 set_timeout(&babel_ifp
->update_timeout
, babel_ifp
->update_interval
);
650 send_request(ifp
, NULL
, 0);
652 update_interface_metric(ifp
);
654 debugf(BABEL_DEBUG_COMMON
,
655 "Upped interface %s (%s, cost=%d, channel=%d%s).",
657 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless",
660 babel_ifp
->ipv4
? ", IPv4" : "");
663 send_update(ifp
, 0, NULL
, 0);
668 /* Reset the interface as it was new: it's not removed from the interface list,
669 and may be considered as a upped interface. */
671 interface_reset(struct interface
*ifp
)
674 struct ipv6_mreq mreq
;
675 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
677 if (!CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
))
680 debugf(BABEL_DEBUG_IF
, "interface reset: %s", ifp
->name
);
682 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_IS_UP
);
684 flush_interface_routes(ifp
, 0);
685 babel_ifp
->buffered
= 0;
686 babel_ifp
->bufsize
= 0;
687 free(babel_ifp
->sendbuf
);
688 babel_ifp
->num_buffered_updates
= 0;
689 babel_ifp
->update_bufsize
= 0;
690 if(babel_ifp
->buffered_updates
)
691 free(babel_ifp
->buffered_updates
);
692 babel_ifp
->buffered_updates
= NULL
;
693 babel_ifp
->sendbuf
= NULL
;
695 if(ifp
->ifindex
> 0) {
696 memset(&mreq
, 0, sizeof(mreq
));
697 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
698 mreq
.ipv6mr_interface
= ifp
->ifindex
;
699 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
700 (char*)&mreq
, sizeof(mreq
));
702 flog_err_sys(EC_LIB_SOCKET
,
703 "setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
704 ifp
->name
, safe_strerror(errno
));
707 update_interface_metric(ifp
);
709 debugf(BABEL_DEBUG_COMMON
,"Upped network %s (%s, cost=%d%s).",
711 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless",
713 babel_ifp
->ipv4
? ", IPv4" : "");
718 /* Send retraction to all, and reset all interfaces statistics. */
720 babel_interface_close_all(void)
722 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
723 struct interface
*ifp
= NULL
;
725 FOR_ALL_INTERFACES(vrf
, ifp
) {
728 send_wildcard_retraction(ifp
);
729 /* Make sure that we expire quickly from our neighbours'
730 association caches. */
731 send_hello_noupdate(ifp
, 10);
733 usleep(roughly(1000));
736 FOR_ALL_INTERFACES(vrf
, ifp
) {
739 /* Make sure they got it. */
740 send_wildcard_retraction(ifp
);
741 send_hello_noupdate(ifp
, 1);
743 usleep(roughly(10000));
745 interface_reset(ifp
);
749 /* return "true" if address is one of our ipv6 addresses */
751 is_interface_ll_address(struct interface
*ifp
, const unsigned char *address
)
753 struct connected
*connected
;
754 struct listnode
*node
;
759 FOR_ALL_INTERFACES_ADDRESSES(ifp
, connected
, node
) {
760 if (connected
->address
->family
== AF_INET6
761 && memcmp(&connected
->address
->u
.prefix6
, address
,
771 show_babel_interface_sub (struct vty
*vty
, struct interface
*ifp
)
774 babel_interface_nfo
*babel_ifp
;
776 vty_out (vty
, "%s is %s\n", ifp
->name
,
777 ((is_up
= if_is_operative(ifp
)) ? "up" : "down"));
778 vty_out (vty
, " ifindex %u, MTU %u bytes %s\n",
779 ifp
->ifindex
, MIN(ifp
->mtu
, ifp
->mtu6
), if_flag_dump(ifp
->flags
));
783 vty_out (vty
, " Babel protocol is not enabled on this interface\n");
789 " Babel protocol is enabled, but not running on this interface\n");
792 babel_ifp
= babel_get_if_nfo (ifp
);
793 vty_out (vty
, " Babel protocol is running on this interface\n");
794 vty_out (vty
, " Operating mode is \"%s\"\n",
795 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless");
796 vty_out (vty
, " Split horizon mode is %s\n",
797 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
) ? "On" : "Off");
798 vty_out (vty
, " Hello interval is %u ms\n", babel_ifp
->hello_interval
);
799 vty_out (vty
, " Update interval is %u ms\n", babel_ifp
->update_interval
);
800 vty_out (vty
, " Rxcost multiplier is %u\n", babel_ifp
->cost
);
803 DEFUN (show_babel_interface
,
804 show_babel_interface_cmd
,
805 "show babel interface [IFNAME]",
807 "Babel information\n"
808 "Interface information\n"
811 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
812 struct interface
*ifp
;
816 FOR_ALL_INTERFACES (vrf
, ifp
)
817 show_babel_interface_sub (vty
, ifp
);
820 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
822 vty_out (vty
, "No such interface name\n");
825 show_babel_interface_sub (vty
, ifp
);
830 show_babel_neighbour_sub (struct vty
*vty
, struct neighbour
*neigh
)
833 "Neighbour %s dev %s reach %04x rxcost %d txcost %d rtt %s rttcost %d%s.\n",
834 format_address(neigh
->address
),
837 neighbour_rxcost(neigh
),
839 format_thousands(neigh
->rtt
),
840 neighbour_rttcost(neigh
),
841 if_up(neigh
->ifp
) ? "" : " (down)");
844 DEFUN (show_babel_neighbour
,
845 show_babel_neighbour_cmd
,
846 "show babel neighbor [IFNAME]",
848 "Babel information\n"
852 struct neighbour
*neigh
;
853 struct interface
*ifp
;
856 FOR_ALL_NEIGHBOURS(neigh
) {
857 show_babel_neighbour_sub(vty
, neigh
);
861 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
863 vty_out (vty
, "No such interface name\n");
866 FOR_ALL_NEIGHBOURS(neigh
) {
867 if(ifp
->ifindex
== neigh
->ifp
->ifindex
) {
868 show_babel_neighbour_sub(vty
, neigh
);
875 babel_prefix_eq(struct prefix
*prefix
, unsigned char *p
, int plen
)
877 if(prefix
->family
== AF_INET6
) {
878 if (prefix
->prefixlen
!= plen
879 || memcmp(&prefix
->u
.prefix6
, p
, IPV6_MAX_BYTELEN
) != 0)
881 } else if(prefix
->family
== AF_INET
) {
882 if (plen
< 96 || !v4mapped(p
) || prefix
->prefixlen
!= plen
- 96
883 || memcmp(&prefix
->u
.prefix4
, p
+ 12, IPV4_MAX_BYTELEN
) != 0)
893 show_babel_routes_sub(struct babel_route
*route
, struct vty
*vty
,
894 struct prefix
*prefix
)
896 const unsigned char *nexthop
=
897 memcmp(route
->nexthop
, route
->neigh
->address
, IPV6_MAX_BYTELEN
)
904 && !babel_prefix_eq(prefix
, route
->src
->prefix
, route
->src
->plen
))
907 if (route
->channels
[0] == 0)
911 snprintf(channels
, sizeof(channels
), " chan (");
912 j
= strlen(channels
);
913 for (k
= 0; k
< DIVERSITY_HOPS
; k
++) {
914 if (route
->channels
[k
] == 0)
918 snprintf(channels
+ j
, 100 - j
, "%u",
920 j
= strlen(channels
);
922 snprintf(channels
+ j
, 100 - j
, ")");
928 "%s metric %d refmetric %d id %s seqno %d%s age %d via %s neigh %s%s%s%s\n",
929 format_prefix(route
->src
->prefix
, route
->src
->plen
),
930 route_metric(route
), route
->refmetric
,
931 format_eui64(route
->src
->id
),
934 (int)(babel_now
.tv_sec
- route
->time
),
935 route
->neigh
->ifp
->name
,
936 format_address(route
->neigh
->address
),
937 nexthop
? " nexthop " : "",
938 nexthop
? format_address(nexthop
) : "",
939 route
->installed
? " (installed)" : route_feasible(route
) ? " (feasible)" : "");
943 show_babel_xroutes_sub (struct xroute
*xroute
, struct vty
*vty
,
944 struct prefix
*prefix
)
946 if(prefix
&& !babel_prefix_eq(prefix
, xroute
->prefix
, xroute
->plen
))
949 vty_out (vty
, "%s metric %d (exported)\n",
950 format_prefix(xroute
->prefix
, xroute
->plen
),
954 DEFUN (show_babel_route
,
955 show_babel_route_cmd
,
958 "Babel information\n"
959 "Babel internal routing table\n")
961 struct route_stream
*routes
= NULL
;
962 struct xroute_stream
*xroutes
= NULL
;
963 routes
= route_stream(0);
966 struct babel_route
*route
= route_stream_next(routes
);
969 show_babel_routes_sub(route
, vty
, NULL
);
971 route_stream_done(routes
);
973 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
975 xroutes
= xroute_stream();
978 struct xroute
*xroute
= xroute_stream_next(xroutes
);
981 show_babel_xroutes_sub(xroute
, vty
, NULL
);
983 xroute_stream_done(xroutes
);
985 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
990 DEFUN (show_babel_route_prefix
,
991 show_babel_route_prefix_cmd
,
992 "show babel route <A.B.C.D/M|X:X::X:X/M>",
994 "Babel information\n"
995 "Babel internal routing table\n"
996 "IPv4 prefix <network>/<length>\n"
997 "IPv6 prefix <network>/<length>\n")
999 struct route_stream
*routes
= NULL
;
1000 struct xroute_stream
*xroutes
= NULL
;
1001 struct prefix prefix
;
1004 ret
= str2prefix(argv
[3]->arg
, &prefix
);
1006 vty_out (vty
, "%% Malformed address\n");
1010 routes
= route_stream(0);
1013 struct babel_route
*route
= route_stream_next(routes
);
1016 show_babel_routes_sub(route
, vty
, &prefix
);
1018 route_stream_done(routes
);
1020 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1022 xroutes
= xroute_stream();
1025 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1028 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1030 xroute_stream_done(xroutes
);
1032 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1038 DEFUN (show_babel_route_addr
,
1039 show_babel_route_addr_cmd
,
1040 "show babel route A.B.C.D",
1042 "Babel information\n"
1043 "Babel internal routing table\n"
1044 "IPv4 address <network>/<length>\n")
1046 struct in_addr addr
;
1047 char buf
[INET_ADDRSTRLEN
+ 8];
1048 char buf1
[INET_ADDRSTRLEN
+ 8];
1049 struct route_stream
*routes
= NULL
;
1050 struct xroute_stream
*xroutes
= NULL
;
1051 struct prefix prefix
;
1054 ret
= inet_aton (argv
[3]->arg
, &addr
);
1056 vty_out (vty
, "%% Malformed address\n");
1060 /* Quagga has no convenient prefix constructors. */
1061 snprintf(buf
, sizeof(buf
), "%s/%d",
1062 inet_ntop(AF_INET
, &addr
, buf1
, sizeof(buf1
)), 32);
1064 ret
= str2prefix(buf
, &prefix
);
1066 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1070 routes
= route_stream(0);
1073 struct babel_route
*route
= route_stream_next(routes
);
1076 show_babel_routes_sub(route
, vty
, &prefix
);
1078 route_stream_done(routes
);
1080 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1082 xroutes
= xroute_stream();
1085 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1088 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1090 xroute_stream_done(xroutes
);
1092 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1097 DEFUN (show_babel_route_addr6
,
1098 show_babel_route_addr6_cmd
,
1099 "show babel route X:X::X:X",
1101 "Babel information\n"
1102 "Babel internal routing table\n"
1103 "IPv6 address <network>/<length>\n")
1105 struct in6_addr addr
;
1106 char buf1
[INET6_ADDRSTRLEN
];
1107 char buf
[INET6_ADDRSTRLEN
+ 8];
1108 struct route_stream
*routes
= NULL
;
1109 struct xroute_stream
*xroutes
= NULL
;
1110 struct prefix prefix
;
1113 ret
= inet_pton (AF_INET6
, argv
[3]->arg
, &addr
);
1115 vty_out (vty
, "%% Malformed address\n");
1119 /* Quagga has no convenient prefix constructors. */
1120 snprintf(buf
, sizeof(buf
), "%s/%d",
1121 inet_ntop(AF_INET6
, &addr
, buf1
, sizeof(buf1
)), 128);
1123 ret
= str2prefix(buf
, &prefix
);
1125 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1129 routes
= route_stream(0);
1132 struct babel_route
*route
= route_stream_next(routes
);
1135 show_babel_routes_sub(route
, vty
, &prefix
);
1137 route_stream_done(routes
);
1139 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1141 xroutes
= xroute_stream();
1144 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1147 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1149 xroute_stream_done(xroutes
);
1151 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1156 DEFUN (show_babel_parameters
,
1157 show_babel_parameters_cmd
,
1158 "show babel parameters",
1160 "Babel information\n"
1161 "Configuration information\n")
1163 struct babel
*babel_ctx
;
1165 vty_out (vty
, " -- Babel running configuration --\n");
1166 show_babel_main_configuration(vty
);
1168 babel_ctx
= babel_lookup();
1170 vty_out (vty
, " -- distribution lists --\n");
1171 config_show_distribute(vty
, babel_ctx
->distribute_ctx
);
1179 /* initialize interface list */
1180 hook_register_prio(if_add
, 0, babel_if_new_hook
);
1181 hook_register_prio(if_del
, 0, babel_if_delete_hook
);
1183 babel_enable_if
= vector_init (1);
1185 /* install interface node and commands */
1186 if_cmd_init(interface_config_write
);
1188 install_element(BABEL_NODE
, &babel_network_cmd
);
1189 install_element(BABEL_NODE
, &no_babel_network_cmd
);
1190 install_element(INTERFACE_NODE
, &babel_split_horizon_cmd
);
1191 install_element(INTERFACE_NODE
, &babel_set_wired_cmd
);
1192 install_element(INTERFACE_NODE
, &babel_set_wireless_cmd
);
1193 install_element(INTERFACE_NODE
, &babel_set_hello_interval_cmd
);
1194 install_element(INTERFACE_NODE
, &babel_set_update_interval_cmd
);
1195 install_element(INTERFACE_NODE
, &babel_set_rxcost_cmd
);
1196 install_element(INTERFACE_NODE
, &babel_set_channel_cmd
);
1197 install_element(INTERFACE_NODE
, &babel_set_rtt_decay_cmd
);
1198 install_element(INTERFACE_NODE
, &babel_set_rtt_min_cmd
);
1199 install_element(INTERFACE_NODE
, &babel_set_rtt_max_cmd
);
1200 install_element(INTERFACE_NODE
, &babel_set_max_rtt_penalty_cmd
);
1201 install_element(INTERFACE_NODE
, &babel_set_enable_timestamps_cmd
);
1203 /* "show babel ..." commands */
1204 install_element(VIEW_NODE
, &show_babel_interface_cmd
);
1205 install_element(VIEW_NODE
, &show_babel_neighbour_cmd
);
1206 install_element(VIEW_NODE
, &show_babel_route_cmd
);
1207 install_element(VIEW_NODE
, &show_babel_route_prefix_cmd
);
1208 install_element(VIEW_NODE
, &show_babel_route_addr_cmd
);
1209 install_element(VIEW_NODE
, &show_babel_route_addr6_cmd
);
1210 install_element(VIEW_NODE
, &show_babel_parameters_cmd
);
1213 /* hooks: functions called respectively when struct interface is
1214 created or deleted. */
1216 babel_if_new_hook (struct interface
*ifp
)
1218 ifp
->info
= babel_interface_allocate();
1223 babel_if_delete_hook (struct interface
*ifp
)
1225 babel_interface_free(ifp
->info
);
1230 /* Output an "interface" section for each of the known interfaces with
1231 babeld-specific statement lines where appropriate. */
1233 interface_config_write (struct vty
*vty
)
1235 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1236 struct interface
*ifp
;
1239 FOR_ALL_INTERFACES (vrf
, ifp
) {
1240 if_vty_config_start(vty
, ifp
);
1242 vty_out (vty
, " description %s\n",ifp
->desc
);
1243 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo (ifp
);
1244 /* wireless is the default*/
1245 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
))
1247 vty_out (vty
, " babel wired\n");
1250 if (babel_ifp
->hello_interval
!= BABEL_DEFAULT_HELLO_INTERVAL
)
1252 vty_out (vty
, " babel hello-interval %u\n",
1253 babel_ifp
->hello_interval
);
1256 if (babel_ifp
->update_interval
!= BABEL_DEFAULT_UPDATE_INTERVAL
)
1258 vty_out (vty
, " babel update-interval %u\n",
1259 babel_ifp
->update_interval
);
1262 if (CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
)) {
1263 vty_out(vty
, " babel enable-timestamps\n");
1266 if (babel_ifp
->max_rtt_penalty
!= BABEL_DEFAULT_MAX_RTT_PENALTY
) {
1267 vty_out(vty
, " babel max-rtt-penalty %u\n",
1268 babel_ifp
->max_rtt_penalty
);
1271 if (babel_ifp
->rtt_decay
!= BABEL_DEFAULT_RTT_DECAY
) {
1272 vty_out(vty
, " babel rtt-decay %u\n", babel_ifp
->rtt_decay
);
1275 if (babel_ifp
->rtt_min
!= BABEL_DEFAULT_RTT_MIN
) {
1276 vty_out(vty
, " babel rtt-min %u\n", babel_ifp
->rtt_min
/ 1000);
1279 if (babel_ifp
->rtt_max
!= BABEL_DEFAULT_RTT_MAX
) {
1280 vty_out(vty
, " babel rtt-max %u\n", babel_ifp
->rtt_max
/ 1000);
1283 /* Some parameters have different defaults for wired/wireless. */
1284 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
)) {
1285 if (!CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1286 vty_out (vty
, " no babel split-horizon\n");
1289 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRED
) {
1290 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1293 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_INTERFERING
) {
1294 vty_out (vty
, " babel channel interfering\n");
1296 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_NONINTERFERING
) {
1297 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1301 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1302 vty_out (vty
, " babel split-horizon\n");
1305 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRELESS
) {
1306 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1309 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_NONINTERFERING
) {
1310 vty_out (vty
, " babel channel noninterfering\n");
1312 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_INTERFERING
) {
1313 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1317 if_vty_config_end(vty
);
1323 /* Output a "network" statement line for each of the enabled interfaces. */
1325 babel_enable_if_config_write (struct vty
* vty
)
1327 unsigned int i
, lines
= 0;
1330 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
1331 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
1333 vty_out (vty
, " network %s\n", str
);
1339 /* functions to allocate or free memory for a babel_interface_nfo, filling
1341 static babel_interface_nfo
*
1342 babel_interface_allocate (void)
1344 babel_interface_nfo
*babel_ifp
;
1345 babel_ifp
= XCALLOC(MTYPE_BABEL_IF
, sizeof(babel_interface_nfo
));
1346 /* All flags are unset */
1347 babel_ifp
->bucket_time
= babel_now
.tv_sec
;
1348 babel_ifp
->bucket
= BUCKET_TOKENS_MAX
;
1349 babel_ifp
->hello_seqno
= (frr_weak_random() & 0xFFFF);
1350 babel_ifp
->rtt_decay
= BABEL_DEFAULT_RTT_DECAY
;
1351 babel_ifp
->rtt_min
= BABEL_DEFAULT_RTT_MIN
;
1352 babel_ifp
->rtt_max
= BABEL_DEFAULT_RTT_MAX
;
1353 babel_ifp
->max_rtt_penalty
= BABEL_DEFAULT_MAX_RTT_PENALTY
;
1354 babel_ifp
->hello_interval
= BABEL_DEFAULT_HELLO_INTERVAL
;
1355 babel_ifp
->update_interval
= BABEL_DEFAULT_UPDATE_INTERVAL
;
1356 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
1357 babel_set_wired_internal(babel_ifp
, 0);
1363 babel_interface_free (babel_interface_nfo
*babel_ifp
)
1365 XFREE(MTYPE_BABEL_IF
, babel_ifp
);