]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_interface.c
*: remove VTY_GET_*
[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
31 #include "babel_main.h"
32 #include "util.h"
33 #include "kernel.h"
34 #include "babel_interface.h"
35 #include "message.h"
36 #include "route.h"
37 #include "babel_zebra.h"
38 #include "neighbour.h"
39 #include "route.h"
40 #include "xroute.h"
41 #include "babel_memory.h"
42
43 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
44
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);
55
56
57 static vector babel_enable_if; /* enable interfaces (by cmd). */
58 static struct cmd_node babel_interface_node = /* babeld's interface node. */
59 {
60 INTERFACE_NODE,
61 "%s(config-if)# ",
62 1 /* VTYSH */
63 };
64
65
66 int
67 babel_interface_up (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
68 {
69 struct stream *s = NULL;
70 struct interface *ifp = NULL;
71
72 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
73
74 s = zclient->ibuf;
75 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
76
77 if (ifp == NULL) {
78 return 0;
79 }
80
81 interface_recalculate(ifp);
82 return 0;
83 }
84
85 int
86 babel_interface_down (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
87 {
88 struct stream *s = NULL;
89 struct interface *ifp = NULL;
90
91 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
92
93 s = zclient->ibuf;
94 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
95
96 if (ifp == NULL) {
97 return 0;
98 }
99
100 interface_reset(ifp);
101 return 0;
102 }
103
104 int
105 babel_interface_add (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
106 {
107 struct interface *ifp = NULL;
108
109 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
110
111 /* read and add the interface in the iflist. */
112 ifp = zebra_interface_add_read (zclient->ibuf, vrf);
113
114 if (ifp == NULL) {
115 return 0;
116 }
117
118 interface_recalculate(ifp);
119 return 0;
120 }
121
122 int
123 babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
124 {
125 struct interface *ifp;
126 struct stream *s;
127
128 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
129
130 s = zclient->ibuf;
131 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
132
133 if (ifp == NULL)
134 return 0;
135
136 if (IS_ENABLE(ifp))
137 interface_reset(ifp);
138
139 /* To support pseudo interface do not free interface structure. */
140 /* if_delete(ifp); */
141 ifp->ifindex = IFINDEX_INTERNAL;
142
143 return 0;
144 }
145
146 int
147 babel_interface_address_add (int cmd, struct zclient *client,
148 zebra_size_t length, vrf_id_t vrf)
149 {
150 babel_interface_nfo *babel_ifp;
151 struct connected *ifc;
152 struct prefix *prefix;
153
154 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
155
156 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
157 zclient->ibuf, vrf);
158
159 if (ifc == NULL)
160 return 0;
161
162 prefix = ifc->address;
163
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");
171 } else {
172 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
173 }
174 }
175 }
176
177 send_request(ifc->ifp, NULL, 0);
178 send_update(ifc->ifp, 0, NULL, 0);
179
180 return 0;
181 }
182
183 int
184 babel_interface_address_delete (int cmd, struct zclient *client,
185 zebra_size_t length, vrf_id_t vrf)
186 {
187 babel_interface_nfo *babel_ifp;
188 struct connected *ifc;
189 struct prefix *prefix;
190
191 debugf(BABEL_DEBUG_IF, "receive a 'interface address delete'");
192
193 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
194 zclient->ibuf, vrf);
195
196 if (ifc == NULL)
197 return 0;
198
199 prefix = ifc->address;
200
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;
208 }
209 }
210
211 send_request(ifc->ifp, NULL, 0);
212 send_update(ifc->ifp, 0, NULL, 0);
213
214 return 0;
215 }
216
217 /* Lookup function. */
218 static int
219 babel_enable_if_lookup (const char *ifname)
220 {
221 unsigned int i;
222 char *str;
223
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)
227 return i;
228 return -1;
229 }
230
231 /* Add interface to babel_enable_if. */
232 static int
233 babel_enable_if_add (const char *ifname)
234 {
235 int ret;
236 struct interface *ifp = NULL;
237
238 ret = babel_enable_if_lookup (ifname);
239 if (ret >= 0)
240 return -1;
241
242 vector_set (babel_enable_if, strdup (ifname));
243
244 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
245 if (ifp != NULL)
246 interface_recalculate(ifp);
247
248 return 1;
249 }
250
251 /* Delete interface from babel_enable_if. */
252 static int
253 babel_enable_if_delete (const char *ifname)
254 {
255 int babel_enable_if_index;
256 char *str;
257 struct interface *ifp = NULL;
258
259 babel_enable_if_index = babel_enable_if_lookup (ifname);
260 if (babel_enable_if_index < 0)
261 return -1;
262
263 str = vector_slot (babel_enable_if, babel_enable_if_index);
264 free (str);
265 vector_unset (babel_enable_if, babel_enable_if_index);
266
267 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
268 if (ifp != NULL)
269 interface_reset(ifp);
270
271 return 1;
272 }
273
274 /* [Babel Command] Babel enable on specified interface or matched network. */
275 DEFUN (babel_network,
276 babel_network_cmd,
277 "network IF_OR_ADDR",
278 "Enable Babel protocol on specified interface or network.\n"
279 "Interface or address\n")
280 {
281 int ret;
282 struct prefix p;
283
284 ret = str2prefix (argv[1]->arg, &p);
285
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);
291
292 if (ret < 0) {
293 vty_out (vty, "There is same network configuration %s%s", argv[1]->arg,
294 VTY_NEWLINE);
295 return CMD_WARNING;
296 }
297
298 return CMD_SUCCESS;
299 }
300
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",
305 NO_STR
306 "Disable Babel protocol on specified interface or network.\n"
307 "Interface or address\n")
308 {
309 int ret;
310 struct prefix p;
311
312 ret = str2prefix (argv[2]->arg, &p);
313
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);
319
320 if (ret < 0) {
321 vty_out (vty, "can't find network %s%s", argv[2]->arg,
322 VTY_NEWLINE);
323 return CMD_WARNING;
324 }
325
326 return CMD_SUCCESS;
327 }
328
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. */
332
333 static void
334 babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
335 {
336 if(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;
342 } else {
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;
348 }
349
350 }
351
352 /* [Interface Command] Tell the interface is wire. */
353 DEFUN (babel_set_wired,
354 babel_set_wired_cmd,
355 "babel wired",
356 "Babel interface commands\n"
357 "Enable wired optimizations\n")
358 {
359 VTY_DECLVAR_CONTEXT(interface, ifp);
360 babel_interface_nfo *babel_ifp;
361
362 babel_ifp = babel_get_if_nfo(ifp);
363
364 assert (babel_ifp != NULL);
365 babel_set_wired_internal(babel_ifp, 1);
366 return CMD_SUCCESS;
367 }
368
369 /* [Interface Command] Tell the interface is wireless (default). */
370 DEFUN (babel_set_wireless,
371 babel_set_wireless_cmd,
372 "babel wireless",
373 "Babel interface commands\n"
374 "Disable wired optimizations (assume wireless)\n")
375 {
376 VTY_DECLVAR_CONTEXT(interface, ifp);
377 babel_interface_nfo *babel_ifp;
378
379 babel_ifp = babel_get_if_nfo(ifp);
380
381 assert (babel_ifp != NULL);
382 babel_set_wired_internal(babel_ifp, 0);
383 return CMD_SUCCESS;
384 }
385
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")
392 {
393 VTY_DECLVAR_CONTEXT(interface, ifp);
394 babel_interface_nfo *babel_ifp;
395
396 babel_ifp = babel_get_if_nfo(ifp);
397
398 assert (babel_ifp != NULL);
399 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
400 return CMD_SUCCESS;
401 }
402
403 /* [Interface Command] Disable split horizon (default). */
404 DEFUN (no_babel_split_horizon,
405 no_babel_split_horizon_cmd,
406 "no babel split-horizon",
407 NO_STR
408 "Babel interface commands\n"
409 "Disable split horizon processing\n")
410 {
411 VTY_DECLVAR_CONTEXT(interface, ifp);
412 babel_interface_nfo *babel_ifp;
413
414 babel_ifp = babel_get_if_nfo(ifp);
415
416 assert (babel_ifp != NULL);
417 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
418 return CMD_SUCCESS;
419 }
420
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"
427 "Milliseconds\n")
428 {
429 VTY_DECLVAR_CONTEXT(interface, ifp);
430 babel_interface_nfo *babel_ifp;
431 int interval;
432
433 interval = strtoul(argv[2]->arg, NULL, 10);
434
435 babel_ifp = babel_get_if_nfo(ifp);
436 assert (babel_ifp != NULL);
437
438 babel_ifp->hello_interval = interval;
439 return CMD_SUCCESS;
440 }
441
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"
448 "Milliseconds\n")
449 {
450 VTY_DECLVAR_CONTEXT(interface, ifp);
451 babel_interface_nfo *babel_ifp;
452 int interval;
453
454 interval = strtoul(argv[2]->arg, NULL, 10);
455
456 babel_ifp = babel_get_if_nfo(ifp);
457 assert (babel_ifp != NULL);
458
459 babel_ifp->update_interval = interval;
460 return CMD_SUCCESS;
461 }
462
463 DEFUN (babel_set_rxcost,
464 babel_set_rxcost_cmd,
465 "babel rxcost (1-65534)",
466 "Babel interface commands\n"
467 "Rxcost multiplier\n"
468 "Units\n")
469 {
470 VTY_DECLVAR_CONTEXT(interface, ifp);
471 babel_interface_nfo *babel_ifp;
472 int rxcost;
473
474 rxcost = strtoul(argv[2]->arg, NULL, 10);
475
476 babel_ifp = babel_get_if_nfo(ifp);
477 assert (babel_ifp != NULL);
478
479 babel_ifp->cost = rxcost;
480 return CMD_SUCCESS;
481 }
482
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"
488 "Units of 1/256\n")
489 {
490 VTY_DECLVAR_CONTEXT(interface, ifp);
491 babel_interface_nfo *babel_ifp;
492 int decay;
493
494 decay = strtoul(argv[2]->arg, NULL, 10);
495
496 babel_ifp = babel_get_if_nfo(ifp);
497 assert (babel_ifp != NULL);
498
499 babel_ifp->rtt_decay = decay;
500 return CMD_SUCCESS;
501 }
502
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"
508 "Milliseconds\n")
509 {
510 VTY_DECLVAR_CONTEXT(interface, ifp);
511 babel_interface_nfo *babel_ifp;
512 int rtt;
513
514 rtt = strtoul(argv[2]->arg, NULL, 10);
515
516 babel_ifp = babel_get_if_nfo(ifp);
517 assert (babel_ifp != NULL);
518
519 babel_ifp->rtt_min = rtt;
520 return CMD_SUCCESS;
521 }
522
523 DEFUN (babel_set_rtt_max,
524 babel_set_rtt_max_cmd,
525 "babel rtt-max (1-65535)",
526 "Babel interface commands\n"
527 "Maximum RTT\n"
528 "Milliseconds\n")
529 {
530 VTY_DECLVAR_CONTEXT(interface, ifp);
531 babel_interface_nfo *babel_ifp;
532 int rtt;
533
534 rtt = strtoul(argv[2]->arg, NULL, 10);
535
536 babel_ifp = babel_get_if_nfo(ifp);
537 assert (babel_ifp != NULL);
538
539 babel_ifp->rtt_max = rtt;
540 return CMD_SUCCESS;
541 }
542
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"
548 "Milliseconds\n")
549 {
550 VTY_DECLVAR_CONTEXT(interface, ifp);
551 babel_interface_nfo *babel_ifp;
552 int penalty;
553
554 penalty = strtoul(argv[2]->arg, NULL, 10);
555
556 babel_ifp = babel_get_if_nfo(ifp);
557 assert (babel_ifp != NULL);
558
559 babel_ifp->max_rtt_penalty = penalty;
560 return CMD_SUCCESS;
561 }
562
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")
568 {
569 VTY_DECLVAR_CONTEXT(interface, ifp);
570 babel_interface_nfo *babel_ifp;
571
572 babel_ifp = babel_get_if_nfo(ifp);
573 assert (babel_ifp != NULL);
574
575 babel_ifp->flags |= BABEL_IF_TIMESTAMPS;
576 return CMD_SUCCESS;
577 }
578
579 DEFUN (no_babel_set_enable_timestamps,
580 no_babel_set_enable_timestamps_cmd,
581 "no babel enable-timestamps",
582 NO_STR
583 "Babel interface commands\n"
584 "Disable timestamps\n")
585 {
586 VTY_DECLVAR_CONTEXT(interface, ifp);
587 babel_interface_nfo *babel_ifp;
588
589 babel_ifp = babel_get_if_nfo(ifp);
590 assert (babel_ifp != NULL);
591
592 babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS;
593 return CMD_SUCCESS;
594 }
595
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"
601 "Number\n")
602 {
603 VTY_DECLVAR_CONTEXT(interface, ifp);
604 babel_interface_nfo *babel_ifp;
605 int channel;
606
607 channel = strtoul(argv[2]->arg, NULL, 10);
608
609 babel_ifp = babel_get_if_nfo(ifp);
610 assert (babel_ifp != NULL);
611
612 babel_ifp->channel = channel;
613 return CMD_SUCCESS;
614 }
615
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")
622 {
623 VTY_DECLVAR_CONTEXT(interface, ifp);
624 babel_interface_nfo *babel_ifp;
625
626 babel_ifp = babel_get_if_nfo(ifp);
627 assert (babel_ifp != NULL);
628
629 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
630 return CMD_SUCCESS;
631 }
632
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")
639 {
640 VTY_DECLVAR_CONTEXT(interface, ifp);
641 babel_interface_nfo *babel_ifp;
642
643 babel_ifp = babel_get_if_nfo(ifp);
644 assert (babel_ifp != NULL);
645
646 babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
647 return CMD_SUCCESS;
648 }
649
650 /* This should be no more than half the hello interval, so that hellos
651 aren't sent late. The result is in milliseconds. */
652 unsigned
653 jitter(babel_interface_nfo *babel_ifp, int urgent)
654 {
655 unsigned interval = babel_ifp->hello_interval;
656 if(urgent)
657 interval = MIN(interval, 100);
658 else
659 interval = MIN(interval, 4000);
660 return roughly(interval) / 4;
661 }
662
663 unsigned
664 update_jitter(babel_interface_nfo *babel_ifp, int urgent)
665 {
666 unsigned interval = babel_ifp->hello_interval;
667 if(urgent)
668 interval = MIN(interval, 100);
669 else
670 interval = MIN(interval, 4000);
671 return roughly(interval);
672 }
673
674 /* calculate babeld's specific datas of an interface (change when the interface
675 change) */
676 static int
677 interface_recalculate(struct interface *ifp)
678 {
679 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
680 unsigned char *tmp = NULL;
681 int mtu, rc;
682 struct ipv6_mreq mreq;
683
684 if (!IS_ENABLE(ifp))
685 return -1;
686
687 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
688 interface_reset(ifp);
689 return -1;
690 }
691
692 babel_ifp->flags |= BABEL_IF_IS_UP;
693
694 mtu = MIN(ifp->mtu, ifp->mtu6);
695
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. */
700 if(mtu < 128) {
701 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
702 mtu, ifp->name, ifp->ifindex);
703 mtu = 128;
704 }
705
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.");
712 free(tmp);
713 babel_ifp->bufsize = 0;
714 return -1;
715 }
716 tmp = NULL;
717
718 rc = resize_receive_buffer(mtu);
719 if(rc < 0)
720 zlog_warn("couldn't resize "
721 "receive buffer for interface %s (%d) (%d bytes).\n",
722 ifp->name, ifp->ifindex, mtu);
723
724 memset(&mreq, 0, sizeof(mreq));
725 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
726 mreq.ipv6mr_interface = ifp->ifindex;
727
728 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
729 (char*)&mreq, sizeof(mreq));
730 if(rc < 0) {
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);
737 return -1;
738 }
739
740 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
741 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
742 send_hello(ifp);
743 send_request(ifp, NULL, 0);
744
745 update_interface_metric(ifp);
746
747 debugf(BABEL_DEBUG_COMMON,
748 "Upped interface %s (%s, cost=%d, channel=%d%s).",
749 ifp->name,
750 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
751 babel_ifp->cost,
752 babel_ifp->channel,
753 babel_ifp->ipv4 ? ", IPv4" : "");
754
755 if(rc > 0)
756 send_update(ifp, 0, NULL, 0);
757
758 return 1;
759 }
760
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. */
763 static int
764 interface_reset(struct interface *ifp)
765 {
766 int rc;
767 struct ipv6_mreq mreq;
768 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
769
770 if (!(babel_ifp->flags & BABEL_IF_IS_UP))
771 return 0;
772
773 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
774 babel_ifp->flags &= ~BABEL_IF_IS_UP;
775
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;
786
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));
793 if(rc < 0)
794 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
795 ifp->name, safe_strerror(errno));
796 }
797
798 update_interface_metric(ifp);
799
800 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
801 ifp->name,
802 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
803 babel_ifp->cost,
804 babel_ifp->ipv4 ? ", IPv4" : "");
805
806 return 1;
807 }
808
809 /* Send retraction to all, and reset all interfaces statistics. */
810 void
811 babel_interface_close_all(void)
812 {
813 struct interface *ifp = NULL;
814 struct listnode *linklist_node = NULL;
815
816 FOR_ALL_INTERFACES(ifp, linklist_node) {
817 if(!if_up(ifp))
818 continue;
819 send_wildcard_retraction(ifp);
820 /* Make sure that we expire quickly from our neighbours'
821 association caches. */
822 send_hello_noupdate(ifp, 10);
823 flushbuf(ifp);
824 usleep(roughly(1000));
825 gettime(&babel_now);
826 }
827 FOR_ALL_INTERFACES(ifp, linklist_node) {
828 if(!if_up(ifp))
829 continue;
830 /* Make sure they got it. */
831 send_wildcard_retraction(ifp);
832 send_hello_noupdate(ifp, 1);
833 flushbuf(ifp);
834 usleep(roughly(10000));
835 gettime(&babel_now);
836 interface_reset(ifp);
837 }
838 }
839
840 /* return "true" if address is one of our ipv6 addresses */
841 int
842 is_interface_ll_address(struct interface *ifp, const unsigned char *address)
843 {
844 struct connected *connected;
845 struct listnode *node;
846
847 if(!if_up(ifp))
848 return 0;
849
850 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
851 if(connected->address->family == AF_INET6 &&
852 memcmp(&connected->address->u.prefix6, address, 16) == 0)
853 return 1;
854 }
855
856 return 0;
857 }
858
859 static void
860 show_babel_interface_sub (struct vty *vty, struct interface *ifp)
861 {
862 int is_up;
863 babel_interface_nfo *babel_ifp;
864
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);
869
870 if (!IS_ENABLE(ifp))
871 {
872 vty_out (vty, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
873 return;
874 }
875 if (!is_up)
876 {
877 vty_out (vty, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
878 return;
879 }
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);
889 }
890
891 DEFUN (show_babel_interface,
892 show_babel_interface_cmd,
893 "show babel interface [IFNAME]",
894 SHOW_STR
895 "Babel information\n"
896 "Interface information\n"
897 "Interface\n")
898 {
899 struct interface *ifp;
900 struct listnode *node;
901
902 if (argc == 3)
903 {
904 for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp))
905 show_babel_interface_sub (vty, ifp);
906 return CMD_SUCCESS;
907 }
908 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
909 {
910 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
911 return CMD_WARNING;
912 }
913 show_babel_interface_sub (vty, ifp);
914 return CMD_SUCCESS;
915 }
916
917 static void
918 show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
919 {
920 vty_out (vty,
921 "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
922 "rtt %s rttcost %d%s.%s",
923 format_address(neigh->address),
924 neigh->ifp->name,
925 neigh->reach,
926 neighbour_rxcost(neigh),
927 neigh->txcost,
928 format_thousands(neigh->rtt),
929 neighbour_rttcost(neigh),
930 if_up(neigh->ifp) ? "" : " (down)",
931 VTY_NEWLINE);
932 }
933
934 DEFUN (show_babel_neighbour,
935 show_babel_neighbour_cmd,
936 "show babel neighbor [IFNAME]",
937 SHOW_STR
938 "Babel information\n"
939 "Print neighbors\n"
940 "Interface\n")
941 {
942 struct neighbour *neigh;
943 struct interface *ifp;
944
945 if (argc == 3) {
946 FOR_ALL_NEIGHBOURS(neigh) {
947 show_babel_neighbour_sub(vty, neigh);
948 }
949 return CMD_SUCCESS;
950 }
951 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
952 {
953 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
954 return CMD_WARNING;
955 }
956 FOR_ALL_NEIGHBOURS(neigh) {
957 if(ifp->ifindex == neigh->ifp->ifindex) {
958 show_babel_neighbour_sub(vty, neigh);
959 }
960 }
961 return CMD_SUCCESS;
962 }
963
964 static int
965 babel_prefix_eq(struct prefix *prefix, unsigned char *p, int plen)
966 {
967 if(prefix->family == AF_INET6) {
968 if(prefix->prefixlen != plen ||
969 memcmp(&prefix->u.prefix6, p, 16) != 0)
970 return 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)
974 return 0;
975 } else {
976 return 0;
977 }
978
979 return 1;
980 }
981
982 static void
983 show_babel_routes_sub(struct babel_route *route, struct vty *vty,
984 struct prefix *prefix)
985 {
986 const unsigned char *nexthop =
987 memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
988 NULL : route->nexthop;
989 char channels[100];
990
991 if(prefix && !babel_prefix_eq(prefix, route->src->prefix, route->src->plen))
992 return;
993
994 if(route->channels[0] == 0)
995 channels[0] = '\0';
996 else {
997 int k, j = 0;
998 snprintf(channels, 100, " chan (");
999 j = strlen(channels);
1000 for(k = 0; k < DIVERSITY_HOPS; k++) {
1001 if(route->channels[k] == 0)
1002 break;
1003 if(k > 0)
1004 channels[j++] = ',';
1005 snprintf(channels + j, 100 - j, "%d", route->channels[k]);
1006 j = strlen(channels);
1007 }
1008 snprintf(channels + j, 100 - j, ")");
1009 if(k == 0)
1010 channels[0] = '\0';
1011 }
1012
1013 vty_out(vty,
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),
1019 (int)route->seqno,
1020 channels,
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)" : "",
1028 VTY_NEWLINE);
1029 }
1030
1031 static void
1032 show_babel_xroutes_sub (struct xroute *xroute, struct vty *vty,
1033 struct prefix *prefix)
1034 {
1035 if(prefix && !babel_prefix_eq(prefix, xroute->prefix, xroute->plen))
1036 return;
1037
1038 vty_out(vty, "%s metric %d (exported)%s",
1039 format_prefix(xroute->prefix, xroute->plen),
1040 xroute->metric,
1041 VTY_NEWLINE);
1042 }
1043
1044 DEFUN (show_babel_route,
1045 show_babel_route_cmd,
1046 "show babel route",
1047 SHOW_STR
1048 "Babel information\n"
1049 "Babel internal routing table\n")
1050 {
1051 struct route_stream *routes = NULL;
1052 struct xroute_stream *xroutes = NULL;
1053 routes = route_stream(0);
1054 if(routes) {
1055 while(1) {
1056 struct babel_route *route = route_stream_next(routes);
1057 if(route == NULL)
1058 break;
1059 show_babel_routes_sub(route, vty, NULL);
1060 }
1061 route_stream_done(routes);
1062 } else {
1063 zlog_err("Couldn't allocate route stream.");
1064 }
1065 xroutes = xroute_stream();
1066 if(xroutes) {
1067 while(1) {
1068 struct xroute *xroute = xroute_stream_next(xroutes);
1069 if(xroute == NULL)
1070 break;
1071 show_babel_xroutes_sub(xroute, vty, NULL);
1072 }
1073 xroute_stream_done(xroutes);
1074 } else {
1075 zlog_err("Couldn't allocate route stream.");
1076 }
1077 return CMD_SUCCESS;
1078 }
1079
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>",
1083 SHOW_STR
1084 "Babel information\n"
1085 "Babel internal routing table\n"
1086 "IPv4 prefix <network>/<length>\n"
1087 "IPv6 prefix <network>/<length>\n")
1088 {
1089 struct route_stream *routes = NULL;
1090 struct xroute_stream *xroutes = NULL;
1091 struct prefix prefix;
1092 int ret;
1093
1094 ret = str2prefix(argv[3]->arg, &prefix);
1095 if(ret == 0) {
1096 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1097 return CMD_WARNING;
1098 }
1099
1100 routes = route_stream(0);
1101 if(routes) {
1102 while(1) {
1103 struct babel_route *route = route_stream_next(routes);
1104 if(route == NULL)
1105 break;
1106 show_babel_routes_sub(route, vty, &prefix);
1107 }
1108 route_stream_done(routes);
1109 } else {
1110 zlog_err("Couldn't allocate route stream.");
1111 }
1112 xroutes = xroute_stream();
1113 if(xroutes) {
1114 while(1) {
1115 struct xroute *xroute = xroute_stream_next(xroutes);
1116 if(xroute == NULL)
1117 break;
1118 show_babel_xroutes_sub(xroute, vty, &prefix);
1119 }
1120 xroute_stream_done(xroutes);
1121 } else {
1122 zlog_err("Couldn't allocate route stream.");
1123 }
1124 return CMD_SUCCESS;
1125 }
1126
1127
1128 DEFUN (show_babel_route_addr,
1129 show_babel_route_addr_cmd,
1130 "show babel route A.B.C.D",
1131 SHOW_STR
1132 "Babel information\n"
1133 "Babel internal routing table\n"
1134 "IPv4 address <network>/<length>\n")
1135 {
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;
1141 int ret;
1142
1143 ret = inet_aton (argv[3]->arg, &addr);
1144 if (ret <= 0) {
1145 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1146 return CMD_WARNING;
1147 }
1148
1149 /* Quagga has no convenient prefix constructors. */
1150 snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(addr), 32);
1151
1152 ret = str2prefix(buf, &prefix);
1153 if (ret == 0) {
1154 vty_out (vty, "%% Parse error -- this shouldn't happen%s", VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
1157
1158 routes = route_stream(0);
1159 if(routes) {
1160 while(1) {
1161 struct babel_route *route = route_stream_next(routes);
1162 if(route == NULL)
1163 break;
1164 show_babel_routes_sub(route, vty, &prefix);
1165 }
1166 route_stream_done(routes);
1167 } else {
1168 zlog_err("Couldn't allocate route stream.");
1169 }
1170 xroutes = xroute_stream();
1171 if(xroutes) {
1172 while(1) {
1173 struct xroute *xroute = xroute_stream_next(xroutes);
1174 if(xroute == NULL)
1175 break;
1176 show_babel_xroutes_sub(xroute, vty, &prefix);
1177 }
1178 xroute_stream_done(xroutes);
1179 } else {
1180 zlog_err("Couldn't allocate route stream.");
1181 }
1182 return CMD_SUCCESS;
1183 }
1184
1185 DEFUN (show_babel_route_addr6,
1186 show_babel_route_addr6_cmd,
1187 "show babel route X:X::X:X",
1188 SHOW_STR
1189 "Babel information\n"
1190 "Babel internal routing table\n"
1191 "IPv6 address <network>/<length>\n")
1192 {
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;
1199 int ret;
1200
1201 ret = inet_pton (AF_INET6, argv[3]->arg, &addr);
1202 if (ret <= 0) {
1203 vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
1204 return CMD_WARNING;
1205 }
1206
1207 /* Quagga has no convenient prefix constructors. */
1208 snprintf(buf, sizeof(buf), "%s/%d",
1209 inet_ntop(AF_INET6, &addr, buf1, sizeof(buf1)), 128);
1210
1211 ret = str2prefix(buf, &prefix);
1212 if (ret == 0) {
1213 vty_out (vty, "%% Parse error -- this shouldn't happen%s", VTY_NEWLINE);
1214 return CMD_WARNING;
1215 }
1216
1217 routes = route_stream(0);
1218 if(routes) {
1219 while(1) {
1220 struct babel_route *route = route_stream_next(routes);
1221 if(route == NULL)
1222 break;
1223 show_babel_routes_sub(route, vty, &prefix);
1224 }
1225 route_stream_done(routes);
1226 } else {
1227 zlog_err("Couldn't allocate route stream.");
1228 }
1229 xroutes = xroute_stream();
1230 if(xroutes) {
1231 while(1) {
1232 struct xroute *xroute = xroute_stream_next(xroutes);
1233 if(xroute == NULL)
1234 break;
1235 show_babel_xroutes_sub(xroute, vty, &prefix);
1236 }
1237 xroute_stream_done(xroutes);
1238 } else {
1239 zlog_err("Couldn't allocate route stream.");
1240 }
1241 return CMD_SUCCESS;
1242 }
1243
1244 DEFUN (show_babel_parameters,
1245 show_babel_parameters_cmd,
1246 "show babel parameters",
1247 SHOW_STR
1248 "Babel information\n"
1249 "Configuration information\n")
1250 {
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);
1255
1256 return CMD_SUCCESS;
1257 }
1258
1259 void
1260 babel_if_init ()
1261 {
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);
1265
1266 babel_enable_if = vector_init (1);
1267
1268 /* install interface node and commands */
1269 install_node (&babel_interface_node, interface_config_write);
1270 if_cmd_init();
1271
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);
1290
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);
1299 }
1300
1301 /* hooks: functions called respectively when struct interface is
1302 created or deleted. */
1303 static int
1304 babel_if_new_hook (struct interface *ifp)
1305 {
1306 ifp->info = babel_interface_allocate();
1307 return 0;
1308 }
1309
1310 static int
1311 babel_if_delete_hook (struct interface *ifp)
1312 {
1313 babel_interface_free(ifp->info);
1314 ifp->info = NULL;
1315 return 0;
1316 }
1317
1318 /* Output an "interface" section for each of the known interfaces with
1319 babeld-specific statement lines where appropriate. */
1320 static int
1321 interface_config_write (struct vty *vty)
1322 {
1323 struct listnode *node;
1324 struct interface *ifp;
1325 int write = 0;
1326
1327 for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) {
1328 vty_out (vty, "interface %s%s", ifp->name,
1329 VTY_NEWLINE);
1330 if (ifp->desc)
1331 vty_out (vty, " description %s%s", ifp->desc,
1332 VTY_NEWLINE);
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))
1336 {
1337 vty_out (vty, " babel wired%s", VTY_NEWLINE);
1338 write++;
1339 }
1340 if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
1341 {
1342 vty_out (vty, " babel hello-interval %u%s", babel_ifp->hello_interval, VTY_NEWLINE);
1343 write++;
1344 }
1345 if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
1346 {
1347 vty_out (vty, " babel update-interval %u%s", babel_ifp->update_interval, VTY_NEWLINE);
1348 write++;
1349 }
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);
1354 write++;
1355 }
1356 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRED) {
1357 vty_out (vty, " babel rxcost %u%s", babel_ifp->cost, VTY_NEWLINE);
1358 write++;
1359 }
1360 if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) {
1361 vty_out (vty, " babel channel interfering%s", VTY_NEWLINE);
1362 write++;
1363 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_NONINTERFERING) {
1364 vty_out (vty, " babel channel %d%s", babel_ifp->channel,
1365 VTY_NEWLINE);
1366 write++;
1367 }
1368 } else {
1369 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
1370 vty_out (vty, " babel split-horizon%s", VTY_NEWLINE);
1371 write++;
1372 }
1373 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRELESS) {
1374 vty_out (vty, " babel rxcost %u%s", babel_ifp->cost, VTY_NEWLINE);
1375 write++;
1376 }
1377 if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) {
1378 vty_out (vty, " babel channel noninterfering%s", VTY_NEWLINE);
1379 write++;
1380 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_INTERFERING) {
1381 vty_out (vty, " babel channel %d%s", babel_ifp->channel,
1382 VTY_NEWLINE);
1383 write++;
1384 }
1385 }
1386 vty_out (vty, "!%s", VTY_NEWLINE);
1387 write++;
1388 }
1389 return write;
1390 }
1391
1392 /* Output a "network" statement line for each of the enabled interfaces. */
1393 int
1394 babel_enable_if_config_write (struct vty * vty)
1395 {
1396 unsigned int i, lines = 0;
1397 char *str;
1398
1399 for (i = 0; i < vector_active (babel_enable_if); i++)
1400 if ((str = vector_slot (babel_enable_if, i)) != NULL)
1401 {
1402 vty_out (vty, " network %s%s", str, VTY_NEWLINE);
1403 lines++;
1404 }
1405 return lines;
1406 }
1407
1408 /* functions to allocate or free memory for a babel_interface_nfo, filling
1409 needed fields */
1410 static babel_interface_nfo *
1411 babel_interface_allocate (void)
1412 {
1413 babel_interface_nfo *babel_ifp;
1414 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
1415 if(babel_ifp == NULL)
1416 return NULL;
1417
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);
1431
1432 return babel_ifp;
1433 }
1434
1435 static void
1436 babel_interface_free (babel_interface_nfo *babel_ifp)
1437 {
1438 XFREE(MTYPE_BABEL_IF, babel_ifp);
1439 }