]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_interface.c
babeld: change fprintf(stderr) in term of zlog_err.
[mirror_frr.git] / babeld / babel_interface.c
CommitLineData
5734509c
PJ
1/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18
19Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20
21Permission is hereby granted, free of charge, to any person obtaining a copy
22of this software and associated documentation files (the "Software"), to deal
23in the Software without restriction, including without limitation the rights
24to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25copies of the Software, and to permit persons to whom the Software is
26furnished to do so, subject to the following conditions:
27
28The above copyright notice and this permission notice shall be included in
29all copies or substantial portions of the Software.
30
31THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37THE SOFTWARE.
38*/
39
5734509c
PJ
40#include <zebra.h>
41#include "memory.h"
42#include "log.h"
43#include "command.h"
44#include "prefix.h"
45#include "vector.h"
46
47#include "babel_main.h"
48#include "util.h"
49#include "kernel.h"
50#include "babel_interface.h"
51#include "message.h"
52#include "route.h"
53#include "babel_zebra.h"
54
55
56static int babel_enable_if_lookup (const char *ifname);
57static int babel_enable_if_add (const char *ifname);
58static int babel_enable_if_delete (const char *ifname);
59static int interface_recalculate(struct interface *ifp);
60static int interface_reset(struct interface *ifp);
61static int babel_if_new_hook (struct interface *ifp);
62static int babel_if_delete_hook (struct interface *ifp);
63static int interface_config_write (struct vty *vty);
c7c53fa8 64static babel_interface_nfo * babel_interface_allocate (void);
5734509c
PJ
65static void babel_interface_free (babel_interface_nfo *bi);
66
67
68static vector babel_enable_if; /* enable interfaces (by cmd). */
69static struct cmd_node babel_interface_node = /* babeld's interface node. */
70{
71 INTERFACE_NODE,
72 "%s(config-if)# ",
73 1 /* VTYSH */
74};
75
76
77int
78babel_interface_up (int cmd, struct zclient *client, zebra_size_t length)
79{
80 struct stream *s = NULL;
81 struct interface *ifp = NULL;
82
83 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
84
85 s = zclient->ibuf;
86 ifp = zebra_interface_state_read(s);
87
88 if (ifp == NULL) {
89 return 0;
90 }
91
92 interface_recalculate(ifp);
93 return 0;
94}
95
96int
97babel_interface_down (int cmd, struct zclient *client, zebra_size_t length)
98{
99 struct stream *s = NULL;
100 struct interface *ifp = NULL;
101
102 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
103
104 s = zclient->ibuf;
105 ifp = zebra_interface_state_read(s);
106
107 if (ifp == NULL) {
108 return 0;
109 }
110
111 interface_reset(ifp);
112 return 0;
113}
114
115int
116babel_interface_add (int cmd, struct zclient *client, zebra_size_t length)
117{
118 struct interface *ifp = NULL;
119
120 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
121
122 /* read and add the interface in the iflist. */
123 ifp = zebra_interface_add_read (zclient->ibuf);
124
125 if (ifp == NULL) {
126 return 0;
127 }
128
129 interface_recalculate(ifp);
130
131 return 0;
132}
133
134int
135babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length)
136{
137 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
138 return 0;
139}
140
141int
142babel_interface_address_add (int cmd, struct zclient *client,
143 zebra_size_t length)
144{
145 babel_interface_nfo *babel_ifp;
146 struct connected *ifc;
147 struct prefix *prefix;
148
149 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
150
151 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
152 zclient->ibuf);
153
154 if (ifc == NULL)
155 return 0;
156
157 prefix = ifc->address;
158
159 if (prefix->family == AF_INET) {
160 flush_interface_routes(ifc->ifp, 0);
161 babel_ifp = babel_get_if_nfo(ifc->ifp);
162 if (babel_ifp->ipv4 == NULL) {
163 babel_ifp->ipv4 = malloc(4);
164 if (babel_ifp->ipv4 == NULL) {
165 zlog_err("not einough memory");
166 } else {
167 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
168 }
169 }
170 }
171
172 send_request(ifc->ifp, NULL, 0);
173 send_update(ifc->ifp, 0, NULL, 0);
174
175 return 0;
176}
177
178int
179babel_interface_address_delete (int cmd, struct zclient *client,
180 zebra_size_t length)
181{
182 babel_interface_nfo *babel_ifp;
183 struct connected *ifc;
184 struct prefix *prefix;
185
186 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
187
188 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
189 zclient->ibuf);
190
191 if (ifc == NULL)
192 return 0;
193
194 prefix = ifc->address;
195
196 if (prefix->family == AF_INET) {
197 flush_interface_routes(ifc->ifp, 0);
198 babel_ifp = babel_get_if_nfo(ifc->ifp);
199 if (babel_ifp->ipv4 != NULL
200 && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
201 free(babel_ifp->ipv4);
202 babel_ifp->ipv4 = NULL;
203 }
204 }
205
206 send_request(ifc->ifp, NULL, 0);
207 send_update(ifc->ifp, 0, NULL, 0);
208
209 return 0;
210}
211
212/* Lookup function. */
213static int
214babel_enable_if_lookup (const char *ifname)
215{
216 unsigned int i;
217 char *str;
218
219 for (i = 0; i < vector_active (babel_enable_if); i++)
220 if ((str = vector_slot (babel_enable_if, i)) != NULL)
221 if (strcmp (str, ifname) == 0)
222 return i;
223 return -1;
224}
225
226/* Add interface to babel_enable_if. */
227static int
228babel_enable_if_add (const char *ifname)
229{
230 int ret;
231 struct interface *ifp = NULL;
232
233 ret = babel_enable_if_lookup (ifname);
234 if (ret >= 0)
235 return -1;
236
237 vector_set (babel_enable_if, strdup (ifname));
238
239 ifp = if_lookup_by_name(ifname);
240 if (ifp != NULL)
241 babel_get_if_nfo(ifp)->flags |= BABEL_IF_IS_ENABLE;
242
243 return 1;
244}
245
246/* Delete interface from babel_enable_if. */
247static int
248babel_enable_if_delete (const char *ifname)
249{
250 int babel_enable_if_index;
251 char *str;
252 struct interface *ifp = NULL;
253
254 babel_enable_if_index = babel_enable_if_lookup (ifname);
255 if (babel_enable_if_index < 0)
256 return -1;
257
258 str = vector_slot (babel_enable_if, babel_enable_if_index);
259 free (str);
260 vector_unset (babel_enable_if, babel_enable_if_index);
261
262 ifp = if_lookup_by_name(ifname);
263 if (ifp != NULL)
264 babel_get_if_nfo(ifp)->flags &= ~BABEL_IF_IS_ENABLE;
265
266 return 1;
267}
268
269
270/* [Babel Command] Babel enable on specified interface or matched network. */
271DEFUN (babel_network,
272 babel_network_cmd,
273 "network IF_OR_ADDR",
274 "Babel enable on specified interface or network.\n"
275 "Interface or address")
276{
277 int ret;
278 struct prefix p;
279
280 ret = str2prefix (argv[0], &p);
281
282 /* Given string is: */
283 if (ret) /* an IPv4 or v6 network */
284 return CMD_ERR_NO_MATCH; /* not implemented yet */
285 else /* an interface name */
286 ret = babel_enable_if_add (argv[0]);
287
288 if (ret < 0) {
289 vty_out (vty, "There is same network configuration %s%s", argv[0],
290 VTY_NEWLINE);
291 return CMD_WARNING;
292 }
293
294 return CMD_SUCCESS;
295}
296
297/* [Babel Command] Babel enable on specified interface or matched network. */
298DEFUN (no_babel_network,
299 no_babel_network_cmd,
300 "no network IF_OR_ADDR",
301 NO_STR
302 "Babel enable on specified interface or network.\n"
303 "Interface or address")
304{
305 int ret;
306 struct prefix p;
307
308 ret = str2prefix (argv[0], &p);
309
310 /* Given string is: */
311 if (ret) /* an IPv4 or v6 network */
312 return CMD_ERR_NO_MATCH; /* not implemented yet */
313 else /* an interface name */
314 ret = babel_enable_if_delete (argv[0]);
315
316 if (ret < 0) {
317 vty_out (vty, "can't find network %s%s", argv[0],
318 VTY_NEWLINE);
319 return CMD_WARNING;
320 }
321
322 return CMD_SUCCESS;
323}
324
325/* [Interface Command] Tell the interface is wire. */
326DEFUN (babel_set_wired,
327 babel_set_wired_cmd,
328 "wired",
329 "Set this interface as wired (default: wireless).\n"
330 "No attributes")
331{
332 struct interface *ifp;
333 babel_interface_nfo *babel_ifp;
334
335 ifp = vty->index;
336 babel_ifp = babel_get_if_nfo(ifp);
337
338 assert (babel_ifp != NULL);
339 babel_ifp->flags |= BABEL_IF_WIRED;
340 return CMD_SUCCESS;
341}
342
343/* [Interface Command] Tell the interface is wireless (default). */
344DEFUN (babel_set_wireless,
345 babel_set_wireless_cmd,
346 "wireless",
347 NO_STR
348 "Set this interface as wireless (is default).\n"
349 "No attributes")
350{
351 struct interface *ifp;
352 babel_interface_nfo *babel_ifp;
353
354 ifp = vty->index;
355 babel_ifp = babel_get_if_nfo(ifp);
356
357 assert (babel_ifp != NULL);
358 babel_ifp->flags &= ~BABEL_IF_WIRED;
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 IPV6_STR
367 "Routing Information Protocol\n"
368 "Perform split horizon\n")
369{
370 struct interface *ifp;
371 babel_interface_nfo *babel_ifp;
372
373 ifp = vty->index;
374 babel_ifp = babel_get_if_nfo(ifp);
375
376 assert (babel_ifp != NULL);
377 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
378 return CMD_SUCCESS;
379}
380
381/* [Interface Command] Disable split horizon (default). */
382DEFUN (no_babel_split_horizon,
383 no_babel_split_horizon_cmd,
384 "no babel split-horizon",
385 NO_STR
386 IPV6_STR
387 "Routing Information Protocol\n"
388 "Perform split horizon\n")
389{
390 struct interface *ifp;
391 babel_interface_nfo *babel_ifp;
392
393 ifp = vty->index;
394 babel_ifp = babel_get_if_nfo(ifp);
395
396 assert (babel_ifp != NULL);
397 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
398 return CMD_SUCCESS;
399}
400
401/* [Interface Command]. */
402DEFUN (babel_set_hello_interval,
403 babel_set_hello_interval_cmd,
404 "hello interval <5-1000000>",
405 "Set interface's hello interval (default: 4000).\n"
406 "Value in miliseconds\n")
407{
408 struct interface *ifp;
409 babel_interface_nfo *babel_ifp;
410
411 int interval = atoi(argv[1]);
412
413 ifp = vty->index;
414 babel_ifp = babel_get_if_nfo(ifp);
415
416 assert (babel_ifp != NULL);
417 babel_ifp->hello_interval = interval;
418 return CMD_SUCCESS;
419}
420
421/* [Interface Command]. */
422DEFUN (babel_passive_interface,
423 babel_passive_interface_cmd,
424 "passive-interface",
425 "The daemon will only announce redistributed routes\n"
426 "Interface name\n")
427{
428 if (allow_duplicates) {
429 return CMD_WARNING;
430 }
431 parasitic = -1;
432 return CMD_SUCCESS;
433}
434
435/* [Interface Command]. */
436DEFUN (no_babel_passive_interface,
437 no_babel_passive_interface_cmd,
438 "no passive-interface",
439 NO_STR
440 "The daemon will announce all (filtred) routes\n"
441 "Interface name\n")
442{
443 parasitic = 0;
444 return CMD_SUCCESS;
445}
446
447
448int
449interface_idle(babel_interface_nfo *babel_ifp)
450{
451 return (idle_hello_interval > 0 &&
452 babel_ifp->activity_time < babel_now.tv_sec - idle_time);
453}
454
455/* This should be no more than half the hello interval, so that hellos
456 aren't sent late. The result is in milliseconds. */
457unsigned
458jitter(babel_interface_nfo *babel_ifp, int urgent)
459{
460 unsigned interval = babel_ifp->hello_interval;
461 if(urgent)
462 interval = MIN(interval, 100);
463 else
464 interval = MIN(interval, 4000);
465 return roughly(interval) / 4;
466}
467
468unsigned
469update_jitter(babel_interface_nfo *babel_ifp, int urgent)
470{
471 unsigned interval = babel_ifp->hello_interval;
472 if(urgent)
473 interval = MIN(interval, 100);
474 else
475 interval = MIN(interval, 4000);
476 return roughly(interval);
477}
478
479/* calculate babeld's specific datas of an interface (change when the interface
480 change) */
481static int
482interface_recalculate(struct interface *ifp)
483{
484 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
485 unsigned char *tmp = NULL;
486 int mtu, rc;
487 struct ipv6_mreq mreq;
488
489 mtu = MIN(ifp->mtu, ifp->mtu6);
490
491 /* We need to be able to fit at least two messages into a packet,
492 so MTUs below 116 require lower layer fragmentation. */
493 /* In IPv6, the minimum MTU is 1280, and every host must be able
494 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
495 if(mtu < 128) {
496 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
497 mtu, ifp->name, ifp->ifindex);
498 mtu = 128;
499 }
500
501 /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
502 babel_ifp->bufsize = mtu - sizeof(packet_header) - 60;
503 tmp = babel_ifp->sendbuf;
504 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
505 if(babel_ifp->sendbuf == NULL) {
4eedea55 506 zlog_err("Couldn't reallocate sendbuf.");
5734509c
PJ
507 free(tmp);
508 babel_ifp->bufsize = 0;
509 return -1;
510 }
511 tmp = NULL;
512
513 resize_receive_buffer(mtu);
514
515 if(!(babel_ifp->flags & BABEL_IF_WIRED)) { /* if (wired) */
516 babel_ifp->cost = 96;
517 babel_ifp->flags &= ~BABEL_IF_LQ;
518 } else {
519 babel_ifp->cost = 256;
520 babel_ifp->flags |= BABEL_IF_LQ;
521 }
522
523 babel_ifp->activity_time = babel_now.tv_sec;
524 /* Since the interface was marked as active above, the
525 idle_hello_interval cannot be the one being used here. */
526 babel_ifp->update_interval = babel_ifp->hello_interval * 4;
527
528 memset(&mreq, 0, sizeof(mreq));
529 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
530 mreq.ipv6mr_interface = ifp->ifindex;
531
532 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
533 (char*)&mreq, sizeof(mreq));
534 if(rc < 0) {
535 zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
536 ifp->name, safe_strerror(errno));
537 /* This is probably due to a missing link-local address,
538 so down this interface, and wait until the main loop
539 tries to up it again. */
540 interface_reset(ifp);
541 return -1;
542 }
543
544 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
545 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
546 send_hello(ifp);
547 send_request(ifp, NULL, 0);
548
549 update_interface_metric(ifp);
550
551 debugf(BABEL_DEBUG_COMMON,
552 "Upped network %s (%s, cost=%d%s).",
553 ifp->name,
554 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
555 babel_ifp->cost,
556 babel_ifp->ipv4 ? ", IPv4" : "");
557
558 if(rc > 0)
559 send_update(ifp, 0, NULL, 0);
560
561 /* Check and set if interface is enable. */
562 if (babel_enable_if_lookup(ifp->name) >= 0) {
563 babel_ifp->flags |= BABEL_IF_IS_ENABLE;
564 } else {
565 babel_ifp->flags &= ~BABEL_IF_IS_ENABLE;
566 }
567
568 return 1;
569}
570
571/* Reset the interface as it was new: it's not removed from the interface list,
572 and may be considered as a upped interface. */
573static int
574interface_reset(struct interface *ifp)
575{
576 int rc;
577 struct ipv6_mreq mreq;
578 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
579
580 flush_interface_routes(ifp, 0);
581 babel_ifp->buffered = 0;
582 babel_ifp->bufsize = 0;
583 free(babel_ifp->sendbuf);
584 babel_ifp->num_buffered_updates = 0;
585 babel_ifp->update_bufsize = 0;
586 if(babel_ifp->buffered_updates)
587 free(babel_ifp->buffered_updates);
588 babel_ifp->buffered_updates = NULL;
589 babel_ifp->sendbuf = NULL;
590
591 if(ifp->ifindex > 0) {
592 memset(&mreq, 0, sizeof(mreq));
593 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
594 mreq.ipv6mr_interface = ifp->ifindex;
595 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
596 (char*)&mreq, sizeof(mreq));
597 if(rc < 0)
598 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
599 ifp->name, safe_strerror(errno));
600 }
601
602 update_interface_metric(ifp);
603
604 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
605 ifp->name,
606 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
607 babel_ifp->cost,
608 babel_ifp->ipv4 ? ", IPv4" : "");
609
610 return 1;
611}
612
613/* Send retraction to all, and reset all interfaces statistics. */
614void
615babel_interface_close_all(void)
616{
617 struct interface *ifp = NULL;
618 struct listnode *linklist_node = NULL;
619
620 FOR_ALL_INTERFACES(ifp, linklist_node) {
621 if(!if_up(ifp))
622 continue;
623 send_wildcard_retraction(ifp);
624 /* Make sure that we expire quickly from our neighbours'
625 association caches. */
626 send_hello_noupdate(ifp, 10);
627 flushbuf(ifp);
628 usleep(roughly(1000));
629 gettime(&babel_now);
630 }
631 FOR_ALL_INTERFACES(ifp, linklist_node) {
632 if(!if_up(ifp))
633 continue;
634 /* Make sure they got it. */
635 send_wildcard_retraction(ifp);
636 send_hello_noupdate(ifp, 1);
637 flushbuf(ifp);
638 usleep(roughly(10000));
639 gettime(&babel_now);
640 interface_reset(ifp);
641 }
642}
643
644/* return "true" if address is one of our ipv6 addresses */
645int
646is_interface_ll_address(struct interface *ifp, const unsigned char *address)
647{
648 struct connected *connected;
649 struct listnode *node;
650
651 if(!if_up(ifp))
652 return 0;
653
654 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
655 if(connected->address->family == AF_INET6 &&
656 memcmp(&connected->address->u.prefix6, address, 16) == 0)
657 return 1;
658 }
659
660 return 0;
661}
662
d4e46e68
DO
663static void
664show_babel_interface_sub (struct vty *vty, struct interface *ifp)
665{
666 int is_up;
667 babel_interface_nfo *babel_ifp;
668
669 vty_out (vty, "%s is %s%s", ifp->name,
670 ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE);
671 vty_out (vty, " ifindex %u, MTU %u bytes %s%s",
672 ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE);
673
674 if (babel_enable_if_lookup (ifp->name) < 0)
675 {
676 vty_out (vty, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
677 return;
678 }
679 if (!is_up)
680 {
681 vty_out (vty, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
682 return;
683 }
684 babel_ifp = babel_get_if_nfo (ifp);
685 vty_out (vty, " Babel protocol is running on this interface%s", VTY_NEWLINE);
686 vty_out (vty, " Operating mode is \"%s\"%s",
687 CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE);
688 vty_out (vty, " Split horizon mode is %s%s",
689 CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE);
690 vty_out (vty, " Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE);
691}
692
693DEFUN (show_babel_interface,
694 show_babel_interface_cmd,
695 "show babel interface [INTERFACE]",
696 SHOW_STR
697 IP_STR
698 "Babel information\n"
699 "Interface information\n"
700 "Interface name\n")
701{
702 struct interface *ifp;
703 struct listnode *node;
704
705 if (argc == 0)
706 {
707 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
708 show_babel_interface_sub (vty, ifp);
709 return CMD_SUCCESS;
710 }
711 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
712 {
713 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
714 return CMD_WARNING;
715 }
716 show_babel_interface_sub (vty, ifp);
717 return CMD_SUCCESS;
718}
5734509c
PJ
719
720void
721babel_if_init ()
722{
723 /* initialize interface list */
724 if_init();
725 if_add_hook (IF_NEW_HOOK, babel_if_new_hook);
726 if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
727
728 babel_enable_if = vector_init (1);
729
730 /* install interface node and commands */
731 install_element (CONFIG_NODE, &interface_cmd);
732 install_element (CONFIG_NODE, &no_interface_cmd);
733 install_node (&babel_interface_node, interface_config_write);
734 install_default(INTERFACE_NODE);
735 install_element(INTERFACE_NODE, &interface_cmd);
736 install_element(INTERFACE_NODE, &no_interface_cmd);
737
738 install_element(BABEL_NODE, &babel_network_cmd);
739 install_element(BABEL_NODE, &no_babel_network_cmd);
740 install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
741 install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
742 install_element(INTERFACE_NODE, &babel_set_wired_cmd);
743 install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
744 install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
745 install_element(INTERFACE_NODE, &babel_passive_interface_cmd);
746 install_element(INTERFACE_NODE, &no_babel_passive_interface_cmd);
d4e46e68
DO
747
748 /* "show babel ..." commands */
749 install_element (VIEW_NODE, &show_babel_interface_cmd);
750 install_element (ENABLE_NODE, &show_babel_interface_cmd);
5734509c
PJ
751}
752
753/* hooks: functions called respectively when struct interface is
754 created or deleted. */
755static int
756babel_if_new_hook (struct interface *ifp)
757{
758 ifp->info = babel_interface_allocate();
759 return 0;
760}
761
762static int
763babel_if_delete_hook (struct interface *ifp)
764{
765 babel_interface_free(ifp->info);
766 ifp->info = NULL;
767 return 0;
768}
769
770/* Configuration write function for babeld. */
771static int
772interface_config_write (struct vty *vty)
773{
774 struct listnode *node;
775 struct interface *ifp;
5734509c
PJ
776 int write = 0;
777
778 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) {
5734509c
PJ
779 /* Do not display the interface if there is no configuration about it */
780 if (ifp->desc == NULL)
781 continue;
782
783 vty_out (vty, "interface %s%s", ifp->name,
784 VTY_NEWLINE);
785 if (ifp->desc)
786 vty_out (vty, " description %s%s", ifp->desc,
787 VTY_NEWLINE);
788
789 /* TODO: to be completed... */
790
791 vty_out (vty, "!%s", VTY_NEWLINE);
792
793 write++;
794 }
795 return write;
796}
797
798/* functions to allocate or free memory for a babel_interface_nfo, filling
799 needed fields */
800static babel_interface_nfo *
c7c53fa8 801babel_interface_allocate (void)
5734509c
PJ
802{
803 babel_interface_nfo *babel_ifp;
804 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
805 if(babel_ifp == NULL)
806 return NULL;
807
808 /* Here are set the default values for an interface. */
809 memset(babel_ifp, 0, sizeof(babel_interface_nfo));
810 /* All flags are unset */
811 babel_ifp->activity_time = babel_now.tv_sec;
812 babel_ifp->bucket_time = babel_now.tv_sec;
813 babel_ifp->bucket = BUCKET_TOKENS_MAX;
814 babel_ifp->hello_seqno = (random() & 0xFFFF);
815 babel_ifp->hello_interval = BABELD_DEFAULT_HELLO_INTERVAL;
816
817 return babel_ifp;
818}
819
820static void
821babel_interface_free (babel_interface_nfo *babel_ifp)
822{
823 XFREE(MTYPE_BABEL_IF, babel_ifp);
824}