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