]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_interface.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / babeld / babel_interface.c
1 /*
2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
3
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:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
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
20 THE SOFTWARE.
21 */
22
23 #include <zebra.h>
24 #include "memory.h"
25 #include "log.h"
26 #include "command.h"
27 #include "prefix.h"
28 #include "vector.h"
29 #include "distribute.h"
30 #include "lib_errors.h"
31
32 #include "babel_main.h"
33 #include "util.h"
34 #include "kernel.h"
35 #include "babel_interface.h"
36 #include "message.h"
37 #include "route.h"
38 #include "babel_zebra.h"
39 #include "neighbour.h"
40 #include "route.h"
41 #include "xroute.h"
42 #include "babel_errors.h"
43
44 DEFINE_MTYPE_STATIC(BABELD, BABEL_IF, "Babel Interface")
45
46 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
47
48 static int babel_enable_if_lookup (const char *ifname);
49 static int babel_enable_if_add (const char *ifname);
50 static int babel_enable_if_delete (const char *ifname);
51 static int interface_recalculate(struct interface *ifp);
52 static int interface_reset(struct interface *ifp);
53 static int babel_if_new_hook (struct interface *ifp);
54 static int babel_if_delete_hook (struct interface *ifp);
55 static int interface_config_write (struct vty *vty);
56 static babel_interface_nfo * babel_interface_allocate (void);
57 static void babel_interface_free (babel_interface_nfo *bi);
58
59
60 static vector babel_enable_if; /* enable interfaces (by cmd). */
61 static struct cmd_node babel_interface_node = /* babeld's interface node. */
62 {
63 INTERFACE_NODE,
64 "%s(config-if)# ",
65 1 /* VTYSH */
66 };
67
68
69 int
70 babel_interface_up (ZAPI_CALLBACK_ARGS)
71 {
72 struct stream *s = NULL;
73 struct interface *ifp = NULL;
74
75 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
76
77 s = zclient->ibuf;
78 ifp = zebra_interface_state_read(s, vrf_id); /* it updates iflist */
79
80 if (ifp == NULL) {
81 return 0;
82 }
83
84 interface_recalculate(ifp);
85 return 0;
86 }
87
88 int
89 babel_ifp_down(struct interface *ifp)
90 {
91 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
92
93 if (ifp == NULL) {
94 return 0;
95 }
96
97 interface_reset(ifp);
98 return 0;
99 }
100
101 int babel_ifp_create (struct interface *ifp)
102 {
103 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
104
105 interface_recalculate(ifp);
106
107 return 0;
108 }
109
110 int
111 babel_ifp_destroy(struct interface *ifp)
112 {
113 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
114
115 if (IS_ENABLE(ifp))
116 interface_reset(ifp);
117
118 return 0;
119 }
120
121 int
122 babel_interface_address_add (ZAPI_CALLBACK_ARGS)
123 {
124 babel_interface_nfo *babel_ifp;
125 struct connected *ifc;
126 struct prefix *prefix;
127
128 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
129
130 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
131 zclient->ibuf, vrf_id);
132
133 if (ifc == NULL)
134 return 0;
135
136 prefix = ifc->address;
137
138 if (prefix->family == AF_INET) {
139 flush_interface_routes(ifc->ifp, 0);
140 babel_ifp = babel_get_if_nfo(ifc->ifp);
141 if (babel_ifp->ipv4 == NULL) {
142 babel_ifp->ipv4 = malloc(4);
143 if (babel_ifp->ipv4 == NULL) {
144 flog_err(EC_BABEL_MEMORY, "not enough memory");
145 } else {
146 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
147 }
148 }
149 }
150
151 send_request(ifc->ifp, NULL, 0);
152 send_update(ifc->ifp, 0, NULL, 0);
153
154 return 0;
155 }
156
157 int
158 babel_interface_address_delete (ZAPI_CALLBACK_ARGS)
159 {
160 babel_interface_nfo *babel_ifp;
161 struct connected *ifc;
162 struct prefix *prefix;
163
164 debugf(BABEL_DEBUG_IF, "receive a 'interface address delete'");
165
166 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
167 zclient->ibuf, vrf_id);
168
169 if (ifc == NULL)
170 return 0;
171
172 prefix = ifc->address;
173
174 if (prefix->family == AF_INET) {
175 flush_interface_routes(ifc->ifp, 0);
176 babel_ifp = babel_get_if_nfo(ifc->ifp);
177 if (babel_ifp->ipv4 != NULL
178 && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
179 free(babel_ifp->ipv4);
180 babel_ifp->ipv4 = NULL;
181 }
182 }
183
184 send_request(ifc->ifp, NULL, 0);
185 send_update(ifc->ifp, 0, NULL, 0);
186
187 return 0;
188 }
189
190 /* Lookup function. */
191 static int
192 babel_enable_if_lookup (const char *ifname)
193 {
194 unsigned int i;
195 char *str;
196
197 for (i = 0; i < vector_active (babel_enable_if); i++)
198 if ((str = vector_slot (babel_enable_if, i)) != NULL)
199 if (strcmp (str, ifname) == 0)
200 return i;
201 return -1;
202 }
203
204 /* Add interface to babel_enable_if. */
205 static int
206 babel_enable_if_add (const char *ifname)
207 {
208 int ret;
209 struct interface *ifp = NULL;
210
211 ret = babel_enable_if_lookup (ifname);
212 if (ret >= 0)
213 return -1;
214
215 vector_set (babel_enable_if, strdup (ifname));
216
217 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
218 if (ifp != NULL)
219 interface_recalculate(ifp);
220
221 return 1;
222 }
223
224 /* Delete interface from babel_enable_if. */
225 static int
226 babel_enable_if_delete (const char *ifname)
227 {
228 int babel_enable_if_index;
229 char *str;
230 struct interface *ifp = NULL;
231
232 babel_enable_if_index = babel_enable_if_lookup (ifname);
233 if (babel_enable_if_index < 0)
234 return -1;
235
236 str = vector_slot (babel_enable_if, babel_enable_if_index);
237 free (str);
238 vector_unset (babel_enable_if, babel_enable_if_index);
239
240 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
241 if (ifp != NULL)
242 interface_reset(ifp);
243
244 return 1;
245 }
246
247 /* [Babel Command] Babel enable on specified interface or matched network. */
248 DEFUN (babel_network,
249 babel_network_cmd,
250 "network IF_OR_ADDR",
251 "Enable Babel protocol on specified interface or network.\n"
252 "Interface or address\n")
253 {
254 int ret;
255 struct prefix p;
256
257 ret = str2prefix (argv[1]->arg, &p);
258
259 /* Given string is: */
260 if (ret) /* an IPv4 or v6 network */
261 return CMD_ERR_NO_MATCH; /* not implemented yet */
262 else /* an interface name */
263 ret = babel_enable_if_add (argv[1]->arg);
264
265 if (ret < 0) {
266 vty_out (vty, "There is same network configuration %s\n",
267 argv[1]->arg);
268 return CMD_WARNING;
269 }
270
271 return CMD_SUCCESS;
272 }
273
274 /* [Babel Command] Babel enable on specified interface or matched network. */
275 DEFUN (no_babel_network,
276 no_babel_network_cmd,
277 "no network IF_OR_ADDR",
278 NO_STR
279 "Disable Babel protocol on specified interface or network.\n"
280 "Interface or address\n")
281 {
282 int ret;
283 struct prefix p;
284
285 ret = str2prefix (argv[2]->arg, &p);
286
287 /* Given string is: */
288 if (ret) /* an IPv4 or v6 network */
289 return CMD_ERR_NO_MATCH; /* not implemented yet */
290 else /* an interface name */
291 ret = babel_enable_if_delete (argv[2]->arg);
292
293 if (ret < 0) {
294 vty_out (vty, "can't find network %s\n",argv[2]->arg);
295 return CMD_WARNING_CONFIG_FAILED;
296 }
297
298 return CMD_SUCCESS;
299 }
300
301 /* There are a number of interface parameters that must be changed when
302 an interface becomes wired/wireless. In Quagga, they cannot be
303 configured separately. */
304
305 static void
306 babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
307 {
308 if(wired) {
309 babel_ifp->flags |= BABEL_IF_WIRED;
310 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
311 babel_ifp->cost = BABEL_DEFAULT_RXCOST_WIRED;
312 babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
313 babel_ifp->flags &= ~BABEL_IF_LQ;
314 } else {
315 babel_ifp->flags &= ~BABEL_IF_WIRED;
316 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
317 babel_ifp->cost = BABEL_DEFAULT_RXCOST_WIRELESS;
318 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
319 babel_ifp->flags |= BABEL_IF_LQ;
320 }
321
322 }
323
324 /* [Interface Command] Tell the interface is wire. */
325 DEFUN (babel_set_wired,
326 babel_set_wired_cmd,
327 "babel wired",
328 "Babel interface commands\n"
329 "Enable wired optimizations\n")
330 {
331 VTY_DECLVAR_CONTEXT(interface, ifp);
332 babel_interface_nfo *babel_ifp;
333
334 babel_ifp = babel_get_if_nfo(ifp);
335
336 assert (babel_ifp != NULL);
337 babel_set_wired_internal(babel_ifp, 1);
338 return CMD_SUCCESS;
339 }
340
341 /* [Interface Command] Tell the interface is wireless (default). */
342 DEFUN (babel_set_wireless,
343 babel_set_wireless_cmd,
344 "babel wireless",
345 "Babel interface commands\n"
346 "Disable wired optimizations (assume wireless)\n")
347 {
348 VTY_DECLVAR_CONTEXT(interface, ifp);
349 babel_interface_nfo *babel_ifp;
350
351 babel_ifp = babel_get_if_nfo(ifp);
352
353 assert (babel_ifp != NULL);
354 babel_set_wired_internal(babel_ifp, 0);
355 return CMD_SUCCESS;
356 }
357
358 /* [Interface Command] Enable split horizon. */
359 DEFUN (babel_split_horizon,
360 babel_split_horizon_cmd,
361 "babel split-horizon",
362 "Babel interface commands\n"
363 "Enable split horizon processing\n")
364 {
365 VTY_DECLVAR_CONTEXT(interface, ifp);
366 babel_interface_nfo *babel_ifp;
367
368 babel_ifp = babel_get_if_nfo(ifp);
369
370 assert (babel_ifp != NULL);
371 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
372 return CMD_SUCCESS;
373 }
374
375 /* [Interface Command] Disable split horizon (default). */
376 DEFUN (no_babel_split_horizon,
377 no_babel_split_horizon_cmd,
378 "no babel split-horizon",
379 NO_STR
380 "Babel interface commands\n"
381 "Disable split horizon processing\n")
382 {
383 VTY_DECLVAR_CONTEXT(interface, ifp);
384 babel_interface_nfo *babel_ifp;
385
386 babel_ifp = babel_get_if_nfo(ifp);
387
388 assert (babel_ifp != NULL);
389 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
390 return CMD_SUCCESS;
391 }
392
393 /* [Interface Command]. */
394 DEFUN (babel_set_hello_interval,
395 babel_set_hello_interval_cmd,
396 "babel hello-interval (20-655340)",
397 "Babel interface commands\n"
398 "Time between scheduled hellos\n"
399 "Milliseconds\n")
400 {
401 VTY_DECLVAR_CONTEXT(interface, ifp);
402 babel_interface_nfo *babel_ifp;
403 int interval;
404
405 interval = strtoul(argv[2]->arg, NULL, 10);
406
407 babel_ifp = babel_get_if_nfo(ifp);
408 assert (babel_ifp != NULL);
409
410 babel_ifp->hello_interval = interval;
411 return CMD_SUCCESS;
412 }
413
414 /* [Interface Command]. */
415 DEFUN (babel_set_update_interval,
416 babel_set_update_interval_cmd,
417 "babel update-interval (20-655340)",
418 "Babel interface commands\n"
419 "Time between scheduled updates\n"
420 "Milliseconds\n")
421 {
422 VTY_DECLVAR_CONTEXT(interface, ifp);
423 babel_interface_nfo *babel_ifp;
424 int interval;
425
426 interval = strtoul(argv[2]->arg, NULL, 10);
427
428 babel_ifp = babel_get_if_nfo(ifp);
429 assert (babel_ifp != NULL);
430
431 babel_ifp->update_interval = interval;
432 return CMD_SUCCESS;
433 }
434
435 DEFUN (babel_set_rxcost,
436 babel_set_rxcost_cmd,
437 "babel rxcost (1-65534)",
438 "Babel interface commands\n"
439 "Rxcost multiplier\n"
440 "Units\n")
441 {
442 VTY_DECLVAR_CONTEXT(interface, ifp);
443 babel_interface_nfo *babel_ifp;
444 int rxcost;
445
446 rxcost = strtoul(argv[2]->arg, NULL, 10);
447
448 babel_ifp = babel_get_if_nfo(ifp);
449 assert (babel_ifp != NULL);
450
451 babel_ifp->cost = rxcost;
452 return CMD_SUCCESS;
453 }
454
455 DEFUN (babel_set_rtt_decay,
456 babel_set_rtt_decay_cmd,
457 "babel rtt-decay (1-256)",
458 "Babel interface commands\n"
459 "Decay factor for exponential moving average of RTT samples\n"
460 "Units of 1/256\n")
461 {
462 VTY_DECLVAR_CONTEXT(interface, ifp);
463 babel_interface_nfo *babel_ifp;
464 int decay;
465
466 decay = strtoul(argv[2]->arg, NULL, 10);
467
468 babel_ifp = babel_get_if_nfo(ifp);
469 assert (babel_ifp != NULL);
470
471 babel_ifp->rtt_decay = decay;
472 return CMD_SUCCESS;
473 }
474
475 DEFUN (babel_set_rtt_min,
476 babel_set_rtt_min_cmd,
477 "babel rtt-min (1-65535)",
478 "Babel interface commands\n"
479 "Minimum RTT starting for increasing cost\n"
480 "Milliseconds\n")
481 {
482 VTY_DECLVAR_CONTEXT(interface, ifp);
483 babel_interface_nfo *babel_ifp;
484 int rtt;
485
486 rtt = strtoul(argv[2]->arg, NULL, 10);
487
488 babel_ifp = babel_get_if_nfo(ifp);
489 assert (babel_ifp != NULL);
490
491 babel_ifp->rtt_min = rtt;
492 return CMD_SUCCESS;
493 }
494
495 DEFUN (babel_set_rtt_max,
496 babel_set_rtt_max_cmd,
497 "babel rtt-max (1-65535)",
498 "Babel interface commands\n"
499 "Maximum RTT\n"
500 "Milliseconds\n")
501 {
502 VTY_DECLVAR_CONTEXT(interface, ifp);
503 babel_interface_nfo *babel_ifp;
504 int rtt;
505
506 rtt = strtoul(argv[2]->arg, NULL, 10);
507
508 babel_ifp = babel_get_if_nfo(ifp);
509 assert (babel_ifp != NULL);
510
511 babel_ifp->rtt_max = rtt;
512 return CMD_SUCCESS;
513 }
514
515 DEFUN (babel_set_max_rtt_penalty,
516 babel_set_max_rtt_penalty_cmd,
517 "babel max-rtt-penalty (0-65535)",
518 "Babel interface commands\n"
519 "Maximum additional cost due to RTT\n"
520 "Milliseconds\n")
521 {
522 VTY_DECLVAR_CONTEXT(interface, ifp);
523 babel_interface_nfo *babel_ifp;
524 int penalty;
525
526 penalty = strtoul(argv[2]->arg, NULL, 10);
527
528 babel_ifp = babel_get_if_nfo(ifp);
529 assert (babel_ifp != NULL);
530
531 babel_ifp->max_rtt_penalty = penalty;
532 return CMD_SUCCESS;
533 }
534
535 DEFUN (babel_set_enable_timestamps,
536 babel_set_enable_timestamps_cmd,
537 "babel enable-timestamps",
538 "Babel interface commands\n"
539 "Enable timestamps\n")
540 {
541 VTY_DECLVAR_CONTEXT(interface, ifp);
542 babel_interface_nfo *babel_ifp;
543
544 babel_ifp = babel_get_if_nfo(ifp);
545 assert (babel_ifp != NULL);
546
547 babel_ifp->flags |= BABEL_IF_TIMESTAMPS;
548 return CMD_SUCCESS;
549 }
550
551 DEFUN (no_babel_set_enable_timestamps,
552 no_babel_set_enable_timestamps_cmd,
553 "no babel enable-timestamps",
554 NO_STR
555 "Babel interface commands\n"
556 "Disable timestamps\n")
557 {
558 VTY_DECLVAR_CONTEXT(interface, ifp);
559 babel_interface_nfo *babel_ifp;
560
561 babel_ifp = babel_get_if_nfo(ifp);
562 assert (babel_ifp != NULL);
563
564 babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS;
565 return CMD_SUCCESS;
566 }
567
568 DEFUN (babel_set_channel,
569 babel_set_channel_cmd,
570 "babel channel (1-254)",
571 "Babel interface commands\n"
572 "Channel number for diversity routing\n"
573 "Number\n")
574 {
575 VTY_DECLVAR_CONTEXT(interface, ifp);
576 babel_interface_nfo *babel_ifp;
577 int channel;
578
579 channel = strtoul(argv[2]->arg, NULL, 10);
580
581 babel_ifp = babel_get_if_nfo(ifp);
582 assert (babel_ifp != NULL);
583
584 babel_ifp->channel = channel;
585 return CMD_SUCCESS;
586 }
587
588 DEFUN (babel_set_channel_interfering,
589 babel_set_channel_interfering_cmd,
590 "babel channel interfering",
591 "Babel interface commands\n"
592 "Channel number for diversity routing\n"
593 "Mark channel as interfering\n")
594 {
595 VTY_DECLVAR_CONTEXT(interface, ifp);
596 babel_interface_nfo *babel_ifp;
597
598 babel_ifp = babel_get_if_nfo(ifp);
599 assert (babel_ifp != NULL);
600
601 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
602 return CMD_SUCCESS;
603 }
604
605 DEFUN (babel_set_channel_noninterfering,
606 babel_set_channel_noninterfering_cmd,
607 "babel channel noninterfering",
608 "Babel interface commands\n"
609 "Channel number for diversity routing\n"
610 "Mark channel as noninterfering\n")
611 {
612 VTY_DECLVAR_CONTEXT(interface, ifp);
613 babel_interface_nfo *babel_ifp;
614
615 babel_ifp = babel_get_if_nfo(ifp);
616 assert (babel_ifp != NULL);
617
618 babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
619 return CMD_SUCCESS;
620 }
621
622 /* This should be no more than half the hello interval, so that hellos
623 aren't sent late. The result is in milliseconds. */
624 unsigned
625 jitter(babel_interface_nfo *babel_ifp, int urgent)
626 {
627 unsigned interval = babel_ifp->hello_interval;
628 if(urgent)
629 interval = MIN(interval, 100);
630 else
631 interval = MIN(interval, 4000);
632 return roughly(interval) / 4;
633 }
634
635 unsigned
636 update_jitter(babel_interface_nfo *babel_ifp, int urgent)
637 {
638 unsigned interval = babel_ifp->hello_interval;
639 if(urgent)
640 interval = MIN(interval, 100);
641 else
642 interval = MIN(interval, 4000);
643 return roughly(interval);
644 }
645
646 /* calculate babeld's specific datas of an interface (change when the interface
647 change) */
648 static int
649 interface_recalculate(struct interface *ifp)
650 {
651 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
652 unsigned char *tmp = NULL;
653 int mtu, rc;
654 struct ipv6_mreq mreq;
655
656 if (!IS_ENABLE(ifp))
657 return -1;
658
659 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
660 interface_reset(ifp);
661 return -1;
662 }
663
664 babel_ifp->flags |= BABEL_IF_IS_UP;
665
666 mtu = MIN(ifp->mtu, ifp->mtu6);
667
668 /* We need to be able to fit at least two messages into a packet,
669 so MTUs below 116 require lower layer fragmentation. */
670 /* In IPv6, the minimum MTU is 1280, and every host must be able
671 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
672 if(mtu < 128) {
673 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
674 mtu, ifp->name, ifp->ifindex);
675 mtu = 128;
676 }
677
678 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
679 babel_ifp->bufsize = mtu - 4 - 60;
680 tmp = babel_ifp->sendbuf;
681 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
682 if(babel_ifp->sendbuf == NULL) {
683 flog_err(EC_BABEL_MEMORY, "Couldn't reallocate sendbuf.");
684 free(tmp);
685 babel_ifp->bufsize = 0;
686 return -1;
687 }
688 tmp = NULL;
689
690 rc = resize_receive_buffer(mtu);
691 if(rc < 0)
692 zlog_warn("couldn't resize "
693 "receive buffer for interface %s (%d) (%d bytes).\n",
694 ifp->name, ifp->ifindex, mtu);
695
696 memset(&mreq, 0, sizeof(mreq));
697 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
698 mreq.ipv6mr_interface = ifp->ifindex;
699
700 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
701 (char*)&mreq, sizeof(mreq));
702 if(rc < 0) {
703 flog_err_sys(EC_LIB_SOCKET,
704 "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
705 ifp->name, safe_strerror(errno));
706 /* This is probably due to a missing link-local address,
707 so down this interface, and wait until the main loop
708 tries to up it again. */
709 interface_reset(ifp);
710 return -1;
711 }
712
713 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
714 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
715 send_hello(ifp);
716 send_request(ifp, NULL, 0);
717
718 update_interface_metric(ifp);
719
720 debugf(BABEL_DEBUG_COMMON,
721 "Upped interface %s (%s, cost=%d, channel=%d%s).",
722 ifp->name,
723 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
724 babel_ifp->cost,
725 babel_ifp->channel,
726 babel_ifp->ipv4 ? ", IPv4" : "");
727
728 if(rc > 0)
729 send_update(ifp, 0, NULL, 0);
730
731 return 1;
732 }
733
734 /* Reset the interface as it was new: it's not removed from the interface list,
735 and may be considered as a upped interface. */
736 static int
737 interface_reset(struct interface *ifp)
738 {
739 int rc;
740 struct ipv6_mreq mreq;
741 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
742
743 if (!(babel_ifp->flags & BABEL_IF_IS_UP))
744 return 0;
745
746 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
747 babel_ifp->flags &= ~BABEL_IF_IS_UP;
748
749 flush_interface_routes(ifp, 0);
750 babel_ifp->buffered = 0;
751 babel_ifp->bufsize = 0;
752 free(babel_ifp->sendbuf);
753 babel_ifp->num_buffered_updates = 0;
754 babel_ifp->update_bufsize = 0;
755 if(babel_ifp->buffered_updates)
756 free(babel_ifp->buffered_updates);
757 babel_ifp->buffered_updates = NULL;
758 babel_ifp->sendbuf = NULL;
759
760 if(ifp->ifindex > 0) {
761 memset(&mreq, 0, sizeof(mreq));
762 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
763 mreq.ipv6mr_interface = ifp->ifindex;
764 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
765 (char*)&mreq, sizeof(mreq));
766 if(rc < 0)
767 flog_err_sys(EC_LIB_SOCKET,
768 "setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
769 ifp->name, safe_strerror(errno));
770 }
771
772 update_interface_metric(ifp);
773
774 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
775 ifp->name,
776 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
777 babel_ifp->cost,
778 babel_ifp->ipv4 ? ", IPv4" : "");
779
780 return 1;
781 }
782
783 /* Send retraction to all, and reset all interfaces statistics. */
784 void
785 babel_interface_close_all(void)
786 {
787 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
788 struct interface *ifp = NULL;
789
790 FOR_ALL_INTERFACES(vrf, ifp) {
791 if(!if_up(ifp))
792 continue;
793 send_wildcard_retraction(ifp);
794 /* Make sure that we expire quickly from our neighbours'
795 association caches. */
796 send_hello_noupdate(ifp, 10);
797 flushbuf(ifp);
798 usleep(roughly(1000));
799 gettime(&babel_now);
800 }
801 FOR_ALL_INTERFACES(vrf, ifp) {
802 if(!if_up(ifp))
803 continue;
804 /* Make sure they got it. */
805 send_wildcard_retraction(ifp);
806 send_hello_noupdate(ifp, 1);
807 flushbuf(ifp);
808 usleep(roughly(10000));
809 gettime(&babel_now);
810 interface_reset(ifp);
811 }
812 }
813
814 /* return "true" if address is one of our ipv6 addresses */
815 int
816 is_interface_ll_address(struct interface *ifp, const unsigned char *address)
817 {
818 struct connected *connected;
819 struct listnode *node;
820
821 if(!if_up(ifp))
822 return 0;
823
824 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
825 if(connected->address->family == AF_INET6 &&
826 memcmp(&connected->address->u.prefix6, address, 16) == 0)
827 return 1;
828 }
829
830 return 0;
831 }
832
833 static void
834 show_babel_interface_sub (struct vty *vty, struct interface *ifp)
835 {
836 int is_up;
837 babel_interface_nfo *babel_ifp;
838
839 vty_out (vty, "%s is %s\n", ifp->name,
840 ((is_up = if_is_operative(ifp)) ? "up" : "down"));
841 vty_out (vty, " ifindex %u, MTU %u bytes %s\n",
842 ifp->ifindex, MIN(ifp->mtu, ifp->mtu6), if_flag_dump(ifp->flags));
843
844 if (!IS_ENABLE(ifp))
845 {
846 vty_out (vty, " Babel protocol is not enabled on this interface\n");
847 return;
848 }
849 if (!is_up)
850 {
851 vty_out (vty,
852 " Babel protocol is enabled, but not running on this interface\n");
853 return;
854 }
855 babel_ifp = babel_get_if_nfo (ifp);
856 vty_out (vty, " Babel protocol is running on this interface\n");
857 vty_out (vty, " Operating mode is \"%s\"\n",
858 CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless");
859 vty_out (vty, " Split horizon mode is %s\n",
860 CHECK_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off");
861 vty_out (vty, " Hello interval is %u ms\n", babel_ifp->hello_interval);
862 vty_out (vty, " Update interval is %u ms\n", babel_ifp->update_interval);
863 vty_out (vty, " Rxcost multiplier is %u\n", babel_ifp->cost);
864 }
865
866 DEFUN (show_babel_interface,
867 show_babel_interface_cmd,
868 "show babel interface [IFNAME]",
869 SHOW_STR
870 "Babel information\n"
871 "Interface information\n"
872 "Interface\n")
873 {
874 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
875 struct interface *ifp;
876
877 if (argc == 3)
878 {
879 FOR_ALL_INTERFACES (vrf, ifp)
880 show_babel_interface_sub (vty, ifp);
881 return CMD_SUCCESS;
882 }
883 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
884 {
885 vty_out (vty, "No such interface name\n");
886 return CMD_WARNING;
887 }
888 show_babel_interface_sub (vty, ifp);
889 return CMD_SUCCESS;
890 }
891
892 static void
893 show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
894 {
895 vty_out (vty,
896 "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
897 "rtt %s rttcost %d%s.\n",
898 format_address(neigh->address),
899 neigh->ifp->name,
900 neigh->reach,
901 neighbour_rxcost(neigh),
902 neigh->txcost,
903 format_thousands(neigh->rtt),
904 neighbour_rttcost(neigh),
905 if_up(neigh->ifp) ? "" : " (down)");
906 }
907
908 DEFUN (show_babel_neighbour,
909 show_babel_neighbour_cmd,
910 "show babel neighbor [IFNAME]",
911 SHOW_STR
912 "Babel information\n"
913 "Print neighbors\n"
914 "Interface\n")
915 {
916 struct neighbour *neigh;
917 struct interface *ifp;
918
919 if (argc == 3) {
920 FOR_ALL_NEIGHBOURS(neigh) {
921 show_babel_neighbour_sub(vty, neigh);
922 }
923 return CMD_SUCCESS;
924 }
925 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
926 {
927 vty_out (vty, "No such interface name\n");
928 return CMD_WARNING;
929 }
930 FOR_ALL_NEIGHBOURS(neigh) {
931 if(ifp->ifindex == neigh->ifp->ifindex) {
932 show_babel_neighbour_sub(vty, neigh);
933 }
934 }
935 return CMD_SUCCESS;
936 }
937
938 static int
939 babel_prefix_eq(struct prefix *prefix, unsigned char *p, int plen)
940 {
941 if(prefix->family == AF_INET6) {
942 if(prefix->prefixlen != plen ||
943 memcmp(&prefix->u.prefix6, p, 16) != 0)
944 return 0;
945 } else if(prefix->family == AF_INET) {
946 if(plen < 96 || !v4mapped(p) || prefix->prefixlen != plen - 96 ||
947 memcmp(&prefix->u.prefix4, p + 12, 4) != 0)
948 return 0;
949 } else {
950 return 0;
951 }
952
953 return 1;
954 }
955
956 static void
957 show_babel_routes_sub(struct babel_route *route, struct vty *vty,
958 struct prefix *prefix)
959 {
960 const unsigned char *nexthop =
961 memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
962 NULL : route->nexthop;
963 char channels[100];
964
965 if(prefix && !babel_prefix_eq(prefix, route->src->prefix, route->src->plen))
966 return;
967
968 if(route->channels[0] == 0)
969 channels[0] = '\0';
970 else {
971 int k, j = 0;
972 snprintf(channels, 100, " chan (");
973 j = strlen(channels);
974 for(k = 0; k < DIVERSITY_HOPS; k++) {
975 if(route->channels[k] == 0)
976 break;
977 if(k > 0)
978 channels[j++] = ',';
979 snprintf(channels + j, 100 - j, "%u", route->channels[k]);
980 j = strlen(channels);
981 }
982 snprintf(channels + j, 100 - j, ")");
983 if(k == 0)
984 channels[0] = '\0';
985 }
986
987 vty_out (vty,
988 "%s metric %d refmetric %d id %s seqno %d%s age %d "
989 "via %s neigh %s%s%s%s\n",
990 format_prefix(route->src->prefix, route->src->plen),
991 route_metric(route), route->refmetric,
992 format_eui64(route->src->id),
993 (int)route->seqno,
994 channels,
995 (int)(babel_now.tv_sec - route->time),
996 route->neigh->ifp->name,
997 format_address(route->neigh->address),
998 nexthop ? " nexthop " : "",
999 nexthop ? format_address(nexthop) : "",
1000 route->installed ? " (installed)" : route_feasible(route) ? " (feasible)" : "");
1001 }
1002
1003 static void
1004 show_babel_xroutes_sub (struct xroute *xroute, struct vty *vty,
1005 struct prefix *prefix)
1006 {
1007 if(prefix && !babel_prefix_eq(prefix, xroute->prefix, xroute->plen))
1008 return;
1009
1010 vty_out (vty, "%s metric %d (exported)\n",
1011 format_prefix(xroute->prefix, xroute->plen),
1012 xroute->metric);
1013 }
1014
1015 DEFUN (show_babel_route,
1016 show_babel_route_cmd,
1017 "show babel route",
1018 SHOW_STR
1019 "Babel information\n"
1020 "Babel internal routing table\n")
1021 {
1022 struct route_stream *routes = NULL;
1023 struct xroute_stream *xroutes = NULL;
1024 routes = route_stream(0);
1025 if(routes) {
1026 while(1) {
1027 struct babel_route *route = route_stream_next(routes);
1028 if(route == NULL)
1029 break;
1030 show_babel_routes_sub(route, vty, NULL);
1031 }
1032 route_stream_done(routes);
1033 } else {
1034 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1035 }
1036 xroutes = xroute_stream();
1037 if(xroutes) {
1038 while(1) {
1039 struct xroute *xroute = xroute_stream_next(xroutes);
1040 if(xroute == NULL)
1041 break;
1042 show_babel_xroutes_sub(xroute, vty, NULL);
1043 }
1044 xroute_stream_done(xroutes);
1045 } else {
1046 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1047 }
1048 return CMD_SUCCESS;
1049 }
1050
1051 DEFUN (show_babel_route_prefix,
1052 show_babel_route_prefix_cmd,
1053 "show babel route <A.B.C.D/M|X:X::X:X/M>",
1054 SHOW_STR
1055 "Babel information\n"
1056 "Babel internal routing table\n"
1057 "IPv4 prefix <network>/<length>\n"
1058 "IPv6 prefix <network>/<length>\n")
1059 {
1060 struct route_stream *routes = NULL;
1061 struct xroute_stream *xroutes = NULL;
1062 struct prefix prefix;
1063 int ret;
1064
1065 ret = str2prefix(argv[3]->arg, &prefix);
1066 if(ret == 0) {
1067 vty_out (vty, "%% Malformed address\n");
1068 return CMD_WARNING;
1069 }
1070
1071 routes = route_stream(0);
1072 if(routes) {
1073 while(1) {
1074 struct babel_route *route = route_stream_next(routes);
1075 if(route == NULL)
1076 break;
1077 show_babel_routes_sub(route, vty, &prefix);
1078 }
1079 route_stream_done(routes);
1080 } else {
1081 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1082 }
1083 xroutes = xroute_stream();
1084 if(xroutes) {
1085 while(1) {
1086 struct xroute *xroute = xroute_stream_next(xroutes);
1087 if(xroute == NULL)
1088 break;
1089 show_babel_xroutes_sub(xroute, vty, &prefix);
1090 }
1091 xroute_stream_done(xroutes);
1092 } else {
1093 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1094 }
1095 return CMD_SUCCESS;
1096 }
1097
1098
1099 DEFUN (show_babel_route_addr,
1100 show_babel_route_addr_cmd,
1101 "show babel route A.B.C.D",
1102 SHOW_STR
1103 "Babel information\n"
1104 "Babel internal routing table\n"
1105 "IPv4 address <network>/<length>\n")
1106 {
1107 struct in_addr addr;
1108 char buf[INET_ADDRSTRLEN + 8];
1109 struct route_stream *routes = NULL;
1110 struct xroute_stream *xroutes = NULL;
1111 struct prefix prefix;
1112 int ret;
1113
1114 ret = inet_aton (argv[3]->arg, &addr);
1115 if (ret <= 0) {
1116 vty_out (vty, "%% Malformed address\n");
1117 return CMD_WARNING;
1118 }
1119
1120 /* Quagga has no convenient prefix constructors. */
1121 snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(addr), 32);
1122
1123 ret = str2prefix(buf, &prefix);
1124 if (ret == 0) {
1125 vty_out (vty, "%% Parse error -- this shouldn't happen\n");
1126 return CMD_WARNING;
1127 }
1128
1129 routes = route_stream(0);
1130 if(routes) {
1131 while(1) {
1132 struct babel_route *route = route_stream_next(routes);
1133 if(route == NULL)
1134 break;
1135 show_babel_routes_sub(route, vty, &prefix);
1136 }
1137 route_stream_done(routes);
1138 } else {
1139 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1140 }
1141 xroutes = xroute_stream();
1142 if(xroutes) {
1143 while(1) {
1144 struct xroute *xroute = xroute_stream_next(xroutes);
1145 if(xroute == NULL)
1146 break;
1147 show_babel_xroutes_sub(xroute, vty, &prefix);
1148 }
1149 xroute_stream_done(xroutes);
1150 } else {
1151 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1152 }
1153 return CMD_SUCCESS;
1154 }
1155
1156 DEFUN (show_babel_route_addr6,
1157 show_babel_route_addr6_cmd,
1158 "show babel route X:X::X:X",
1159 SHOW_STR
1160 "Babel information\n"
1161 "Babel internal routing table\n"
1162 "IPv6 address <network>/<length>\n")
1163 {
1164 struct in6_addr addr;
1165 char buf1[INET6_ADDRSTRLEN];
1166 char buf[INET6_ADDRSTRLEN + 8];
1167 struct route_stream *routes = NULL;
1168 struct xroute_stream *xroutes = NULL;
1169 struct prefix prefix;
1170 int ret;
1171
1172 ret = inet_pton (AF_INET6, argv[3]->arg, &addr);
1173 if (ret <= 0) {
1174 vty_out (vty, "%% Malformed address\n");
1175 return CMD_WARNING;
1176 }
1177
1178 /* Quagga has no convenient prefix constructors. */
1179 snprintf(buf, sizeof(buf), "%s/%d",
1180 inet_ntop(AF_INET6, &addr, buf1, sizeof(buf1)), 128);
1181
1182 ret = str2prefix(buf, &prefix);
1183 if (ret == 0) {
1184 vty_out (vty, "%% Parse error -- this shouldn't happen\n");
1185 return CMD_WARNING;
1186 }
1187
1188 routes = route_stream(0);
1189 if(routes) {
1190 while(1) {
1191 struct babel_route *route = route_stream_next(routes);
1192 if(route == NULL)
1193 break;
1194 show_babel_routes_sub(route, vty, &prefix);
1195 }
1196 route_stream_done(routes);
1197 } else {
1198 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1199 }
1200 xroutes = xroute_stream();
1201 if(xroutes) {
1202 while(1) {
1203 struct xroute *xroute = xroute_stream_next(xroutes);
1204 if(xroute == NULL)
1205 break;
1206 show_babel_xroutes_sub(xroute, vty, &prefix);
1207 }
1208 xroute_stream_done(xroutes);
1209 } else {
1210 flog_err(EC_BABEL_MEMORY, "Couldn't allocate route stream.");
1211 }
1212 return CMD_SUCCESS;
1213 }
1214
1215 DEFUN (show_babel_parameters,
1216 show_babel_parameters_cmd,
1217 "show babel parameters",
1218 SHOW_STR
1219 "Babel information\n"
1220 "Configuration information\n")
1221 {
1222 struct babel *babel_ctx;
1223
1224 vty_out (vty, " -- Babel running configuration --\n");
1225 show_babel_main_configuration(vty);
1226
1227 babel_ctx = babel_lookup();
1228 if (babel_ctx) {
1229 vty_out (vty, " -- distribution lists --\n");
1230 config_show_distribute(vty, babel_ctx->distribute_ctx);
1231 }
1232 return CMD_SUCCESS;
1233 }
1234
1235 int babel_ifp_up(struct interface *ifp)
1236 {
1237 return 0;
1238 }
1239
1240 void
1241 babel_if_init(void)
1242 {
1243 /* initialize interface list */
1244 hook_register_prio(if_add, 0, babel_if_new_hook);
1245 hook_register_prio(if_del, 0, babel_if_delete_hook);
1246
1247 babel_enable_if = vector_init (1);
1248
1249 /* install interface node and commands */
1250 install_node (&babel_interface_node, interface_config_write);
1251 if_cmd_init();
1252
1253 install_element(BABEL_NODE, &babel_network_cmd);
1254 install_element(BABEL_NODE, &no_babel_network_cmd);
1255 install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
1256 install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
1257 install_element(INTERFACE_NODE, &babel_set_wired_cmd);
1258 install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
1259 install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
1260 install_element(INTERFACE_NODE, &babel_set_update_interval_cmd);
1261 install_element(INTERFACE_NODE, &babel_set_rxcost_cmd);
1262 install_element(INTERFACE_NODE, &babel_set_channel_cmd);
1263 install_element(INTERFACE_NODE, &babel_set_rtt_decay_cmd);
1264 install_element(INTERFACE_NODE, &babel_set_rtt_min_cmd);
1265 install_element(INTERFACE_NODE, &babel_set_rtt_max_cmd);
1266 install_element(INTERFACE_NODE, &babel_set_max_rtt_penalty_cmd);
1267 install_element(INTERFACE_NODE, &babel_set_enable_timestamps_cmd);
1268 install_element(INTERFACE_NODE, &no_babel_set_enable_timestamps_cmd);
1269 install_element(INTERFACE_NODE, &babel_set_channel_interfering_cmd);
1270 install_element(INTERFACE_NODE, &babel_set_channel_noninterfering_cmd);
1271
1272 /* "show babel ..." commands */
1273 install_element(VIEW_NODE, &show_babel_interface_cmd);
1274 install_element(VIEW_NODE, &show_babel_neighbour_cmd);
1275 install_element(VIEW_NODE, &show_babel_route_cmd);
1276 install_element(VIEW_NODE, &show_babel_route_prefix_cmd);
1277 install_element(VIEW_NODE, &show_babel_route_addr_cmd);
1278 install_element(VIEW_NODE, &show_babel_route_addr6_cmd);
1279 install_element(VIEW_NODE, &show_babel_parameters_cmd);
1280 }
1281
1282 /* hooks: functions called respectively when struct interface is
1283 created or deleted. */
1284 static int
1285 babel_if_new_hook (struct interface *ifp)
1286 {
1287 ifp->info = babel_interface_allocate();
1288 return 0;
1289 }
1290
1291 static int
1292 babel_if_delete_hook (struct interface *ifp)
1293 {
1294 babel_interface_free(ifp->info);
1295 ifp->info = NULL;
1296 return 0;
1297 }
1298
1299 /* Output an "interface" section for each of the known interfaces with
1300 babeld-specific statement lines where appropriate. */
1301 static int
1302 interface_config_write (struct vty *vty)
1303 {
1304 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
1305 struct interface *ifp;
1306 int write = 0;
1307
1308 FOR_ALL_INTERFACES (vrf, ifp) {
1309 vty_frame (vty, "interface %s\n",ifp->name);
1310 if (ifp->desc)
1311 vty_out (vty, " description %s\n",ifp->desc);
1312 babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
1313 /* wireless is the default*/
1314 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
1315 {
1316 vty_out (vty, " babel wired\n");
1317 write++;
1318 }
1319 if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
1320 {
1321 vty_out (vty, " babel hello-interval %u\n",
1322 babel_ifp->hello_interval);
1323 write++;
1324 }
1325 if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
1326 {
1327 vty_out (vty, " babel update-interval %u\n",
1328 babel_ifp->update_interval);
1329 write++;
1330 }
1331 /* Some parameters have different defaults for wired/wireless. */
1332 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED)) {
1333 if (!CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
1334 vty_out (vty, " no babel split-horizon\n");
1335 write++;
1336 }
1337 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRED) {
1338 vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
1339 write++;
1340 }
1341 if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) {
1342 vty_out (vty, " babel channel interfering\n");
1343 write++;
1344 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_NONINTERFERING) {
1345 vty_out (vty, " babel channel %d\n",babel_ifp->channel);
1346 write++;
1347 }
1348 } else {
1349 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
1350 vty_out (vty, " babel split-horizon\n");
1351 write++;
1352 }
1353 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRELESS) {
1354 vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
1355 write++;
1356 }
1357 if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) {
1358 vty_out (vty, " babel channel noninterfering\n");
1359 write++;
1360 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_INTERFERING) {
1361 vty_out (vty, " babel channel %d\n",babel_ifp->channel);
1362 write++;
1363 }
1364 }
1365 vty_endframe (vty, "!\n");
1366 write++;
1367 }
1368 return write;
1369 }
1370
1371 /* Output a "network" statement line for each of the enabled interfaces. */
1372 int
1373 babel_enable_if_config_write (struct vty * vty)
1374 {
1375 unsigned int i, lines = 0;
1376 char *str;
1377
1378 for (i = 0; i < vector_active (babel_enable_if); i++)
1379 if ((str = vector_slot (babel_enable_if, i)) != NULL)
1380 {
1381 vty_out (vty, " network %s\n", str);
1382 lines++;
1383 }
1384 return lines;
1385 }
1386
1387 /* functions to allocate or free memory for a babel_interface_nfo, filling
1388 needed fields */
1389 static babel_interface_nfo *
1390 babel_interface_allocate (void)
1391 {
1392 babel_interface_nfo *babel_ifp;
1393 babel_ifp = XCALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
1394 /* All flags are unset */
1395 babel_ifp->bucket_time = babel_now.tv_sec;
1396 babel_ifp->bucket = BUCKET_TOKENS_MAX;
1397 babel_ifp->hello_seqno = (random() & 0xFFFF);
1398 babel_ifp->rtt_min = 10000;
1399 babel_ifp->rtt_max = 120000;
1400 babel_ifp->max_rtt_penalty = 150;
1401 babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL;
1402 babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL;
1403 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
1404 babel_set_wired_internal(babel_ifp, 0);
1405
1406 return babel_ifp;
1407 }
1408
1409 static void
1410 babel_interface_free (babel_interface_nfo *babel_ifp)
1411 {
1412 XFREE(MTYPE_BABEL_IF, babel_ifp);
1413 }