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