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 a 'interface up'");
71 interface_recalculate(ifp
);
76 babel_ifp_down(struct interface
*ifp
)
78 debugf(BABEL_DEBUG_IF
, "receive a 'interface down'");
88 int babel_ifp_create (struct interface
*ifp
)
90 debugf(BABEL_DEBUG_IF
, "receive a 'interface add'");
92 interface_recalculate(ifp
);
98 babel_ifp_destroy(struct interface
*ifp
)
100 debugf(BABEL_DEBUG_IF
, "receive a '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 a '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 a '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 babel_ifp
->flags
|= BABEL_IF_WIRED
;
299 babel_ifp
->flags
|= BABEL_IF_SPLIT_HORIZON
;
300 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRED
;
301 babel_ifp
->channel
= BABEL_IF_CHANNEL_NONINTERFERING
;
302 babel_ifp
->flags
&= ~BABEL_IF_LQ
;
304 babel_ifp
->flags
&= ~BABEL_IF_WIRED
;
305 babel_ifp
->flags
&= ~BABEL_IF_SPLIT_HORIZON
;
306 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRELESS
;
307 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
308 babel_ifp
->flags
|= BABEL_IF_LQ
;
313 /* [Interface Command] Tell the interface is wire. */
314 DEFPY (babel_set_wired
,
318 "Babel interface commands\n"
319 "Enable wired optimizations\n")
321 VTY_DECLVAR_CONTEXT(interface
, ifp
);
322 babel_interface_nfo
*babel_ifp
;
324 babel_ifp
= babel_get_if_nfo(ifp
);
326 assert (babel_ifp
!= NULL
);
327 babel_set_wired_internal(babel_ifp
, no
? 0 : 1);
331 /* [Interface Command] Tell the interface is wireless (default). */
332 DEFPY (babel_set_wireless
,
333 babel_set_wireless_cmd
,
334 "[no] babel wireless",
336 "Babel interface commands\n"
337 "Disable wired optimizations (assume wireless)\n")
339 VTY_DECLVAR_CONTEXT(interface
, ifp
);
340 babel_interface_nfo
*babel_ifp
;
342 babel_ifp
= babel_get_if_nfo(ifp
);
344 assert (babel_ifp
!= NULL
);
345 babel_set_wired_internal(babel_ifp
, no
? 1 : 0);
349 /* [Interface Command] Enable split horizon. */
350 DEFPY (babel_split_horizon
,
351 babel_split_horizon_cmd
,
352 "[no] babel split-horizon",
354 "Babel interface commands\n"
355 "Enable split horizon processing\n")
357 VTY_DECLVAR_CONTEXT(interface
, ifp
);
358 babel_interface_nfo
*babel_ifp
;
360 babel_ifp
= babel_get_if_nfo(ifp
);
362 assert (babel_ifp
!= NULL
);
364 SET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
366 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
);
370 /* [Interface Command]. */
371 DEFPY (babel_set_hello_interval
,
372 babel_set_hello_interval_cmd
,
373 "[no] babel hello-interval (20-655340)",
375 "Babel interface commands\n"
376 "Time between scheduled hellos\n"
379 VTY_DECLVAR_CONTEXT(interface
, ifp
);
380 babel_interface_nfo
*babel_ifp
;
382 babel_ifp
= babel_get_if_nfo(ifp
);
383 assert (babel_ifp
!= NULL
);
385 babel_ifp
->hello_interval
= no
?
386 BABEL_DEFAULT_HELLO_INTERVAL
: hello_interval
;
390 /* [Interface Command]. */
391 DEFPY (babel_set_update_interval
,
392 babel_set_update_interval_cmd
,
393 "[no] babel update-interval (20-655340)",
395 "Babel interface commands\n"
396 "Time between scheduled updates\n"
399 VTY_DECLVAR_CONTEXT(interface
, ifp
);
400 babel_interface_nfo
*babel_ifp
;
402 babel_ifp
= babel_get_if_nfo(ifp
);
403 assert (babel_ifp
!= NULL
);
405 babel_ifp
->update_interval
= no
?
406 BABEL_DEFAULT_UPDATE_INTERVAL
: update_interval
;
410 DEFPY (babel_set_rxcost
,
411 babel_set_rxcost_cmd
,
412 "[no] babel rxcost (1-65534)",
414 "Babel interface commands\n"
415 "Rxcost multiplier\n"
418 VTY_DECLVAR_CONTEXT(interface
, ifp
);
419 babel_interface_nfo
*babel_ifp
;
421 babel_ifp
= babel_get_if_nfo(ifp
);
422 assert (babel_ifp
!= NULL
);
425 rxcost
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
426 BABEL_DEFAULT_RXCOST_WIRED
: BABEL_DEFAULT_RXCOST_WIRELESS
;
428 babel_ifp
->cost
= rxcost
;
432 DEFPY (babel_set_rtt_decay
,
433 babel_set_rtt_decay_cmd
,
434 "[no] babel rtt-decay (1-256)",
436 "Babel interface commands\n"
437 "Decay factor for exponential moving average of RTT samples\n"
440 VTY_DECLVAR_CONTEXT(interface
, ifp
);
441 babel_interface_nfo
*babel_ifp
;
443 babel_ifp
= babel_get_if_nfo(ifp
);
444 assert (babel_ifp
!= NULL
);
446 babel_ifp
->rtt_decay
= no
? BABEL_DEFAULT_RTT_DECAY
: rtt_decay
;
450 DEFPY (babel_set_rtt_min
,
451 babel_set_rtt_min_cmd
,
452 "[no] babel rtt-min (1-65535)",
454 "Babel interface commands\n"
455 "Minimum RTT starting for increasing cost\n"
458 VTY_DECLVAR_CONTEXT(interface
, ifp
);
459 babel_interface_nfo
*babel_ifp
;
461 babel_ifp
= babel_get_if_nfo(ifp
);
462 assert (babel_ifp
!= NULL
);
464 /* The value is entered in milliseconds but stored as microseconds. */
465 babel_ifp
->rtt_min
= no
? BABEL_DEFAULT_RTT_MIN
: rtt_min
* 1000;
469 DEFPY (babel_set_rtt_max
,
470 babel_set_rtt_max_cmd
,
471 "[no] babel rtt-max (1-65535)",
473 "Babel interface commands\n"
477 VTY_DECLVAR_CONTEXT(interface
, ifp
);
478 babel_interface_nfo
*babel_ifp
;
480 babel_ifp
= babel_get_if_nfo(ifp
);
481 assert (babel_ifp
!= NULL
);
483 /* The value is entered in milliseconds but stored as microseconds. */
484 babel_ifp
->rtt_max
= no
? BABEL_DEFAULT_RTT_MAX
: rtt_max
* 1000;
488 DEFPY (babel_set_max_rtt_penalty
,
489 babel_set_max_rtt_penalty_cmd
,
490 "[no] babel max-rtt-penalty (0-65535)",
492 "Babel interface commands\n"
493 "Maximum additional cost due to RTT\n"
496 VTY_DECLVAR_CONTEXT(interface
, ifp
);
497 babel_interface_nfo
*babel_ifp
;
499 babel_ifp
= babel_get_if_nfo(ifp
);
500 assert (babel_ifp
!= NULL
);
502 babel_ifp
->max_rtt_penalty
= no
?
503 BABEL_DEFAULT_MAX_RTT_PENALTY
: max_rtt_penalty
;
507 DEFPY (babel_set_enable_timestamps
,
508 babel_set_enable_timestamps_cmd
,
509 "[no] babel enable-timestamps",
511 "Babel interface commands\n"
512 "Enable timestamps\n")
514 VTY_DECLVAR_CONTEXT(interface
, ifp
);
515 babel_interface_nfo
*babel_ifp
;
517 babel_ifp
= babel_get_if_nfo(ifp
);
518 assert (babel_ifp
!= NULL
);
520 SET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
522 UNSET_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
);
526 DEFPY (babel_set_channel
,
527 babel_set_channel_cmd
,
528 "[no] babel channel <(1-254)$ch|interfering$interfering|"
529 "noninterfering$noninterfering>",
531 "Babel interface commands\n"
532 "Channel number for diversity routing\n"
534 "Mark channel as interfering\n"
535 "Mark channel as noninterfering\n"
538 VTY_DECLVAR_CONTEXT(interface
, ifp
);
539 babel_interface_nfo
*babel_ifp
;
541 babel_ifp
= babel_get_if_nfo(ifp
);
542 assert (babel_ifp
!= NULL
);
545 ch
= CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ?
546 BABEL_IF_CHANNEL_NONINTERFERING
: BABEL_IF_CHANNEL_INTERFERING
;
547 else if (interfering
)
548 ch
= BABEL_IF_CHANNEL_INTERFERING
;
549 else if (noninterfering
)
550 ch
= BABEL_IF_CHANNEL_NONINTERFERING
;
552 babel_ifp
->channel
= ch
;
556 /* This should be no more than half the hello interval, so that hellos
557 aren't sent late. The result is in milliseconds. */
559 jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
561 unsigned interval
= babel_ifp
->hello_interval
;
563 interval
= MIN(interval
, 100);
565 interval
= MIN(interval
, 4000);
566 return roughly(interval
) / 4;
570 update_jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
572 unsigned interval
= babel_ifp
->hello_interval
;
574 interval
= MIN(interval
, 100);
576 interval
= MIN(interval
, 4000);
577 return roughly(interval
);
580 /* calculate babeld's specific datas of an interface (change when the interface
583 interface_recalculate(struct interface
*ifp
)
585 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
586 unsigned char *tmp
= NULL
;
588 struct ipv6_mreq mreq
;
593 if (!if_is_operative(ifp
) || !CHECK_FLAG(ifp
->flags
, IFF_RUNNING
)) {
594 interface_reset(ifp
);
598 babel_ifp
->flags
|= BABEL_IF_IS_UP
;
600 mtu
= MIN(ifp
->mtu
, ifp
->mtu6
);
602 /* We need to be able to fit at least two messages into a packet,
603 so MTUs below 116 require lower layer fragmentation. */
604 /* In IPv6, the minimum MTU is 1280, and every host must be able
605 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
607 debugf(BABEL_DEBUG_IF
, "Suspiciously low MTU %d on interface %s (%d).",
608 mtu
, ifp
->name
, ifp
->ifindex
);
612 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
613 babel_ifp
->bufsize
= mtu
- 4 - 60;
614 tmp
= babel_ifp
->sendbuf
;
615 babel_ifp
->sendbuf
= realloc(babel_ifp
->sendbuf
, babel_ifp
->bufsize
);
616 if(babel_ifp
->sendbuf
== NULL
) {
617 flog_err(EC_BABEL_MEMORY
, "Couldn't reallocate sendbuf.");
619 babel_ifp
->bufsize
= 0;
624 rc
= resize_receive_buffer(mtu
);
626 zlog_warn("couldn't resize receive buffer for interface %s (%d) (%d bytes).",
627 ifp
->name
, ifp
->ifindex
, mtu
);
629 memset(&mreq
, 0, sizeof(mreq
));
630 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
631 mreq
.ipv6mr_interface
= ifp
->ifindex
;
633 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
634 (char*)&mreq
, sizeof(mreq
));
635 if (rc
< 0 && errno
!= EADDRINUSE
) {
636 flog_err_sys(EC_LIB_SOCKET
,
637 "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
638 ifp
->name
, safe_strerror(errno
));
639 /* This is probably due to a missing link-local address,
640 so down this interface, and wait until the main loop
641 tries to up it again. */
642 interface_reset(ifp
);
646 set_timeout(&babel_ifp
->hello_timeout
, babel_ifp
->hello_interval
);
647 set_timeout(&babel_ifp
->update_timeout
, babel_ifp
->update_interval
);
649 send_request(ifp
, NULL
, 0);
651 update_interface_metric(ifp
);
653 debugf(BABEL_DEBUG_COMMON
,
654 "Upped interface %s (%s, cost=%d, channel=%d%s).",
656 (babel_ifp
->flags
& BABEL_IF_WIRED
) ? "wired" : "wireless",
659 babel_ifp
->ipv4
? ", IPv4" : "");
662 send_update(ifp
, 0, NULL
, 0);
667 /* Reset the interface as it was new: it's not removed from the interface list,
668 and may be considered as a upped interface. */
670 interface_reset(struct interface
*ifp
)
673 struct ipv6_mreq mreq
;
674 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
676 if (!(babel_ifp
->flags
& BABEL_IF_IS_UP
))
679 debugf(BABEL_DEBUG_IF
, "interface reset: %s", ifp
->name
);
680 babel_ifp
->flags
&= ~BABEL_IF_IS_UP
;
682 flush_interface_routes(ifp
, 0);
683 babel_ifp
->buffered
= 0;
684 babel_ifp
->bufsize
= 0;
685 free(babel_ifp
->sendbuf
);
686 babel_ifp
->num_buffered_updates
= 0;
687 babel_ifp
->update_bufsize
= 0;
688 if(babel_ifp
->buffered_updates
)
689 free(babel_ifp
->buffered_updates
);
690 babel_ifp
->buffered_updates
= NULL
;
691 babel_ifp
->sendbuf
= NULL
;
693 if(ifp
->ifindex
> 0) {
694 memset(&mreq
, 0, sizeof(mreq
));
695 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
696 mreq
.ipv6mr_interface
= ifp
->ifindex
;
697 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
698 (char*)&mreq
, sizeof(mreq
));
700 flog_err_sys(EC_LIB_SOCKET
,
701 "setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
702 ifp
->name
, safe_strerror(errno
));
705 update_interface_metric(ifp
);
707 debugf(BABEL_DEBUG_COMMON
,"Upped network %s (%s, cost=%d%s).",
709 (babel_ifp
->flags
& BABEL_IF_WIRED
) ? "wired" : "wireless",
711 babel_ifp
->ipv4
? ", IPv4" : "");
716 /* Send retraction to all, and reset all interfaces statistics. */
718 babel_interface_close_all(void)
720 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
721 struct interface
*ifp
= NULL
;
723 FOR_ALL_INTERFACES(vrf
, ifp
) {
726 send_wildcard_retraction(ifp
);
727 /* Make sure that we expire quickly from our neighbours'
728 association caches. */
729 send_hello_noupdate(ifp
, 10);
731 usleep(roughly(1000));
734 FOR_ALL_INTERFACES(vrf
, ifp
) {
737 /* Make sure they got it. */
738 send_wildcard_retraction(ifp
);
739 send_hello_noupdate(ifp
, 1);
741 usleep(roughly(10000));
743 interface_reset(ifp
);
747 /* return "true" if address is one of our ipv6 addresses */
749 is_interface_ll_address(struct interface
*ifp
, const unsigned char *address
)
751 struct connected
*connected
;
752 struct listnode
*node
;
757 FOR_ALL_INTERFACES_ADDRESSES(ifp
, connected
, node
) {
758 if (connected
->address
->family
== AF_INET6
759 && memcmp(&connected
->address
->u
.prefix6
, address
,
769 show_babel_interface_sub (struct vty
*vty
, struct interface
*ifp
)
772 babel_interface_nfo
*babel_ifp
;
774 vty_out (vty
, "%s is %s\n", ifp
->name
,
775 ((is_up
= if_is_operative(ifp
)) ? "up" : "down"));
776 vty_out (vty
, " ifindex %u, MTU %u bytes %s\n",
777 ifp
->ifindex
, MIN(ifp
->mtu
, ifp
->mtu6
), if_flag_dump(ifp
->flags
));
781 vty_out (vty
, " Babel protocol is not enabled on this interface\n");
787 " Babel protocol is enabled, but not running on this interface\n");
790 babel_ifp
= babel_get_if_nfo (ifp
);
791 vty_out (vty
, " Babel protocol is running on this interface\n");
792 vty_out (vty
, " Operating mode is \"%s\"\n",
793 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless");
794 vty_out (vty
, " Split horizon mode is %s\n",
795 CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
) ? "On" : "Off");
796 vty_out (vty
, " Hello interval is %u ms\n", babel_ifp
->hello_interval
);
797 vty_out (vty
, " Update interval is %u ms\n", babel_ifp
->update_interval
);
798 vty_out (vty
, " Rxcost multiplier is %u\n", babel_ifp
->cost
);
801 DEFUN (show_babel_interface
,
802 show_babel_interface_cmd
,
803 "show babel interface [IFNAME]",
805 "Babel information\n"
806 "Interface information\n"
809 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
810 struct interface
*ifp
;
814 FOR_ALL_INTERFACES (vrf
, ifp
)
815 show_babel_interface_sub (vty
, ifp
);
818 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
820 vty_out (vty
, "No such interface name\n");
823 show_babel_interface_sub (vty
, ifp
);
828 show_babel_neighbour_sub (struct vty
*vty
, struct neighbour
*neigh
)
831 "Neighbour %s dev %s reach %04x rxcost %d txcost %d rtt %s rttcost %d%s.\n",
832 format_address(neigh
->address
),
835 neighbour_rxcost(neigh
),
837 format_thousands(neigh
->rtt
),
838 neighbour_rttcost(neigh
),
839 if_up(neigh
->ifp
) ? "" : " (down)");
842 DEFUN (show_babel_neighbour
,
843 show_babel_neighbour_cmd
,
844 "show babel neighbor [IFNAME]",
846 "Babel information\n"
850 struct neighbour
*neigh
;
851 struct interface
*ifp
;
854 FOR_ALL_NEIGHBOURS(neigh
) {
855 show_babel_neighbour_sub(vty
, neigh
);
859 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
861 vty_out (vty
, "No such interface name\n");
864 FOR_ALL_NEIGHBOURS(neigh
) {
865 if(ifp
->ifindex
== neigh
->ifp
->ifindex
) {
866 show_babel_neighbour_sub(vty
, neigh
);
873 babel_prefix_eq(struct prefix
*prefix
, unsigned char *p
, int plen
)
875 if(prefix
->family
== AF_INET6
) {
876 if (prefix
->prefixlen
!= plen
877 || memcmp(&prefix
->u
.prefix6
, p
, IPV6_MAX_BYTELEN
) != 0)
879 } else if(prefix
->family
== AF_INET
) {
880 if (plen
< 96 || !v4mapped(p
) || prefix
->prefixlen
!= plen
- 96
881 || memcmp(&prefix
->u
.prefix4
, p
+ 12, IPV4_MAX_BYTELEN
) != 0)
891 show_babel_routes_sub(struct babel_route
*route
, struct vty
*vty
,
892 struct prefix
*prefix
)
894 const unsigned char *nexthop
=
895 memcmp(route
->nexthop
, route
->neigh
->address
, IPV6_MAX_BYTELEN
)
902 && !babel_prefix_eq(prefix
, route
->src
->prefix
, route
->src
->plen
))
905 if (route
->channels
[0] == 0)
909 snprintf(channels
, sizeof(channels
), " chan (");
910 j
= strlen(channels
);
911 for (k
= 0; k
< DIVERSITY_HOPS
; k
++) {
912 if (route
->channels
[k
] == 0)
916 snprintf(channels
+ j
, 100 - j
, "%u",
918 j
= strlen(channels
);
920 snprintf(channels
+ j
, 100 - j
, ")");
926 "%s metric %d refmetric %d id %s seqno %d%s age %d via %s neigh %s%s%s%s\n",
927 format_prefix(route
->src
->prefix
, route
->src
->plen
),
928 route_metric(route
), route
->refmetric
,
929 format_eui64(route
->src
->id
),
932 (int)(babel_now
.tv_sec
- route
->time
),
933 route
->neigh
->ifp
->name
,
934 format_address(route
->neigh
->address
),
935 nexthop
? " nexthop " : "",
936 nexthop
? format_address(nexthop
) : "",
937 route
->installed
? " (installed)" : route_feasible(route
) ? " (feasible)" : "");
941 show_babel_xroutes_sub (struct xroute
*xroute
, struct vty
*vty
,
942 struct prefix
*prefix
)
944 if(prefix
&& !babel_prefix_eq(prefix
, xroute
->prefix
, xroute
->plen
))
947 vty_out (vty
, "%s metric %d (exported)\n",
948 format_prefix(xroute
->prefix
, xroute
->plen
),
952 DEFUN (show_babel_route
,
953 show_babel_route_cmd
,
956 "Babel information\n"
957 "Babel internal routing table\n")
959 struct route_stream
*routes
= NULL
;
960 struct xroute_stream
*xroutes
= NULL
;
961 routes
= route_stream(0);
964 struct babel_route
*route
= route_stream_next(routes
);
967 show_babel_routes_sub(route
, vty
, NULL
);
969 route_stream_done(routes
);
971 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
973 xroutes
= xroute_stream();
976 struct xroute
*xroute
= xroute_stream_next(xroutes
);
979 show_babel_xroutes_sub(xroute
, vty
, NULL
);
981 xroute_stream_done(xroutes
);
983 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
988 DEFUN (show_babel_route_prefix
,
989 show_babel_route_prefix_cmd
,
990 "show babel route <A.B.C.D/M|X:X::X:X/M>",
992 "Babel information\n"
993 "Babel internal routing table\n"
994 "IPv4 prefix <network>/<length>\n"
995 "IPv6 prefix <network>/<length>\n")
997 struct route_stream
*routes
= NULL
;
998 struct xroute_stream
*xroutes
= NULL
;
999 struct prefix prefix
;
1002 ret
= str2prefix(argv
[3]->arg
, &prefix
);
1004 vty_out (vty
, "%% Malformed address\n");
1008 routes
= route_stream(0);
1011 struct babel_route
*route
= route_stream_next(routes
);
1014 show_babel_routes_sub(route
, vty
, &prefix
);
1016 route_stream_done(routes
);
1018 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1020 xroutes
= xroute_stream();
1023 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1026 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1028 xroute_stream_done(xroutes
);
1030 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1036 DEFUN (show_babel_route_addr
,
1037 show_babel_route_addr_cmd
,
1038 "show babel route A.B.C.D",
1040 "Babel information\n"
1041 "Babel internal routing table\n"
1042 "IPv4 address <network>/<length>\n")
1044 struct in_addr addr
;
1045 char buf
[INET_ADDRSTRLEN
+ 8];
1046 char buf1
[INET_ADDRSTRLEN
+ 8];
1047 struct route_stream
*routes
= NULL
;
1048 struct xroute_stream
*xroutes
= NULL
;
1049 struct prefix prefix
;
1052 ret
= inet_aton (argv
[3]->arg
, &addr
);
1054 vty_out (vty
, "%% Malformed address\n");
1058 /* Quagga has no convenient prefix constructors. */
1059 snprintf(buf
, sizeof(buf
), "%s/%d",
1060 inet_ntop(AF_INET
, &addr
, buf1
, sizeof(buf1
)), 32);
1062 ret
= str2prefix(buf
, &prefix
);
1064 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1068 routes
= route_stream(0);
1071 struct babel_route
*route
= route_stream_next(routes
);
1074 show_babel_routes_sub(route
, vty
, &prefix
);
1076 route_stream_done(routes
);
1078 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1080 xroutes
= xroute_stream();
1083 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1086 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1088 xroute_stream_done(xroutes
);
1090 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1095 DEFUN (show_babel_route_addr6
,
1096 show_babel_route_addr6_cmd
,
1097 "show babel route X:X::X:X",
1099 "Babel information\n"
1100 "Babel internal routing table\n"
1101 "IPv6 address <network>/<length>\n")
1103 struct in6_addr addr
;
1104 char buf1
[INET6_ADDRSTRLEN
];
1105 char buf
[INET6_ADDRSTRLEN
+ 8];
1106 struct route_stream
*routes
= NULL
;
1107 struct xroute_stream
*xroutes
= NULL
;
1108 struct prefix prefix
;
1111 ret
= inet_pton (AF_INET6
, argv
[3]->arg
, &addr
);
1113 vty_out (vty
, "%% Malformed address\n");
1117 /* Quagga has no convenient prefix constructors. */
1118 snprintf(buf
, sizeof(buf
), "%s/%d",
1119 inet_ntop(AF_INET6
, &addr
, buf1
, sizeof(buf1
)), 128);
1121 ret
= str2prefix(buf
, &prefix
);
1123 vty_out (vty
, "%% Parse error -- this shouldn't happen\n");
1127 routes
= route_stream(0);
1130 struct babel_route
*route
= route_stream_next(routes
);
1133 show_babel_routes_sub(route
, vty
, &prefix
);
1135 route_stream_done(routes
);
1137 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1139 xroutes
= xroute_stream();
1142 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1145 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1147 xroute_stream_done(xroutes
);
1149 flog_err(EC_BABEL_MEMORY
, "Couldn't allocate route stream.");
1154 DEFUN (show_babel_parameters
,
1155 show_babel_parameters_cmd
,
1156 "show babel parameters",
1158 "Babel information\n"
1159 "Configuration information\n")
1161 struct babel
*babel_ctx
;
1163 vty_out (vty
, " -- Babel running configuration --\n");
1164 show_babel_main_configuration(vty
);
1166 babel_ctx
= babel_lookup();
1168 vty_out (vty
, " -- distribution lists --\n");
1169 config_show_distribute(vty
, babel_ctx
->distribute_ctx
);
1177 /* initialize interface list */
1178 hook_register_prio(if_add
, 0, babel_if_new_hook
);
1179 hook_register_prio(if_del
, 0, babel_if_delete_hook
);
1181 babel_enable_if
= vector_init (1);
1183 /* install interface node and commands */
1184 if_cmd_init(interface_config_write
);
1186 install_element(BABEL_NODE
, &babel_network_cmd
);
1187 install_element(BABEL_NODE
, &no_babel_network_cmd
);
1188 install_element(INTERFACE_NODE
, &babel_split_horizon_cmd
);
1189 install_element(INTERFACE_NODE
, &babel_set_wired_cmd
);
1190 install_element(INTERFACE_NODE
, &babel_set_wireless_cmd
);
1191 install_element(INTERFACE_NODE
, &babel_set_hello_interval_cmd
);
1192 install_element(INTERFACE_NODE
, &babel_set_update_interval_cmd
);
1193 install_element(INTERFACE_NODE
, &babel_set_rxcost_cmd
);
1194 install_element(INTERFACE_NODE
, &babel_set_channel_cmd
);
1195 install_element(INTERFACE_NODE
, &babel_set_rtt_decay_cmd
);
1196 install_element(INTERFACE_NODE
, &babel_set_rtt_min_cmd
);
1197 install_element(INTERFACE_NODE
, &babel_set_rtt_max_cmd
);
1198 install_element(INTERFACE_NODE
, &babel_set_max_rtt_penalty_cmd
);
1199 install_element(INTERFACE_NODE
, &babel_set_enable_timestamps_cmd
);
1201 /* "show babel ..." commands */
1202 install_element(VIEW_NODE
, &show_babel_interface_cmd
);
1203 install_element(VIEW_NODE
, &show_babel_neighbour_cmd
);
1204 install_element(VIEW_NODE
, &show_babel_route_cmd
);
1205 install_element(VIEW_NODE
, &show_babel_route_prefix_cmd
);
1206 install_element(VIEW_NODE
, &show_babel_route_addr_cmd
);
1207 install_element(VIEW_NODE
, &show_babel_route_addr6_cmd
);
1208 install_element(VIEW_NODE
, &show_babel_parameters_cmd
);
1211 /* hooks: functions called respectively when struct interface is
1212 created or deleted. */
1214 babel_if_new_hook (struct interface
*ifp
)
1216 ifp
->info
= babel_interface_allocate();
1221 babel_if_delete_hook (struct interface
*ifp
)
1223 babel_interface_free(ifp
->info
);
1228 /* Output an "interface" section for each of the known interfaces with
1229 babeld-specific statement lines where appropriate. */
1231 interface_config_write (struct vty
*vty
)
1233 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1234 struct interface
*ifp
;
1237 FOR_ALL_INTERFACES (vrf
, ifp
) {
1238 if_vty_config_start(vty
, ifp
);
1240 vty_out (vty
, " description %s\n",ifp
->desc
);
1241 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo (ifp
);
1242 /* wireless is the default*/
1243 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
))
1245 vty_out (vty
, " babel wired\n");
1248 if (babel_ifp
->hello_interval
!= BABEL_DEFAULT_HELLO_INTERVAL
)
1250 vty_out (vty
, " babel hello-interval %u\n",
1251 babel_ifp
->hello_interval
);
1254 if (babel_ifp
->update_interval
!= BABEL_DEFAULT_UPDATE_INTERVAL
)
1256 vty_out (vty
, " babel update-interval %u\n",
1257 babel_ifp
->update_interval
);
1260 if (CHECK_FLAG(babel_ifp
->flags
, BABEL_IF_TIMESTAMPS
)) {
1261 vty_out(vty
, " babel enable-timestamps\n");
1264 if (babel_ifp
->max_rtt_penalty
!= BABEL_DEFAULT_MAX_RTT_PENALTY
) {
1265 vty_out(vty
, " babel max-rtt-penalty %u\n",
1266 babel_ifp
->max_rtt_penalty
);
1269 if (babel_ifp
->rtt_decay
!= BABEL_DEFAULT_RTT_DECAY
) {
1270 vty_out(vty
, " babel rtt-decay %u\n", babel_ifp
->rtt_decay
);
1273 if (babel_ifp
->rtt_min
!= BABEL_DEFAULT_RTT_MIN
) {
1274 vty_out(vty
, " babel rtt-min %u\n", babel_ifp
->rtt_min
/ 1000);
1277 if (babel_ifp
->rtt_max
!= BABEL_DEFAULT_RTT_MAX
) {
1278 vty_out(vty
, " babel rtt-max %u\n", babel_ifp
->rtt_max
/ 1000);
1281 /* Some parameters have different defaults for wired/wireless. */
1282 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
)) {
1283 if (!CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1284 vty_out (vty
, " no babel split-horizon\n");
1287 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRED
) {
1288 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1291 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_INTERFERING
) {
1292 vty_out (vty
, " babel channel interfering\n");
1294 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_NONINTERFERING
) {
1295 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1299 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1300 vty_out (vty
, " babel split-horizon\n");
1303 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRELESS
) {
1304 vty_out (vty
, " babel rxcost %u\n", babel_ifp
->cost
);
1307 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_NONINTERFERING
) {
1308 vty_out (vty
, " babel channel noninterfering\n");
1310 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_INTERFERING
) {
1311 vty_out (vty
, " babel channel %d\n",babel_ifp
->channel
);
1315 if_vty_config_end(vty
);
1321 /* Output a "network" statement line for each of the enabled interfaces. */
1323 babel_enable_if_config_write (struct vty
* vty
)
1325 unsigned int i
, lines
= 0;
1328 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
1329 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
1331 vty_out (vty
, " network %s\n", str
);
1337 /* functions to allocate or free memory for a babel_interface_nfo, filling
1339 static babel_interface_nfo
*
1340 babel_interface_allocate (void)
1342 babel_interface_nfo
*babel_ifp
;
1343 babel_ifp
= XCALLOC(MTYPE_BABEL_IF
, sizeof(babel_interface_nfo
));
1344 /* All flags are unset */
1345 babel_ifp
->bucket_time
= babel_now
.tv_sec
;
1346 babel_ifp
->bucket
= BUCKET_TOKENS_MAX
;
1347 babel_ifp
->hello_seqno
= (frr_weak_random() & 0xFFFF);
1348 babel_ifp
->rtt_decay
= BABEL_DEFAULT_RTT_DECAY
;
1349 babel_ifp
->rtt_min
= BABEL_DEFAULT_RTT_MIN
;
1350 babel_ifp
->rtt_max
= BABEL_DEFAULT_RTT_MAX
;
1351 babel_ifp
->max_rtt_penalty
= BABEL_DEFAULT_MAX_RTT_PENALTY
;
1352 babel_ifp
->hello_interval
= BABEL_DEFAULT_HELLO_INTERVAL
;
1353 babel_ifp
->update_interval
= BABEL_DEFAULT_UPDATE_INTERVAL
;
1354 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
1355 babel_set_wired_internal(babel_ifp
, 0);
1361 babel_interface_free (babel_interface_nfo
*babel_ifp
)
1363 XFREE(MTYPE_BABEL_IF
, babel_ifp
);