]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_interface.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[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_memory.h"
43 #include "babel_errors.h"
44
45 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
46
47 static int babel_enable_if_lookup (const char *ifname);
48 static int babel_enable_if_add (const char *ifname);
49 static int babel_enable_if_delete (const char *ifname);
50 static int interface_recalculate(struct interface *ifp);
51 static int interface_reset(struct interface *ifp);
52 static int babel_if_new_hook (struct interface *ifp);
53 static int babel_if_delete_hook (struct interface *ifp);
54 static int interface_config_write (struct vty *vty);
55 static babel_interface_nfo * babel_interface_allocate (void);
56 static void babel_interface_free (babel_interface_nfo *bi);
57
58
59 static vector babel_enable_if; /* enable interfaces (by cmd). */
60 static struct cmd_node babel_interface_node = /* babeld's interface node. */
61 {
62 INTERFACE_NODE,
63 "%s(config-if)# ",
64 1 /* VTYSH */
65 };
66
67
68 int
69 babel_interface_up (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
70 {
71 struct stream *s = NULL;
72 struct interface *ifp = NULL;
73
74 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
75
76 s = zclient->ibuf;
77 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
78
79 if (ifp == NULL) {
80 return 0;
81 }
82
83 interface_recalculate(ifp);
84 return 0;
85 }
86
87 int
88 babel_interface_down (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
89 {
90 struct stream *s = NULL;
91 struct interface *ifp = NULL;
92
93 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
94
95 s = zclient->ibuf;
96 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
97
98 if (ifp == NULL) {
99 return 0;
100 }
101
102 interface_reset(ifp);
103 return 0;
104 }
105
106 int
107 babel_interface_add (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
108 {
109 struct interface *ifp = NULL;
110
111 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
112
113 /* read and add the interface in the iflist. */
114 ifp = zebra_interface_add_read (zclient->ibuf, vrf);
115
116 if (ifp == NULL) {
117 return 0;
118 }
119
120 interface_recalculate(ifp);
121 return 0;
122 }
123
124 int
125 babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf)
126 {
127 struct interface *ifp;
128 struct stream *s;
129
130 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
131
132 s = zclient->ibuf;
133 ifp = zebra_interface_state_read(s, vrf); /* it updates iflist */
134
135 if (ifp == NULL)
136 return 0;
137
138 if (IS_ENABLE(ifp))
139 interface_reset(ifp);
140
141 /* To support pseudo interface do not free interface structure. */
142 /* if_delete(ifp); */
143 if_set_index(ifp, IFINDEX_INTERNAL);
144
145 return 0;
146 }
147
148 int
149 babel_interface_address_add (int cmd, struct zclient *client,
150 zebra_size_t length, vrf_id_t vrf)
151 {
152 babel_interface_nfo *babel_ifp;
153 struct connected *ifc;
154 struct prefix *prefix;
155
156 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
157
158 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
159 zclient->ibuf, vrf);
160
161 if (ifc == NULL)
162 return 0;
163
164 prefix = ifc->address;
165
166 if (prefix->family == AF_INET) {
167 flush_interface_routes(ifc->ifp, 0);
168 babel_ifp = babel_get_if_nfo(ifc->ifp);
169 if (babel_ifp->ipv4 == NULL) {
170 babel_ifp->ipv4 = malloc(4);
171 if (babel_ifp->ipv4 == NULL) {
172 flog_err(EC_BABEL_MEMORY, "not enough memory");
173 } else {
174 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
175 }
176 }
177 }
178
179 send_request(ifc->ifp, NULL, 0);
180 send_update(ifc->ifp, 0, NULL, 0);
181
182 return 0;
183 }
184
185 int
186 babel_interface_address_delete (int cmd, struct zclient *client,
187 zebra_size_t length, vrf_id_t vrf)
188 {
189 babel_interface_nfo *babel_ifp;
190 struct connected *ifc;
191 struct prefix *prefix;
192
193 debugf(BABEL_DEBUG_IF, "receive a 'interface address delete'");
194
195 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
196 zclient->ibuf, vrf);
197
198 if (ifc == NULL)
199 return 0;
200
201 prefix = ifc->address;
202
203 if (prefix->family == AF_INET) {
204 flush_interface_routes(ifc->ifp, 0);
205 babel_ifp = babel_get_if_nfo(ifc->ifp);
206 if (babel_ifp->ipv4 != NULL
207 && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
208 free(babel_ifp->ipv4);
209 babel_ifp->ipv4 = NULL;
210 }
211 }
212
213 send_request(ifc->ifp, NULL, 0);
214 send_update(ifc->ifp, 0, NULL, 0);
215
216 return 0;
217 }
218
219 /* Lookup function. */
220 static int
221 babel_enable_if_lookup (const char *ifname)
222 {
223 unsigned int i;
224 char *str;
225
226 for (i = 0; i < vector_active (babel_enable_if); i++)
227 if ((str = vector_slot (babel_enable_if, i)) != NULL)
228 if (strcmp (str, ifname) == 0)
229 return i;
230 return -1;
231 }
232
233 /* Add interface to babel_enable_if. */
234 static int
235 babel_enable_if_add (const char *ifname)
236 {
237 int ret;
238 struct interface *ifp = NULL;
239
240 ret = babel_enable_if_lookup (ifname);
241 if (ret >= 0)
242 return -1;
243
244 vector_set (babel_enable_if, strdup (ifname));
245
246 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
247 if (ifp != NULL)
248 interface_recalculate(ifp);
249
250 return 1;
251 }
252
253 /* Delete interface from babel_enable_if. */
254 static int
255 babel_enable_if_delete (const char *ifname)
256 {
257 int babel_enable_if_index;
258 char *str;
259 struct interface *ifp = NULL;
260
261 babel_enable_if_index = babel_enable_if_lookup (ifname);
262 if (babel_enable_if_index < 0)
263 return -1;
264
265 str = vector_slot (babel_enable_if, babel_enable_if_index);
266 free (str);
267 vector_unset (babel_enable_if, babel_enable_if_index);
268
269 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
270 if (ifp != NULL)
271 interface_reset(ifp);
272
273 return 1;
274 }
275
276 /* [Babel Command] Babel enable on specified interface or matched network. */
277 DEFUN (babel_network,
278 babel_network_cmd,
279 "network IF_OR_ADDR",
280 "Enable Babel protocol on specified interface or network.\n"
281 "Interface or address\n")
282 {
283 int ret;
284 struct prefix p;
285
286 ret = str2prefix (argv[1]->arg, &p);
287
288 /* Given string is: */
289 if (ret) /* an IPv4 or v6 network */
290 return CMD_ERR_NO_MATCH; /* not implemented yet */
291 else /* an interface name */
292 ret = babel_enable_if_add (argv[1]->arg);
293
294 if (ret < 0) {
295 vty_out (vty, "There is same network configuration %s\n",
296 argv[1]->arg);
297 return CMD_WARNING;
298 }
299
300 return CMD_SUCCESS;
301 }
302
303 /* [Babel Command] Babel enable on specified interface or matched network. */
304 DEFUN (no_babel_network,
305 no_babel_network_cmd,
306 "no network IF_OR_ADDR",
307 NO_STR
308 "Disable Babel protocol on specified interface or network.\n"
309 "Interface or address\n")
310 {
311 int ret;
312 struct prefix p;
313
314 ret = str2prefix (argv[2]->arg, &p);
315
316 /* Given string is: */
317 if (ret) /* an IPv4 or v6 network */
318 return CMD_ERR_NO_MATCH; /* not implemented yet */
319 else /* an interface name */
320 ret = babel_enable_if_delete (argv[2]->arg);
321
322 if (ret < 0) {
323 vty_out (vty, "can't find network %s\n",argv[2]->arg);
324 return CMD_WARNING_CONFIG_FAILED;
325 }
326
327 return CMD_SUCCESS;
328 }
329
330 /* There are a number of interface parameters that must be changed when
331 an interface becomes wired/wireless. In Quagga, they cannot be
332 configured separately. */
333
334 static void
335 babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
336 {
337 if(wired) {
338 babel_ifp->flags |= BABEL_IF_WIRED;
339 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
340 babel_ifp->cost = BABEL_DEFAULT_RXCOST_WIRED;
341 babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
342 babel_ifp->flags &= ~BABEL_IF_LQ;
343 } else {
344 babel_ifp->flags &= ~BABEL_IF_WIRED;
345 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
346 babel_ifp->cost = BABEL_DEFAULT_RXCOST_WIRELESS;
347 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
348 babel_ifp->flags |= BABEL_IF_LQ;
349 }
350
351 }
352
353 /* [Interface Command] Tell the interface is wire. */
354 DEFUN (babel_set_wired,
355 babel_set_wired_cmd,
356 "babel wired",
357 "Babel interface commands\n"
358 "Enable wired optimizations\n")
359 {
360 VTY_DECLVAR_CONTEXT(interface, ifp);
361 babel_interface_nfo *babel_ifp;
362
363 babel_ifp = babel_get_if_nfo(ifp);
364
365 assert (babel_ifp != NULL);
366 babel_set_wired_internal(babel_ifp, 1);
367 return CMD_SUCCESS;
368 }
369
370 /* [Interface Command] Tell the interface is wireless (default). */
371 DEFUN (babel_set_wireless,
372 babel_set_wireless_cmd,
373 "babel wireless",
374 "Babel interface commands\n"
375 "Disable wired optimizations (assume wireless)\n")
376 {
377 VTY_DECLVAR_CONTEXT(interface, ifp);
378 babel_interface_nfo *babel_ifp;
379
380 babel_ifp = babel_get_if_nfo(ifp);
381
382 assert (babel_ifp != NULL);
383 babel_set_wired_internal(babel_ifp, 0);
384 return CMD_SUCCESS;
385 }
386
387 /* [Interface Command] Enable split horizon. */
388 DEFUN (babel_split_horizon,
389 babel_split_horizon_cmd,
390 "babel split-horizon",
391 "Babel interface commands\n"
392 "Enable split horizon processing\n")
393 {
394 VTY_DECLVAR_CONTEXT(interface, ifp);
395 babel_interface_nfo *babel_ifp;
396
397 babel_ifp = babel_get_if_nfo(ifp);
398
399 assert (babel_ifp != NULL);
400 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
401 return CMD_SUCCESS;
402 }
403
404 /* [Interface Command] Disable split horizon (default). */
405 DEFUN (no_babel_split_horizon,
406 no_babel_split_horizon_cmd,
407 "no babel split-horizon",
408 NO_STR
409 "Babel interface commands\n"
410 "Disable split horizon processing\n")
411 {
412 VTY_DECLVAR_CONTEXT(interface, ifp);
413 babel_interface_nfo *babel_ifp;
414
415 babel_ifp = babel_get_if_nfo(ifp);
416
417 assert (babel_ifp != NULL);
418 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
419 return CMD_SUCCESS;
420 }
421
422 /* [Interface Command]. */
423 DEFUN (babel_set_hello_interval,
424 babel_set_hello_interval_cmd,
425 "babel hello-interval (20-655340)",
426 "Babel interface commands\n"
427 "Time between scheduled hellos\n"
428 "Milliseconds\n")
429 {
430 VTY_DECLVAR_CONTEXT(interface, ifp);
431 babel_interface_nfo *babel_ifp;
432 int interval;
433
434 interval = strtoul(argv[2]->arg, NULL, 10);
435
436 babel_ifp = babel_get_if_nfo(ifp);
437 assert (babel_ifp != NULL);
438
439 babel_ifp->hello_interval = interval;
440 return CMD_SUCCESS;
441 }
442
443 /* [Interface Command]. */
444 DEFUN (babel_set_update_interval,
445 babel_set_update_interval_cmd,
446 "babel update-interval (20-655340)",
447 "Babel interface commands\n"
448 "Time between scheduled updates\n"
449 "Milliseconds\n")
450 {
451 VTY_DECLVAR_CONTEXT(interface, ifp);
452 babel_interface_nfo *babel_ifp;
453 int interval;
454
455 interval = strtoul(argv[2]->arg, NULL, 10);
456
457 babel_ifp = babel_get_if_nfo(ifp);
458 assert (babel_ifp != NULL);
459
460 babel_ifp->update_interval = interval;
461 return CMD_SUCCESS;
462 }
463
464 DEFUN (babel_set_rxcost,
465 babel_set_rxcost_cmd,
466 "babel rxcost (1-65534)",
467 "Babel interface commands\n"
468 "Rxcost multiplier\n"
469 "Units\n")
470 {
471 VTY_DECLVAR_CONTEXT(interface, ifp);
472 babel_interface_nfo *babel_ifp;
473 int rxcost;
474
475 rxcost = strtoul(argv[2]->arg, NULL, 10);
476
477 babel_ifp = babel_get_if_nfo(ifp);
478 assert (babel_ifp != NULL);
479
480 babel_ifp->cost = rxcost;
481 return CMD_SUCCESS;
482 }
483
484 DEFUN (babel_set_rtt_decay,
485 babel_set_rtt_decay_cmd,
486 "babel rtt-decay (1-256)",
487 "Babel interface commands\n"
488 "Decay factor for exponential moving average of RTT samples\n"
489 "Units of 1/256\n")
490 {
491 VTY_DECLVAR_CONTEXT(interface, ifp);
492 babel_interface_nfo *babel_ifp;
493 int decay;
494
495 decay = strtoul(argv[2]->arg, NULL, 10);
496
497 babel_ifp = babel_get_if_nfo(ifp);
498 assert (babel_ifp != NULL);
499
500 babel_ifp->rtt_decay = decay;
501 return CMD_SUCCESS;
502 }
503
504 DEFUN (babel_set_rtt_min,
505 babel_set_rtt_min_cmd,
506 "babel rtt-min (1-65535)",
507 "Babel interface commands\n"
508 "Minimum RTT starting for increasing cost\n"
509 "Milliseconds\n")
510 {
511 VTY_DECLVAR_CONTEXT(interface, ifp);
512 babel_interface_nfo *babel_ifp;
513 int rtt;
514
515 rtt = strtoul(argv[2]->arg, NULL, 10);
516
517 babel_ifp = babel_get_if_nfo(ifp);
518 assert (babel_ifp != NULL);
519
520 babel_ifp->rtt_min = rtt;
521 return CMD_SUCCESS;
522 }
523
524 DEFUN (babel_set_rtt_max,
525 babel_set_rtt_max_cmd,
526 "babel rtt-max (1-65535)",
527 "Babel interface commands\n"
528 "Maximum RTT\n"
529 "Milliseconds\n")
530 {
531 VTY_DECLVAR_CONTEXT(interface, ifp);
532 babel_interface_nfo *babel_ifp;
533 int rtt;
534
535 rtt = strtoul(argv[2]->arg, NULL, 10);
536
537 babel_ifp = babel_get_if_nfo(ifp);
538 assert (babel_ifp != NULL);
539
540 babel_ifp->rtt_max = rtt;
541 return CMD_SUCCESS;
542 }
543
544 DEFUN (babel_set_max_rtt_penalty,
545 babel_set_max_rtt_penalty_cmd,
546 "babel max-rtt-penalty (0-65535)",
547 "Babel interface commands\n"
548 "Maximum additional cost due to RTT\n"
549 "Milliseconds\n")
550 {
551 VTY_DECLVAR_CONTEXT(interface, ifp);
552 babel_interface_nfo *babel_ifp;
553 int penalty;
554
555 penalty = strtoul(argv[2]->arg, NULL, 10);
556
557 babel_ifp = babel_get_if_nfo(ifp);
558 assert (babel_ifp != NULL);
559
560 babel_ifp->max_rtt_penalty = penalty;
561 return CMD_SUCCESS;
562 }
563
564 DEFUN (babel_set_enable_timestamps,
565 babel_set_enable_timestamps_cmd,
566 "babel enable-timestamps",
567 "Babel interface commands\n"
568 "Enable timestamps\n")
569 {
570 VTY_DECLVAR_CONTEXT(interface, ifp);
571 babel_interface_nfo *babel_ifp;
572
573 babel_ifp = babel_get_if_nfo(ifp);
574 assert (babel_ifp != NULL);
575
576 babel_ifp->flags |= BABEL_IF_TIMESTAMPS;
577 return CMD_SUCCESS;
578 }
579
580 DEFUN (no_babel_set_enable_timestamps,
581 no_babel_set_enable_timestamps_cmd,
582 "no babel enable-timestamps",
583 NO_STR
584 "Babel interface commands\n"
585 "Disable timestamps\n")
586 {
587 VTY_DECLVAR_CONTEXT(interface, ifp);
588 babel_interface_nfo *babel_ifp;
589
590 babel_ifp = babel_get_if_nfo(ifp);
591 assert (babel_ifp != NULL);
592
593 babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS;
594 return CMD_SUCCESS;
595 }
596
597 DEFUN (babel_set_channel,
598 babel_set_channel_cmd,
599 "babel channel (1-254)",
600 "Babel interface commands\n"
601 "Channel number for diversity routing\n"
602 "Number\n")
603 {
604 VTY_DECLVAR_CONTEXT(interface, ifp);
605 babel_interface_nfo *babel_ifp;
606 int channel;
607
608 channel = strtoul(argv[2]->arg, NULL, 10);
609
610 babel_ifp = babel_get_if_nfo(ifp);
611 assert (babel_ifp != NULL);
612
613 babel_ifp->channel = channel;
614 return CMD_SUCCESS;
615 }
616
617 DEFUN (babel_set_channel_interfering,
618 babel_set_channel_interfering_cmd,
619 "babel channel interfering",
620 "Babel interface commands\n"
621 "Channel number for diversity routing\n"
622 "Mark channel as interfering\n")
623 {
624 VTY_DECLVAR_CONTEXT(interface, ifp);
625 babel_interface_nfo *babel_ifp;
626
627 babel_ifp = babel_get_if_nfo(ifp);
628 assert (babel_ifp != NULL);
629
630 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
631 return CMD_SUCCESS;
632 }
633
634 DEFUN (babel_set_channel_noninterfering,
635 babel_set_channel_noninterfering_cmd,
636 "babel channel noninterfering",
637 "Babel interface commands\n"
638 "Channel number for diversity routing\n"
639 "Mark channel as noninterfering\n")
640 {
641 VTY_DECLVAR_CONTEXT(interface, ifp);
642 babel_interface_nfo *babel_ifp;
643
644 babel_ifp = babel_get_if_nfo(ifp);
645 assert (babel_ifp != NULL);
646
647 babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
648 return CMD_SUCCESS;
649 }
650
651 /* This should be no more than half the hello interval, so that hellos
652 aren't sent late. The result is in milliseconds. */
653 unsigned
654 jitter(babel_interface_nfo *babel_ifp, int urgent)
655 {
656 unsigned interval = babel_ifp->hello_interval;
657 if(urgent)
658 interval = MIN(interval, 100);
659 else
660 interval = MIN(interval, 4000);
661 return roughly(interval) / 4;
662 }
663
664 unsigned
665 update_jitter(babel_interface_nfo *babel_ifp, int urgent)
666 {
667 unsigned interval = babel_ifp->hello_interval;
668 if(urgent)
669 interval = MIN(interval, 100);
670 else
671 interval = MIN(interval, 4000);
672 return roughly(interval);
673 }
674
675 /* calculate babeld's specific datas of an interface (change when the interface
676 change) */
677 static int
678 interface_recalculate(struct interface *ifp)
679 {
680 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
681 unsigned char *tmp = NULL;
682 int mtu, rc;
683 struct ipv6_mreq mreq;
684
685 if (!IS_ENABLE(ifp))
686 return -1;
687
688 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
689 interface_reset(ifp);
690 return -1;
691 }
692
693 babel_ifp->flags |= BABEL_IF_IS_UP;
694
695 mtu = MIN(ifp->mtu, ifp->mtu6);
696
697 /* We need to be able to fit at least two messages into a packet,
698 so MTUs below 116 require lower layer fragmentation. */
699 /* In IPv6, the minimum MTU is 1280, and every host must be able
700 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
701 if(mtu < 128) {
702 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
703 mtu, ifp->name, ifp->ifindex);
704 mtu = 128;
705 }
706
707 /* 4 for Babel header; 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
708 babel_ifp->bufsize = mtu - 4 - 60;
709 tmp = babel_ifp->sendbuf;
710 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
711 if(babel_ifp->sendbuf == NULL) {
712 flog_err(EC_BABEL_MEMORY, "Couldn't reallocate sendbuf.");
713 free(tmp);
714 babel_ifp->bufsize = 0;
715 return -1;
716 }
717 tmp = NULL;
718
719 rc = resize_receive_buffer(mtu);
720 if(rc < 0)
721 zlog_warn("couldn't resize "
722 "receive buffer for interface %s (%d) (%d bytes).\n",
723 ifp->name, ifp->ifindex, mtu);
724
725 memset(&mreq, 0, sizeof(mreq));
726 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
727 mreq.ipv6mr_interface = ifp->ifindex;
728
729 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
730 (char*)&mreq, sizeof(mreq));
731 if(rc < 0) {
732 flog_err_sys(EC_LIB_SOCKET,
733 "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
734 ifp->name, safe_strerror(errno));
735 /* This is probably due to a missing link-local address,
736 so down this interface, and wait until the main loop
737 tries to up it again. */
738 interface_reset(ifp);
739 return -1;
740 }
741
742 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
743 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
744 send_hello(ifp);
745 send_request(ifp, NULL, 0);
746
747 update_interface_metric(ifp);
748
749 debugf(BABEL_DEBUG_COMMON,
750 "Upped interface %s (%s, cost=%d, channel=%d%s).",
751 ifp->name,
752 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
753 babel_ifp->cost,
754 babel_ifp->channel,
755 babel_ifp->ipv4 ? ", IPv4" : "");
756
757 if(rc > 0)
758 send_update(ifp, 0, NULL, 0);
759
760 return 1;
761 }
762
763 /* Reset the interface as it was new: it's not removed from the interface list,
764 and may be considered as a upped interface. */
765 static int
766 interface_reset(struct interface *ifp)
767 {
768 int rc;
769 struct ipv6_mreq mreq;
770 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
771
772 if (!(babel_ifp->flags & BABEL_IF_IS_UP))
773 return 0;
774
775 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
776 babel_ifp->flags &= ~BABEL_IF_IS_UP;
777
778 flush_interface_routes(ifp, 0);
779 babel_ifp->buffered = 0;
780 babel_ifp->bufsize = 0;
781 free(babel_ifp->sendbuf);
782 babel_ifp->num_buffered_updates = 0;
783 babel_ifp->update_bufsize = 0;
784 if(babel_ifp->buffered_updates)
785 free(babel_ifp->buffered_updates);
786 babel_ifp->buffered_updates = NULL;
787 babel_ifp->sendbuf = NULL;
788
789 if(ifp->ifindex > 0) {
790 memset(&mreq, 0, sizeof(mreq));
791 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
792 mreq.ipv6mr_interface = ifp->ifindex;
793 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
794 (char*)&mreq, sizeof(mreq));
795 if(rc < 0)
796 flog_err_sys(EC_LIB_SOCKET,
797 "setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
798 ifp->name, safe_strerror(errno));
799 }
800
801 update_interface_metric(ifp);
802
803 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
804 ifp->name,
805 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
806 babel_ifp->cost,
807 babel_ifp->ipv4 ? ", IPv4" : "");
808
809 return 1;
810 }
811
812 /* Send retraction to all, and reset all interfaces statistics. */
813 void
814 babel_interface_close_all(void)
815 {
816 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
817 struct interface *ifp = NULL;
818
819 FOR_ALL_INTERFACES(vrf, ifp) {
820 if(!if_up(ifp))
821 continue;
822 send_wildcard_retraction(ifp);
823 /* Make sure that we expire quickly from our neighbours'
824 association caches. */
825 send_hello_noupdate(ifp, 10);
826 flushbuf(ifp);
827 usleep(roughly(1000));
828 gettime(&babel_now);
829 }
830 FOR_ALL_INTERFACES(vrf, ifp) {
831 if(!if_up(ifp))
832 continue;
833 /* Make sure they got it. */
834 send_wildcard_retraction(ifp);
835 send_hello_noupdate(ifp, 1);
836 flushbuf(ifp);
837 usleep(roughly(10000));
838 gettime(&babel_now);
839 interface_reset(ifp);
840 }
841 }
842
843 /* return "true" if address is one of our ipv6 addresses */
844 int
845 is_interface_ll_address(struct interface *ifp, const unsigned char *address)
846 {
847 struct connected *connected;
848 struct listnode *node;
849
850 if(!if_up(ifp))
851 return 0;
852
853 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
854 if(connected->address->family == AF_INET6 &&
855 memcmp(&connected->address->u.prefix6, address, 16) == 0)
856 return 1;
857 }
858
859 return 0;
860 }
861
862 static void
863 show_babel_interface_sub (struct vty *vty, struct interface *ifp)
864 {
865 int is_up;
866 babel_interface_nfo *babel_ifp;
867
868 vty_out (vty, "%s is %s\n", ifp->name,
869 ((is_up = if_is_operative(ifp)) ? "up" : "down"));
870 vty_out (vty, " ifindex %u, MTU %u bytes %s\n",
871 ifp->ifindex, MIN(ifp->mtu, ifp->mtu6), if_flag_dump(ifp->flags));
872
873 if (!IS_ENABLE(ifp))
874 {
875 vty_out (vty, " Babel protocol is not enabled on this interface\n");
876 return;
877 }
878 if (!is_up)
879 {
880 vty_out (vty,
881 " Babel protocol is enabled, but not running on this interface\n");
882 return;
883 }
884 babel_ifp = babel_get_if_nfo (ifp);
885 vty_out (vty, " Babel protocol is running on this interface\n");
886 vty_out (vty, " Operating mode is \"%s\"\n",
887 CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless");
888 vty_out (vty, " Split horizon mode is %s\n",
889 CHECK_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off");
890 vty_out (vty, " Hello interval is %u ms\n", babel_ifp->hello_interval);
891 vty_out (vty, " Update interval is %u ms\n", babel_ifp->update_interval);
892 vty_out (vty, " Rxcost multiplier is %u\n", babel_ifp->cost);
893 }
894
895 DEFUN (show_babel_interface,
896 show_babel_interface_cmd,
897 "show babel interface [IFNAME]",
898 SHOW_STR
899 "Babel information\n"
900 "Interface information\n"
901 "Interface\n")
902 {
903 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
904 struct interface *ifp;
905
906 if (argc == 3)
907 {
908 FOR_ALL_INTERFACES (vrf, ifp)
909 show_babel_interface_sub (vty, ifp);
910 return CMD_SUCCESS;
911 }
912 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
913 {
914 vty_out (vty, "No such interface name\n");
915 return CMD_WARNING;
916 }
917 show_babel_interface_sub (vty, ifp);
918 return CMD_SUCCESS;
919 }
920
921 static void
922 show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
923 {
924 vty_out (vty,
925 "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
926 "rtt %s rttcost %d%s.\n",
927 format_address(neigh->address),
928 neigh->ifp->name,
929 neigh->reach,
930 neighbour_rxcost(neigh),
931 neigh->txcost,
932 format_thousands(neigh->rtt),
933 neighbour_rttcost(neigh),
934 if_up(neigh->ifp) ? "" : " (down)");
935 }
936
937 DEFUN (show_babel_neighbour,
938 show_babel_neighbour_cmd,
939 "show babel neighbor [IFNAME]",
940 SHOW_STR
941 "Babel information\n"
942 "Print neighbors\n"
943 "Interface\n")
944 {
945 struct neighbour *neigh;
946 struct interface *ifp;
947
948 if (argc == 3) {
949 FOR_ALL_NEIGHBOURS(neigh) {
950 show_babel_neighbour_sub(vty, neigh);
951 }
952 return CMD_SUCCESS;
953 }
954 if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
955 {
956 vty_out (vty, "No such interface name\n");
957 return CMD_WARNING;
958 }
959 FOR_ALL_NEIGHBOURS(neigh) {
960 if(ifp->ifindex == neigh->ifp->ifindex) {
961 show_babel_neighbour_sub(vty, neigh);
962 }
963 }
964 return CMD_SUCCESS;
965 }
966
967 static int
968 babel_prefix_eq(struct prefix *prefix, unsigned char *p, int plen)
969 {
970 if(prefix->family == AF_INET6) {
971 if(prefix->prefixlen != plen ||
972 memcmp(&prefix->u.prefix6, p, 16) != 0)
973 return 0;
974 } else if(prefix->family == AF_INET) {
975 if(plen < 96 || !v4mapped(p) || prefix->prefixlen != plen - 96 ||
976 memcmp(&prefix->u.prefix4, p + 12, 4) != 0)
977 return 0;
978 } else {
979 return 0;
980 }
981
982 return 1;
983 }
984
985 static void
986 show_babel_routes_sub(struct babel_route *route, struct vty *vty,
987 struct prefix *prefix)
988 {
989 const unsigned char *nexthop =
990 memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
991 NULL : route->nexthop;
992 char channels[100];
993
994 if(prefix && !babel_prefix_eq(prefix, route->src->prefix, route->src->plen))
995 return;
996
997 if(route->channels[0] == 0)
998 channels[0] = '\0';
999 else {
1000 int k, j = 0;
1001 snprintf(channels, 100, " chan (");
1002 j = strlen(channels);
1003 for(k = 0; k < DIVERSITY_HOPS; k++) {
1004 if(route->channels[k] == 0)
1005 break;
1006 if(k > 0)
1007 channels[j++] = ',';
1008 snprintf(channels + j, 100 - j, "%u", route->channels[k]);
1009 j = strlen(channels);
1010 }
1011 snprintf(channels + j, 100 - j, ")");
1012 if(k == 0)
1013 channels[0] = '\0';
1014 }
1015
1016 vty_out (vty,
1017 "%s metric %d refmetric %d id %s seqno %d%s age %d "
1018 "via %s neigh %s%s%s%s\n",
1019 format_prefix(route->src->prefix, route->src->plen),
1020 route_metric(route), route->refmetric,
1021 format_eui64(route->src->id),
1022 (int)route->seqno,
1023 channels,
1024 (int)(babel_now.tv_sec - route->time),
1025 route->neigh->ifp->name,
1026 format_address(route->neigh->address),
1027 nexthop ? " nexthop " : "",
1028 nexthop ? format_address(nexthop) : "",
1029 route->installed ? " (installed)" : route_feasible(route) ? " (feasible)" : "");
1030 }
1031
1032 static void
1033 show_babel_xroutes_sub (struct xroute *xroute, struct vty *vty,
1034 struct prefix *prefix)
1035 {
1036 if(prefix && !babel_prefix_eq(prefix, xroute->prefix, xroute->plen))
1037 return;
1038
1039 vty_out (vty, "%s metric %d (exported)\n",
1040 format_prefix(xroute->prefix, xroute->plen),
1041 xroute->metric);
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 flog_err(EC_BABEL_MEMORY, "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 flog_err(EC_BABEL_MEMORY, "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\n");
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 flog_err(EC_BABEL_MEMORY, "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 flog_err(EC_BABEL_MEMORY, "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\n");
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\n");
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 flog_err(EC_BABEL_MEMORY, "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 flog_err(EC_BABEL_MEMORY, "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\n");
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\n");
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 flog_err(EC_BABEL_MEMORY, "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 flog_err(EC_BABEL_MEMORY, "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 --\n");
1252 show_babel_main_configuration(vty);
1253 vty_out (vty, " -- distribution lists --\n");
1254 config_show_distribute(vty);
1255
1256 return CMD_SUCCESS;
1257 }
1258
1259 void
1260 babel_if_init ()
1261 {
1262 /* initialize interface list */
1263 hook_register_prio(if_add, 0, babel_if_new_hook);
1264 hook_register_prio(if_del, 0, 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 vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
1324 struct interface *ifp;
1325 int write = 0;
1326
1327 FOR_ALL_INTERFACES (vrf, ifp) {
1328 vty_frame (vty, "interface %s\n",ifp->name);
1329 if (ifp->desc)
1330 vty_out (vty, " description %s\n",ifp->desc);
1331 babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
1332 /* wireless is the default*/
1333 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
1334 {
1335 vty_out (vty, " babel wired\n");
1336 write++;
1337 }
1338 if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
1339 {
1340 vty_out (vty, " babel hello-interval %u\n",
1341 babel_ifp->hello_interval);
1342 write++;
1343 }
1344 if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
1345 {
1346 vty_out (vty, " babel update-interval %u\n",
1347 babel_ifp->update_interval);
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\n");
1354 write++;
1355 }
1356 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRED) {
1357 vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
1358 write++;
1359 }
1360 if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) {
1361 vty_out (vty, " babel channel interfering\n");
1362 write++;
1363 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_NONINTERFERING) {
1364 vty_out (vty, " babel channel %d\n",babel_ifp->channel);
1365 write++;
1366 }
1367 } else {
1368 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
1369 vty_out (vty, " babel split-horizon\n");
1370 write++;
1371 }
1372 if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRELESS) {
1373 vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
1374 write++;
1375 }
1376 if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) {
1377 vty_out (vty, " babel channel noninterfering\n");
1378 write++;
1379 } else if(babel_ifp->channel != BABEL_IF_CHANNEL_INTERFERING) {
1380 vty_out (vty, " babel channel %d\n",babel_ifp->channel);
1381 write++;
1382 }
1383 }
1384 vty_endframe (vty, "!\n");
1385 write++;
1386 }
1387 return write;
1388 }
1389
1390 /* Output a "network" statement line for each of the enabled interfaces. */
1391 int
1392 babel_enable_if_config_write (struct vty * vty)
1393 {
1394 unsigned int i, lines = 0;
1395 char *str;
1396
1397 for (i = 0; i < vector_active (babel_enable_if); i++)
1398 if ((str = vector_slot (babel_enable_if, i)) != NULL)
1399 {
1400 vty_out (vty, " network %s\n", str);
1401 lines++;
1402 }
1403 return lines;
1404 }
1405
1406 /* functions to allocate or free memory for a babel_interface_nfo, filling
1407 needed fields */
1408 static babel_interface_nfo *
1409 babel_interface_allocate (void)
1410 {
1411 babel_interface_nfo *babel_ifp;
1412 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
1413 if(babel_ifp == NULL)
1414 return NULL;
1415
1416 /* Here are set the default values for an interface. */
1417 memset(babel_ifp, 0, sizeof(babel_interface_nfo));
1418 /* All flags are unset */
1419 babel_ifp->bucket_time = babel_now.tv_sec;
1420 babel_ifp->bucket = BUCKET_TOKENS_MAX;
1421 babel_ifp->hello_seqno = (random() & 0xFFFF);
1422 babel_ifp->rtt_min = 10000;
1423 babel_ifp->rtt_max = 120000;
1424 babel_ifp->max_rtt_penalty = 150;
1425 babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL;
1426 babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL;
1427 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
1428 babel_set_wired_internal(babel_ifp, 0);
1429
1430 return babel_ifp;
1431 }
1432
1433 static void
1434 babel_interface_free (babel_interface_nfo *babel_ifp)
1435 {
1436 XFREE(MTYPE_BABEL_IF, babel_ifp);
1437 }