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"
31 #include "babel_main.h"
34 #include "babel_interface.h"
37 #include "babel_zebra.h"
38 #include "neighbour.h"
41 #include "babel_memory.h"
43 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
45 static int babel_enable_if_lookup (const char *ifname
);
46 static int babel_enable_if_add (const char *ifname
);
47 static int babel_enable_if_delete (const char *ifname
);
48 static int interface_recalculate(struct interface
*ifp
);
49 static int interface_reset(struct interface
*ifp
);
50 static int babel_if_new_hook (struct interface
*ifp
);
51 static int babel_if_delete_hook (struct interface
*ifp
);
52 static int interface_config_write (struct vty
*vty
);
53 static babel_interface_nfo
* babel_interface_allocate (void);
54 static void babel_interface_free (babel_interface_nfo
*bi
);
57 static vector babel_enable_if
; /* enable interfaces (by cmd). */
58 static struct cmd_node babel_interface_node
= /* babeld's interface node. */
67 babel_interface_up (int cmd
, struct zclient
*client
, zebra_size_t length
, vrf_id_t vrf
)
69 struct stream
*s
= NULL
;
70 struct interface
*ifp
= NULL
;
72 debugf(BABEL_DEBUG_IF
, "receive a 'interface up'");
75 ifp
= zebra_interface_state_read(s
, vrf
); /* it updates iflist */
81 interface_recalculate(ifp
);
86 babel_interface_down (int cmd
, struct zclient
*client
, zebra_size_t length
, vrf_id_t vrf
)
88 struct stream
*s
= NULL
;
89 struct interface
*ifp
= NULL
;
91 debugf(BABEL_DEBUG_IF
, "receive a 'interface down'");
94 ifp
= zebra_interface_state_read(s
, vrf
); /* it updates iflist */
100 interface_reset(ifp
);
105 babel_interface_add (int cmd
, struct zclient
*client
, zebra_size_t length
, vrf_id_t vrf
)
107 struct interface
*ifp
= NULL
;
109 debugf(BABEL_DEBUG_IF
, "receive a 'interface add'");
111 /* read and add the interface in the iflist. */
112 ifp
= zebra_interface_add_read (zclient
->ibuf
, vrf
);
118 interface_recalculate(ifp
);
123 babel_interface_delete (int cmd
, struct zclient
*client
, zebra_size_t length
, vrf_id_t vrf
)
125 struct interface
*ifp
;
128 debugf(BABEL_DEBUG_IF
, "receive a 'interface delete'");
131 ifp
= zebra_interface_state_read(s
, vrf
); /* it updates iflist */
137 interface_reset(ifp
);
139 /* To support pseudo interface do not free interface structure. */
140 /* if_delete(ifp); */
141 ifp
->ifindex
= IFINDEX_INTERNAL
;
147 babel_interface_address_add (int cmd
, struct zclient
*client
,
148 zebra_size_t length
, vrf_id_t vrf
)
150 babel_interface_nfo
*babel_ifp
;
151 struct connected
*ifc
;
152 struct prefix
*prefix
;
154 debugf(BABEL_DEBUG_IF
, "receive a 'interface address add'");
156 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
162 prefix
= ifc
->address
;
164 if (prefix
->family
== AF_INET
) {
165 flush_interface_routes(ifc
->ifp
, 0);
166 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
167 if (babel_ifp
->ipv4
== NULL
) {
168 babel_ifp
->ipv4
= malloc(4);
169 if (babel_ifp
->ipv4
== NULL
) {
170 zlog_err("not einough memory");
172 memcpy(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, 4);
177 send_request(ifc
->ifp
, NULL
, 0);
178 send_update(ifc
->ifp
, 0, NULL
, 0);
184 babel_interface_address_delete (int cmd
, struct zclient
*client
,
185 zebra_size_t length
, vrf_id_t vrf
)
187 babel_interface_nfo
*babel_ifp
;
188 struct connected
*ifc
;
189 struct prefix
*prefix
;
191 debugf(BABEL_DEBUG_IF
, "receive a 'interface address delete'");
193 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
199 prefix
= ifc
->address
;
201 if (prefix
->family
== AF_INET
) {
202 flush_interface_routes(ifc
->ifp
, 0);
203 babel_ifp
= babel_get_if_nfo(ifc
->ifp
);
204 if (babel_ifp
->ipv4
!= NULL
205 && memcmp(babel_ifp
->ipv4
, &prefix
->u
.prefix4
, 4) == 0) {
206 free(babel_ifp
->ipv4
);
207 babel_ifp
->ipv4
= NULL
;
211 send_request(ifc
->ifp
, NULL
, 0);
212 send_update(ifc
->ifp
, 0, NULL
, 0);
217 /* Lookup function. */
219 babel_enable_if_lookup (const char *ifname
)
224 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
225 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
226 if (strcmp (str
, ifname
) == 0)
231 /* Add interface to babel_enable_if. */
233 babel_enable_if_add (const char *ifname
)
236 struct interface
*ifp
= NULL
;
238 ret
= babel_enable_if_lookup (ifname
);
242 vector_set (babel_enable_if
, strdup (ifname
));
244 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
246 interface_recalculate(ifp
);
251 /* Delete interface from babel_enable_if. */
253 babel_enable_if_delete (const char *ifname
)
255 int babel_enable_if_index
;
257 struct interface
*ifp
= NULL
;
259 babel_enable_if_index
= babel_enable_if_lookup (ifname
);
260 if (babel_enable_if_index
< 0)
263 str
= vector_slot (babel_enable_if
, babel_enable_if_index
);
265 vector_unset (babel_enable_if
, babel_enable_if_index
);
267 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
269 interface_reset(ifp
);
274 /* [Babel Command] Babel enable on specified interface or matched network. */
275 DEFUN (babel_network
,
277 "network IF_OR_ADDR",
278 "Enable Babel protocol on specified interface or network.\n"
279 "Interface or address\n")
284 ret
= str2prefix (argv
[1]->arg
, &p
);
286 /* Given string is: */
287 if (ret
) /* an IPv4 or v6 network */
288 return CMD_ERR_NO_MATCH
; /* not implemented yet */
289 else /* an interface name */
290 ret
= babel_enable_if_add (argv
[1]->arg
);
293 vty_out (vty
, "There is same network configuration %s%s", argv
[1]->arg
,
301 /* [Babel Command] Babel enable on specified interface or matched network. */
302 DEFUN (no_babel_network
,
303 no_babel_network_cmd
,
304 "no network IF_OR_ADDR",
306 "Disable Babel protocol on specified interface or network.\n"
307 "Interface or address\n")
312 ret
= str2prefix (argv
[2]->arg
, &p
);
314 /* Given string is: */
315 if (ret
) /* an IPv4 or v6 network */
316 return CMD_ERR_NO_MATCH
; /* not implemented yet */
317 else /* an interface name */
318 ret
= babel_enable_if_delete (argv
[2]->arg
);
321 vty_out (vty
, "can't find network %s%s", argv
[2]->arg
,
329 /* There are a number of interface parameters that must be changed when
330 an interface becomes wired/wireless. In Quagga, they cannot be
331 configured separately. */
334 babel_set_wired_internal(babel_interface_nfo
*babel_ifp
, int wired
)
337 babel_ifp
->flags
|= BABEL_IF_WIRED
;
338 babel_ifp
->flags
|= BABEL_IF_SPLIT_HORIZON
;
339 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRED
;
340 babel_ifp
->channel
= BABEL_IF_CHANNEL_NONINTERFERING
;
341 babel_ifp
->flags
&= ~BABEL_IF_LQ
;
343 babel_ifp
->flags
&= ~BABEL_IF_WIRED
;
344 babel_ifp
->flags
&= ~BABEL_IF_SPLIT_HORIZON
;
345 babel_ifp
->cost
= BABEL_DEFAULT_RXCOST_WIRELESS
;
346 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
347 babel_ifp
->flags
|= BABEL_IF_LQ
;
352 /* [Interface Command] Tell the interface is wire. */
353 DEFUN (babel_set_wired
,
356 "Babel interface commands\n"
357 "Enable wired optimizations\n")
359 VTY_DECLVAR_CONTEXT(interface
, ifp
);
360 babel_interface_nfo
*babel_ifp
;
362 babel_ifp
= babel_get_if_nfo(ifp
);
364 assert (babel_ifp
!= NULL
);
365 babel_set_wired_internal(babel_ifp
, 1);
369 /* [Interface Command] Tell the interface is wireless (default). */
370 DEFUN (babel_set_wireless
,
371 babel_set_wireless_cmd
,
373 "Babel interface commands\n"
374 "Disable wired optimizations (assume wireless)\n")
376 VTY_DECLVAR_CONTEXT(interface
, ifp
);
377 babel_interface_nfo
*babel_ifp
;
379 babel_ifp
= babel_get_if_nfo(ifp
);
381 assert (babel_ifp
!= NULL
);
382 babel_set_wired_internal(babel_ifp
, 0);
386 /* [Interface Command] Enable split horizon. */
387 DEFUN (babel_split_horizon
,
388 babel_split_horizon_cmd
,
389 "babel split-horizon",
390 "Babel interface commands\n"
391 "Enable split horizon processing\n")
393 VTY_DECLVAR_CONTEXT(interface
, ifp
);
394 babel_interface_nfo
*babel_ifp
;
396 babel_ifp
= babel_get_if_nfo(ifp
);
398 assert (babel_ifp
!= NULL
);
399 babel_ifp
->flags
|= BABEL_IF_SPLIT_HORIZON
;
403 /* [Interface Command] Disable split horizon (default). */
404 DEFUN (no_babel_split_horizon
,
405 no_babel_split_horizon_cmd
,
406 "no babel split-horizon",
408 "Babel interface commands\n"
409 "Disable split horizon processing\n")
411 VTY_DECLVAR_CONTEXT(interface
, ifp
);
412 babel_interface_nfo
*babel_ifp
;
414 babel_ifp
= babel_get_if_nfo(ifp
);
416 assert (babel_ifp
!= NULL
);
417 babel_ifp
->flags
&= ~BABEL_IF_SPLIT_HORIZON
;
421 /* [Interface Command]. */
422 DEFUN (babel_set_hello_interval
,
423 babel_set_hello_interval_cmd
,
424 "babel hello-interval (20-655340)",
425 "Babel interface commands\n"
426 "Time between scheduled hellos\n"
429 VTY_DECLVAR_CONTEXT(interface
, ifp
);
430 babel_interface_nfo
*babel_ifp
;
433 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
435 babel_ifp
= babel_get_if_nfo(ifp
);
436 assert (babel_ifp
!= NULL
);
438 babel_ifp
->hello_interval
= interval
;
442 /* [Interface Command]. */
443 DEFUN (babel_set_update_interval
,
444 babel_set_update_interval_cmd
,
445 "babel update-interval (20-655340)",
446 "Babel interface commands\n"
447 "Time between scheduled updates\n"
450 VTY_DECLVAR_CONTEXT(interface
, ifp
);
451 babel_interface_nfo
*babel_ifp
;
454 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
456 babel_ifp
= babel_get_if_nfo(ifp
);
457 assert (babel_ifp
!= NULL
);
459 babel_ifp
->update_interval
= interval
;
463 DEFUN (babel_set_rxcost
,
464 babel_set_rxcost_cmd
,
465 "babel rxcost (1-65534)",
466 "Babel interface commands\n"
467 "Rxcost multiplier\n"
470 VTY_DECLVAR_CONTEXT(interface
, ifp
);
471 babel_interface_nfo
*babel_ifp
;
474 rxcost
= strtoul(argv
[2]->arg
, NULL
, 10);
476 babel_ifp
= babel_get_if_nfo(ifp
);
477 assert (babel_ifp
!= NULL
);
479 babel_ifp
->cost
= rxcost
;
483 DEFUN (babel_set_rtt_decay
,
484 babel_set_rtt_decay_cmd
,
485 "babel rtt-decay (1-256)",
486 "Babel interface commands\n"
487 "Decay factor for exponential moving average of RTT samples\n"
490 VTY_DECLVAR_CONTEXT(interface
, ifp
);
491 babel_interface_nfo
*babel_ifp
;
494 decay
= strtoul(argv
[2]->arg
, NULL
, 10);
496 babel_ifp
= babel_get_if_nfo(ifp
);
497 assert (babel_ifp
!= NULL
);
499 babel_ifp
->rtt_decay
= decay
;
503 DEFUN (babel_set_rtt_min
,
504 babel_set_rtt_min_cmd
,
505 "babel rtt-min (1-65535)",
506 "Babel interface commands\n"
507 "Minimum RTT starting for increasing cost\n"
510 VTY_DECLVAR_CONTEXT(interface
, ifp
);
511 babel_interface_nfo
*babel_ifp
;
514 rtt
= strtoul(argv
[2]->arg
, NULL
, 10);
516 babel_ifp
= babel_get_if_nfo(ifp
);
517 assert (babel_ifp
!= NULL
);
519 babel_ifp
->rtt_min
= rtt
;
523 DEFUN (babel_set_rtt_max
,
524 babel_set_rtt_max_cmd
,
525 "babel rtt-max (1-65535)",
526 "Babel interface commands\n"
530 VTY_DECLVAR_CONTEXT(interface
, ifp
);
531 babel_interface_nfo
*babel_ifp
;
534 rtt
= strtoul(argv
[2]->arg
, NULL
, 10);
536 babel_ifp
= babel_get_if_nfo(ifp
);
537 assert (babel_ifp
!= NULL
);
539 babel_ifp
->rtt_max
= rtt
;
543 DEFUN (babel_set_max_rtt_penalty
,
544 babel_set_max_rtt_penalty_cmd
,
545 "babel max-rtt-penalty (0-65535)",
546 "Babel interface commands\n"
547 "Maximum additional cost due to RTT\n"
550 VTY_DECLVAR_CONTEXT(interface
, ifp
);
551 babel_interface_nfo
*babel_ifp
;
554 penalty
= strtoul(argv
[2]->arg
, NULL
, 10);
556 babel_ifp
= babel_get_if_nfo(ifp
);
557 assert (babel_ifp
!= NULL
);
559 babel_ifp
->max_rtt_penalty
= penalty
;
563 DEFUN (babel_set_enable_timestamps
,
564 babel_set_enable_timestamps_cmd
,
565 "babel enable-timestamps",
566 "Babel interface commands\n"
567 "Enable timestamps\n")
569 VTY_DECLVAR_CONTEXT(interface
, ifp
);
570 babel_interface_nfo
*babel_ifp
;
572 babel_ifp
= babel_get_if_nfo(ifp
);
573 assert (babel_ifp
!= NULL
);
575 babel_ifp
->flags
|= BABEL_IF_TIMESTAMPS
;
579 DEFUN (no_babel_set_enable_timestamps
,
580 no_babel_set_enable_timestamps_cmd
,
581 "no babel enable-timestamps",
583 "Babel interface commands\n"
584 "Disable timestamps\n")
586 VTY_DECLVAR_CONTEXT(interface
, ifp
);
587 babel_interface_nfo
*babel_ifp
;
589 babel_ifp
= babel_get_if_nfo(ifp
);
590 assert (babel_ifp
!= NULL
);
592 babel_ifp
->flags
&= ~BABEL_IF_TIMESTAMPS
;
596 DEFUN (babel_set_channel
,
597 babel_set_channel_cmd
,
598 "babel channel (1-254)",
599 "Babel interface commands\n"
600 "Channel number for diversity routing\n"
603 VTY_DECLVAR_CONTEXT(interface
, ifp
);
604 babel_interface_nfo
*babel_ifp
;
607 channel
= strtoul(argv
[2]->arg
, NULL
, 10);
609 babel_ifp
= babel_get_if_nfo(ifp
);
610 assert (babel_ifp
!= NULL
);
612 babel_ifp
->channel
= channel
;
616 DEFUN (babel_set_channel_interfering
,
617 babel_set_channel_interfering_cmd
,
618 "babel channel interfering",
619 "Babel interface commands\n"
620 "Channel number for diversity routing\n"
621 "Mark channel as interfering\n")
623 VTY_DECLVAR_CONTEXT(interface
, ifp
);
624 babel_interface_nfo
*babel_ifp
;
626 babel_ifp
= babel_get_if_nfo(ifp
);
627 assert (babel_ifp
!= NULL
);
629 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
633 DEFUN (babel_set_channel_noninterfering
,
634 babel_set_channel_noninterfering_cmd
,
635 "babel channel noninterfering",
636 "Babel interface commands\n"
637 "Channel number for diversity routing\n"
638 "Mark channel as noninterfering\n")
640 VTY_DECLVAR_CONTEXT(interface
, ifp
);
641 babel_interface_nfo
*babel_ifp
;
643 babel_ifp
= babel_get_if_nfo(ifp
);
644 assert (babel_ifp
!= NULL
);
646 babel_ifp
->channel
= BABEL_IF_CHANNEL_NONINTERFERING
;
650 /* This should be no more than half the hello interval, so that hellos
651 aren't sent late. The result is in milliseconds. */
653 jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
655 unsigned interval
= babel_ifp
->hello_interval
;
657 interval
= MIN(interval
, 100);
659 interval
= MIN(interval
, 4000);
660 return roughly(interval
) / 4;
664 update_jitter(babel_interface_nfo
*babel_ifp
, int urgent
)
666 unsigned interval
= babel_ifp
->hello_interval
;
668 interval
= MIN(interval
, 100);
670 interval
= MIN(interval
, 4000);
671 return roughly(interval
);
674 /* calculate babeld's specific datas of an interface (change when the interface
677 interface_recalculate(struct interface
*ifp
)
679 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
680 unsigned char *tmp
= NULL
;
682 struct ipv6_mreq mreq
;
687 if (!if_is_operative(ifp
) || !CHECK_FLAG(ifp
->flags
, IFF_RUNNING
)) {
688 interface_reset(ifp
);
692 babel_ifp
->flags
|= BABEL_IF_IS_UP
;
694 mtu
= MIN(ifp
->mtu
, ifp
->mtu6
);
696 /* We need to be able to fit at least two messages into a packet,
697 so MTUs below 116 require lower layer fragmentation. */
698 /* In IPv6, the minimum MTU is 1280, and every host must be able
699 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
701 debugf(BABEL_DEBUG_IF
, "Suspiciously low MTU %d on interface %s (%d).",
702 mtu
, ifp
->name
, ifp
->ifindex
);
706 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
707 babel_ifp
->bufsize
= mtu
- 4 - 60;
708 tmp
= babel_ifp
->sendbuf
;
709 babel_ifp
->sendbuf
= realloc(babel_ifp
->sendbuf
, babel_ifp
->bufsize
);
710 if(babel_ifp
->sendbuf
== NULL
) {
711 zlog_err("Couldn't reallocate sendbuf.");
713 babel_ifp
->bufsize
= 0;
718 rc
= resize_receive_buffer(mtu
);
720 zlog_warn("couldn't resize "
721 "receive buffer for interface %s (%d) (%d bytes).\n",
722 ifp
->name
, ifp
->ifindex
, mtu
);
724 memset(&mreq
, 0, sizeof(mreq
));
725 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
726 mreq
.ipv6mr_interface
= ifp
->ifindex
;
728 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
729 (char*)&mreq
, sizeof(mreq
));
731 zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
732 ifp
->name
, safe_strerror(errno
));
733 /* This is probably due to a missing link-local address,
734 so down this interface, and wait until the main loop
735 tries to up it again. */
736 interface_reset(ifp
);
740 set_timeout(&babel_ifp
->hello_timeout
, babel_ifp
->hello_interval
);
741 set_timeout(&babel_ifp
->update_timeout
, babel_ifp
->update_interval
);
743 send_request(ifp
, NULL
, 0);
745 update_interface_metric(ifp
);
747 debugf(BABEL_DEBUG_COMMON
,
748 "Upped interface %s (%s, cost=%d, channel=%d%s).",
750 (babel_ifp
->flags
& BABEL_IF_WIRED
) ? "wired" : "wireless",
753 babel_ifp
->ipv4
? ", IPv4" : "");
756 send_update(ifp
, 0, NULL
, 0);
761 /* Reset the interface as it was new: it's not removed from the interface list,
762 and may be considered as a upped interface. */
764 interface_reset(struct interface
*ifp
)
767 struct ipv6_mreq mreq
;
768 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo(ifp
);
770 if (!(babel_ifp
->flags
& BABEL_IF_IS_UP
))
773 debugf(BABEL_DEBUG_IF
, "interface reset: %s", ifp
->name
);
774 babel_ifp
->flags
&= ~BABEL_IF_IS_UP
;
776 flush_interface_routes(ifp
, 0);
777 babel_ifp
->buffered
= 0;
778 babel_ifp
->bufsize
= 0;
779 free(babel_ifp
->sendbuf
);
780 babel_ifp
->num_buffered_updates
= 0;
781 babel_ifp
->update_bufsize
= 0;
782 if(babel_ifp
->buffered_updates
)
783 free(babel_ifp
->buffered_updates
);
784 babel_ifp
->buffered_updates
= NULL
;
785 babel_ifp
->sendbuf
= NULL
;
787 if(ifp
->ifindex
> 0) {
788 memset(&mreq
, 0, sizeof(mreq
));
789 memcpy(&mreq
.ipv6mr_multiaddr
, protocol_group
, 16);
790 mreq
.ipv6mr_interface
= ifp
->ifindex
;
791 rc
= setsockopt(protocol_socket
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
792 (char*)&mreq
, sizeof(mreq
));
794 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
795 ifp
->name
, safe_strerror(errno
));
798 update_interface_metric(ifp
);
800 debugf(BABEL_DEBUG_COMMON
,"Upped network %s (%s, cost=%d%s).",
802 (babel_ifp
->flags
& BABEL_IF_WIRED
) ? "wired" : "wireless",
804 babel_ifp
->ipv4
? ", IPv4" : "");
809 /* Send retraction to all, and reset all interfaces statistics. */
811 babel_interface_close_all(void)
813 struct interface
*ifp
= NULL
;
814 struct listnode
*linklist_node
= NULL
;
816 FOR_ALL_INTERFACES(ifp
, linklist_node
) {
819 send_wildcard_retraction(ifp
);
820 /* Make sure that we expire quickly from our neighbours'
821 association caches. */
822 send_hello_noupdate(ifp
, 10);
824 usleep(roughly(1000));
827 FOR_ALL_INTERFACES(ifp
, linklist_node
) {
830 /* Make sure they got it. */
831 send_wildcard_retraction(ifp
);
832 send_hello_noupdate(ifp
, 1);
834 usleep(roughly(10000));
836 interface_reset(ifp
);
840 /* return "true" if address is one of our ipv6 addresses */
842 is_interface_ll_address(struct interface
*ifp
, const unsigned char *address
)
844 struct connected
*connected
;
845 struct listnode
*node
;
850 FOR_ALL_INTERFACES_ADDRESSES(ifp
, connected
, node
) {
851 if(connected
->address
->family
== AF_INET6
&&
852 memcmp(&connected
->address
->u
.prefix6
, address
, 16) == 0)
860 show_babel_interface_sub (struct vty
*vty
, struct interface
*ifp
)
863 babel_interface_nfo
*babel_ifp
;
865 vty_out (vty
, "%s is %s%s", ifp
->name
,
866 ((is_up
= if_is_operative(ifp
)) ? "up" : "down"), VTY_NEWLINE
);
867 vty_out (vty
, " ifindex %u, MTU %u bytes %s%s",
868 ifp
->ifindex
, MIN(ifp
->mtu
, ifp
->mtu6
), if_flag_dump(ifp
->flags
), VTY_NEWLINE
);
872 vty_out (vty
, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE
);
877 vty_out (vty
, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE
);
880 babel_ifp
= babel_get_if_nfo (ifp
);
881 vty_out (vty
, " Babel protocol is running on this interface%s", VTY_NEWLINE
);
882 vty_out (vty
, " Operating mode is \"%s\"%s",
883 CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
) ? "wired" : "wireless", VTY_NEWLINE
);
884 vty_out (vty
, " Split horizon mode is %s%s",
885 CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
) ? "On" : "Off", VTY_NEWLINE
);
886 vty_out (vty
, " Hello interval is %u ms%s", babel_ifp
->hello_interval
, VTY_NEWLINE
);
887 vty_out (vty
, " Update interval is %u ms%s", babel_ifp
->update_interval
, VTY_NEWLINE
);
888 vty_out (vty
, " Rxcost multiplier is %u%s", babel_ifp
->cost
, VTY_NEWLINE
);
891 DEFUN (show_babel_interface
,
892 show_babel_interface_cmd
,
893 "show babel interface [IFNAME]",
895 "Babel information\n"
896 "Interface information\n"
899 struct interface
*ifp
;
900 struct listnode
*node
;
904 for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT
), node
, ifp
))
905 show_babel_interface_sub (vty
, ifp
);
908 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
910 vty_out (vty
, "No such interface name%s", VTY_NEWLINE
);
913 show_babel_interface_sub (vty
, ifp
);
918 show_babel_neighbour_sub (struct vty
*vty
, struct neighbour
*neigh
)
921 "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
922 "rtt %s rttcost %d%s.%s",
923 format_address(neigh
->address
),
926 neighbour_rxcost(neigh
),
928 format_thousands(neigh
->rtt
),
929 neighbour_rttcost(neigh
),
930 if_up(neigh
->ifp
) ? "" : " (down)",
934 DEFUN (show_babel_neighbour
,
935 show_babel_neighbour_cmd
,
936 "show babel neighbor [IFNAME]",
938 "Babel information\n"
942 struct neighbour
*neigh
;
943 struct interface
*ifp
;
946 FOR_ALL_NEIGHBOURS(neigh
) {
947 show_babel_neighbour_sub(vty
, neigh
);
951 if ((ifp
= if_lookup_by_name (argv
[3]->arg
, VRF_DEFAULT
)) == NULL
)
953 vty_out (vty
, "No such interface name%s", VTY_NEWLINE
);
956 FOR_ALL_NEIGHBOURS(neigh
) {
957 if(ifp
->ifindex
== neigh
->ifp
->ifindex
) {
958 show_babel_neighbour_sub(vty
, neigh
);
965 babel_prefix_eq(struct prefix
*prefix
, unsigned char *p
, int plen
)
967 if(prefix
->family
== AF_INET6
) {
968 if(prefix
->prefixlen
!= plen
||
969 memcmp(&prefix
->u
.prefix6
, p
, 16) != 0)
971 } else if(prefix
->family
== AF_INET
) {
972 if(plen
< 96 || !v4mapped(p
) || prefix
->prefixlen
!= plen
- 96 ||
973 memcmp(&prefix
->u
.prefix4
, p
+ 12, 4) != 0)
983 show_babel_routes_sub(struct babel_route
*route
, struct vty
*vty
,
984 struct prefix
*prefix
)
986 const unsigned char *nexthop
=
987 memcmp(route
->nexthop
, route
->neigh
->address
, 16) == 0 ?
988 NULL
: route
->nexthop
;
991 if(prefix
&& !babel_prefix_eq(prefix
, route
->src
->prefix
, route
->src
->plen
))
994 if(route
->channels
[0] == 0)
998 snprintf(channels
, 100, " chan (");
999 j
= strlen(channels
);
1000 for(k
= 0; k
< DIVERSITY_HOPS
; k
++) {
1001 if(route
->channels
[k
] == 0)
1004 channels
[j
++] = ',';
1005 snprintf(channels
+ j
, 100 - j
, "%d", route
->channels
[k
]);
1006 j
= strlen(channels
);
1008 snprintf(channels
+ j
, 100 - j
, ")");
1014 "%s metric %d refmetric %d id %s seqno %d%s age %d "
1015 "via %s neigh %s%s%s%s%s",
1016 format_prefix(route
->src
->prefix
, route
->src
->plen
),
1017 route_metric(route
), route
->refmetric
,
1018 format_eui64(route
->src
->id
),
1021 (int)(babel_now
.tv_sec
- route
->time
),
1022 route
->neigh
->ifp
->name
,
1023 format_address(route
->neigh
->address
),
1024 nexthop
? " nexthop " : "",
1025 nexthop
? format_address(nexthop
) : "",
1026 route
->installed
? " (installed)" :
1027 route_feasible(route
) ? " (feasible)" : "",
1032 show_babel_xroutes_sub (struct xroute
*xroute
, struct vty
*vty
,
1033 struct prefix
*prefix
)
1035 if(prefix
&& !babel_prefix_eq(prefix
, xroute
->prefix
, xroute
->plen
))
1038 vty_out(vty
, "%s metric %d (exported)%s",
1039 format_prefix(xroute
->prefix
, xroute
->plen
),
1044 DEFUN (show_babel_route
,
1045 show_babel_route_cmd
,
1048 "Babel information\n"
1049 "Babel internal routing table\n")
1051 struct route_stream
*routes
= NULL
;
1052 struct xroute_stream
*xroutes
= NULL
;
1053 routes
= route_stream(0);
1056 struct babel_route
*route
= route_stream_next(routes
);
1059 show_babel_routes_sub(route
, vty
, NULL
);
1061 route_stream_done(routes
);
1063 zlog_err("Couldn't allocate route stream.");
1065 xroutes
= xroute_stream();
1068 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1071 show_babel_xroutes_sub(xroute
, vty
, NULL
);
1073 xroute_stream_done(xroutes
);
1075 zlog_err("Couldn't allocate route stream.");
1080 DEFUN (show_babel_route_prefix
,
1081 show_babel_route_prefix_cmd
,
1082 "show babel route <A.B.C.D/M|X:X::X:X/M>",
1084 "Babel information\n"
1085 "Babel internal routing table\n"
1086 "IPv4 prefix <network>/<length>\n"
1087 "IPv6 prefix <network>/<length>\n")
1089 struct route_stream
*routes
= NULL
;
1090 struct xroute_stream
*xroutes
= NULL
;
1091 struct prefix prefix
;
1094 ret
= str2prefix(argv
[3]->arg
, &prefix
);
1096 vty_out (vty
, "%% Malformed address%s", VTY_NEWLINE
);
1100 routes
= route_stream(0);
1103 struct babel_route
*route
= route_stream_next(routes
);
1106 show_babel_routes_sub(route
, vty
, &prefix
);
1108 route_stream_done(routes
);
1110 zlog_err("Couldn't allocate route stream.");
1112 xroutes
= xroute_stream();
1115 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1118 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1120 xroute_stream_done(xroutes
);
1122 zlog_err("Couldn't allocate route stream.");
1128 DEFUN (show_babel_route_addr
,
1129 show_babel_route_addr_cmd
,
1130 "show babel route A.B.C.D",
1132 "Babel information\n"
1133 "Babel internal routing table\n"
1134 "IPv4 address <network>/<length>\n")
1136 struct in_addr addr
;
1137 char buf
[INET_ADDRSTRLEN
+ 8];
1138 struct route_stream
*routes
= NULL
;
1139 struct xroute_stream
*xroutes
= NULL
;
1140 struct prefix prefix
;
1143 ret
= inet_aton (argv
[3]->arg
, &addr
);
1145 vty_out (vty
, "%% Malformed address%s", VTY_NEWLINE
);
1149 /* Quagga has no convenient prefix constructors. */
1150 snprintf(buf
, sizeof(buf
), "%s/%d", inet_ntoa(addr
), 32);
1152 ret
= str2prefix(buf
, &prefix
);
1154 vty_out (vty
, "%% Parse error -- this shouldn't happen%s", VTY_NEWLINE
);
1158 routes
= route_stream(0);
1161 struct babel_route
*route
= route_stream_next(routes
);
1164 show_babel_routes_sub(route
, vty
, &prefix
);
1166 route_stream_done(routes
);
1168 zlog_err("Couldn't allocate route stream.");
1170 xroutes
= xroute_stream();
1173 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1176 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1178 xroute_stream_done(xroutes
);
1180 zlog_err("Couldn't allocate route stream.");
1185 DEFUN (show_babel_route_addr6
,
1186 show_babel_route_addr6_cmd
,
1187 "show babel route X:X::X:X",
1189 "Babel information\n"
1190 "Babel internal routing table\n"
1191 "IPv6 address <network>/<length>\n")
1193 struct in6_addr addr
;
1194 char buf1
[INET6_ADDRSTRLEN
];
1195 char buf
[INET6_ADDRSTRLEN
+ 8];
1196 struct route_stream
*routes
= NULL
;
1197 struct xroute_stream
*xroutes
= NULL
;
1198 struct prefix prefix
;
1201 ret
= inet_pton (AF_INET6
, argv
[3]->arg
, &addr
);
1203 vty_out (vty
, "%% Malformed address%s", VTY_NEWLINE
);
1207 /* Quagga has no convenient prefix constructors. */
1208 snprintf(buf
, sizeof(buf
), "%s/%d",
1209 inet_ntop(AF_INET6
, &addr
, buf1
, sizeof(buf1
)), 128);
1211 ret
= str2prefix(buf
, &prefix
);
1213 vty_out (vty
, "%% Parse error -- this shouldn't happen%s", VTY_NEWLINE
);
1217 routes
= route_stream(0);
1220 struct babel_route
*route
= route_stream_next(routes
);
1223 show_babel_routes_sub(route
, vty
, &prefix
);
1225 route_stream_done(routes
);
1227 zlog_err("Couldn't allocate route stream.");
1229 xroutes
= xroute_stream();
1232 struct xroute
*xroute
= xroute_stream_next(xroutes
);
1235 show_babel_xroutes_sub(xroute
, vty
, &prefix
);
1237 xroute_stream_done(xroutes
);
1239 zlog_err("Couldn't allocate route stream.");
1244 DEFUN (show_babel_parameters
,
1245 show_babel_parameters_cmd
,
1246 "show babel parameters",
1248 "Babel information\n"
1249 "Configuration information\n")
1251 vty_out(vty
, " -- Babel running configuration --%s", VTY_NEWLINE
);
1252 show_babel_main_configuration(vty
);
1253 vty_out(vty
, " -- distribution lists --%s", VTY_NEWLINE
);
1254 config_show_distribute(vty
);
1262 /* initialize interface list */
1263 if_add_hook (IF_NEW_HOOK
, babel_if_new_hook
);
1264 if_add_hook (IF_DELETE_HOOK
, babel_if_delete_hook
);
1266 babel_enable_if
= vector_init (1);
1268 /* install interface node and commands */
1269 install_node (&babel_interface_node
, interface_config_write
);
1272 install_element(BABEL_NODE
, &babel_network_cmd
);
1273 install_element(BABEL_NODE
, &no_babel_network_cmd
);
1274 install_element(INTERFACE_NODE
, &babel_split_horizon_cmd
);
1275 install_element(INTERFACE_NODE
, &no_babel_split_horizon_cmd
);
1276 install_element(INTERFACE_NODE
, &babel_set_wired_cmd
);
1277 install_element(INTERFACE_NODE
, &babel_set_wireless_cmd
);
1278 install_element(INTERFACE_NODE
, &babel_set_hello_interval_cmd
);
1279 install_element(INTERFACE_NODE
, &babel_set_update_interval_cmd
);
1280 install_element(INTERFACE_NODE
, &babel_set_rxcost_cmd
);
1281 install_element(INTERFACE_NODE
, &babel_set_channel_cmd
);
1282 install_element(INTERFACE_NODE
, &babel_set_rtt_decay_cmd
);
1283 install_element(INTERFACE_NODE
, &babel_set_rtt_min_cmd
);
1284 install_element(INTERFACE_NODE
, &babel_set_rtt_max_cmd
);
1285 install_element(INTERFACE_NODE
, &babel_set_max_rtt_penalty_cmd
);
1286 install_element(INTERFACE_NODE
, &babel_set_enable_timestamps_cmd
);
1287 install_element(INTERFACE_NODE
, &no_babel_set_enable_timestamps_cmd
);
1288 install_element(INTERFACE_NODE
, &babel_set_channel_interfering_cmd
);
1289 install_element(INTERFACE_NODE
, &babel_set_channel_noninterfering_cmd
);
1291 /* "show babel ..." commands */
1292 install_element(VIEW_NODE
, &show_babel_interface_cmd
);
1293 install_element(VIEW_NODE
, &show_babel_neighbour_cmd
);
1294 install_element(VIEW_NODE
, &show_babel_route_cmd
);
1295 install_element(VIEW_NODE
, &show_babel_route_prefix_cmd
);
1296 install_element(VIEW_NODE
, &show_babel_route_addr_cmd
);
1297 install_element(VIEW_NODE
, &show_babel_route_addr6_cmd
);
1298 install_element(VIEW_NODE
, &show_babel_parameters_cmd
);
1301 /* hooks: functions called respectively when struct interface is
1302 created or deleted. */
1304 babel_if_new_hook (struct interface
*ifp
)
1306 ifp
->info
= babel_interface_allocate();
1311 babel_if_delete_hook (struct interface
*ifp
)
1313 babel_interface_free(ifp
->info
);
1318 /* Output an "interface" section for each of the known interfaces with
1319 babeld-specific statement lines where appropriate. */
1321 interface_config_write (struct vty
*vty
)
1323 struct listnode
*node
;
1324 struct interface
*ifp
;
1327 for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT
), node
, ifp
)) {
1328 vty_out (vty
, "interface %s%s", ifp
->name
,
1331 vty_out (vty
, " description %s%s", ifp
->desc
,
1333 babel_interface_nfo
*babel_ifp
= babel_get_if_nfo (ifp
);
1334 /* wireless is the default*/
1335 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
))
1337 vty_out (vty
, " babel wired%s", VTY_NEWLINE
);
1340 if (babel_ifp
->hello_interval
!= BABEL_DEFAULT_HELLO_INTERVAL
)
1342 vty_out (vty
, " babel hello-interval %u%s", babel_ifp
->hello_interval
, VTY_NEWLINE
);
1345 if (babel_ifp
->update_interval
!= BABEL_DEFAULT_UPDATE_INTERVAL
)
1347 vty_out (vty
, " babel update-interval %u%s", babel_ifp
->update_interval
, VTY_NEWLINE
);
1350 /* Some parameters have different defaults for wired/wireless. */
1351 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_WIRED
)) {
1352 if (!CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1353 vty_out (vty
, " no babel split-horizon%s", VTY_NEWLINE
);
1356 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRED
) {
1357 vty_out (vty
, " babel rxcost %u%s", babel_ifp
->cost
, VTY_NEWLINE
);
1360 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_INTERFERING
) {
1361 vty_out (vty
, " babel channel interfering%s", VTY_NEWLINE
);
1363 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_NONINTERFERING
) {
1364 vty_out (vty
, " babel channel %d%s", babel_ifp
->channel
,
1369 if (CHECK_FLAG (babel_ifp
->flags
, BABEL_IF_SPLIT_HORIZON
)) {
1370 vty_out (vty
, " babel split-horizon%s", VTY_NEWLINE
);
1373 if (babel_ifp
->cost
!= BABEL_DEFAULT_RXCOST_WIRELESS
) {
1374 vty_out (vty
, " babel rxcost %u%s", babel_ifp
->cost
, VTY_NEWLINE
);
1377 if (babel_ifp
->channel
== BABEL_IF_CHANNEL_NONINTERFERING
) {
1378 vty_out (vty
, " babel channel noninterfering%s", VTY_NEWLINE
);
1380 } else if(babel_ifp
->channel
!= BABEL_IF_CHANNEL_INTERFERING
) {
1381 vty_out (vty
, " babel channel %d%s", babel_ifp
->channel
,
1386 vty_out (vty
, "!%s", VTY_NEWLINE
);
1392 /* Output a "network" statement line for each of the enabled interfaces. */
1394 babel_enable_if_config_write (struct vty
* vty
)
1396 unsigned int i
, lines
= 0;
1399 for (i
= 0; i
< vector_active (babel_enable_if
); i
++)
1400 if ((str
= vector_slot (babel_enable_if
, i
)) != NULL
)
1402 vty_out (vty
, " network %s%s", str
, VTY_NEWLINE
);
1408 /* functions to allocate or free memory for a babel_interface_nfo, filling
1410 static babel_interface_nfo
*
1411 babel_interface_allocate (void)
1413 babel_interface_nfo
*babel_ifp
;
1414 babel_ifp
= XMALLOC(MTYPE_BABEL_IF
, sizeof(babel_interface_nfo
));
1415 if(babel_ifp
== NULL
)
1418 /* Here are set the default values for an interface. */
1419 memset(babel_ifp
, 0, sizeof(babel_interface_nfo
));
1420 /* All flags are unset */
1421 babel_ifp
->bucket_time
= babel_now
.tv_sec
;
1422 babel_ifp
->bucket
= BUCKET_TOKENS_MAX
;
1423 babel_ifp
->hello_seqno
= (random() & 0xFFFF);
1424 babel_ifp
->rtt_min
= 10000;
1425 babel_ifp
->rtt_max
= 120000;
1426 babel_ifp
->max_rtt_penalty
= 150;
1427 babel_ifp
->hello_interval
= BABEL_DEFAULT_HELLO_INTERVAL
;
1428 babel_ifp
->update_interval
= BABEL_DEFAULT_UPDATE_INTERVAL
;
1429 babel_ifp
->channel
= BABEL_IF_CHANNEL_INTERFERING
;
1430 babel_set_wired_internal(babel_ifp
, 0);
1436 babel_interface_free (babel_interface_nfo
*babel_ifp
)
1438 XFREE(MTYPE_BABEL_IF
, babel_ifp
);