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