blob: 00d53bc67b1644a02f33e26c234ea434f9d6d1e0 [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
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
Paul Jakma57345092011-12-25 17:52:09 +010040#include <zebra.h>
41#include "memory.h"
42#include "log.h"
43#include "command.h"
44#include "prefix.h"
45#include "vector.h"
Matthieu Boutierd3351d12012-01-19 22:36:56 +010046#include "distribute.h"
Paul Jakma57345092011-12-25 17:52:09 +010047
48#include "babel_main.h"
49#include "util.h"
50#include "kernel.h"
51#include "babel_interface.h"
52#include "message.h"
53#include "route.h"
54#include "babel_zebra.h"
Matthieu Boutier297a55b2012-01-18 16:39:29 +010055#include "neighbour.h"
Matthieu Boutier1f39f462012-01-18 20:01:31 +010056#include "route.h"
57#include "xroute.h"
Paul Jakma57345092011-12-25 17:52:09 +010058
59
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +010060#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
61
Paul Jakma57345092011-12-25 17:52:09 +010062static int babel_enable_if_lookup (const char *ifname);
63static int babel_enable_if_add (const char *ifname);
64static int babel_enable_if_delete (const char *ifname);
65static int interface_recalculate(struct interface *ifp);
66static int interface_reset(struct interface *ifp);
67static int babel_if_new_hook (struct interface *ifp);
68static int babel_if_delete_hook (struct interface *ifp);
69static int interface_config_write (struct vty *vty);
Matthieu Boutierc7c53fa2012-01-08 16:43:08 +010070static babel_interface_nfo * babel_interface_allocate (void);
Paul Jakma57345092011-12-25 17:52:09 +010071static void babel_interface_free (babel_interface_nfo *bi);
72
73
74static vector babel_enable_if; /* enable interfaces (by cmd). */
75static struct cmd_node babel_interface_node = /* babeld's interface node. */
76{
77 INTERFACE_NODE,
78 "%s(config-if)# ",
79 1 /* VTYSH */
80};
81
82
83int
84babel_interface_up (int cmd, struct zclient *client, zebra_size_t length)
85{
86 struct stream *s = NULL;
87 struct interface *ifp = NULL;
88
89 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
90
91 s = zclient->ibuf;
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +010092 ifp = zebra_interface_state_read(s); /* it updates iflist */
Paul Jakma57345092011-12-25 17:52:09 +010093
94 if (ifp == NULL) {
95 return 0;
96 }
97
98 interface_recalculate(ifp);
99 return 0;
100}
101
102int
103babel_interface_down (int cmd, struct zclient *client, zebra_size_t length)
104{
105 struct stream *s = NULL;
106 struct interface *ifp = NULL;
107
108 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
109
110 s = zclient->ibuf;
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100111 ifp = zebra_interface_state_read(s); /* it updates iflist */
Paul Jakma57345092011-12-25 17:52:09 +0100112
113 if (ifp == NULL) {
114 return 0;
115 }
116
117 interface_reset(ifp);
118 return 0;
119}
120
121int
122babel_interface_add (int cmd, struct zclient *client, zebra_size_t length)
123{
124 struct interface *ifp = NULL;
125
126 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
127
128 /* read and add the interface in the iflist. */
129 ifp = zebra_interface_add_read (zclient->ibuf);
130
131 if (ifp == NULL) {
132 return 0;
133 }
134
135 interface_recalculate(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100136 return 0;
137}
138
139int
140babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length)
141{
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100142 struct interface *ifp;
143 struct stream *s;
144
Paul Jakma57345092011-12-25 17:52:09 +0100145 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100146
147 s = zclient->ibuf;
148 ifp = zebra_interface_state_read(s); /* it updates iflist */
149
150 if (ifp == NULL)
151 return 0;
152
153 if (IS_ENABLE(ifp))
154 interface_reset(ifp);
155
156 /* To support pseudo interface do not free interface structure. */
157 /* if_delete(ifp); */
158 ifp->ifindex = IFINDEX_INTERNAL;
159
Paul Jakma57345092011-12-25 17:52:09 +0100160 return 0;
161}
162
163int
164babel_interface_address_add (int cmd, struct zclient *client,
165 zebra_size_t length)
166{
167 babel_interface_nfo *babel_ifp;
168 struct connected *ifc;
169 struct prefix *prefix;
170
171 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
172
173 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
174 zclient->ibuf);
175
176 if (ifc == NULL)
177 return 0;
178
179 prefix = ifc->address;
180
181 if (prefix->family == AF_INET) {
182 flush_interface_routes(ifc->ifp, 0);
183 babel_ifp = babel_get_if_nfo(ifc->ifp);
184 if (babel_ifp->ipv4 == NULL) {
185 babel_ifp->ipv4 = malloc(4);
186 if (babel_ifp->ipv4 == NULL) {
187 zlog_err("not einough memory");
188 } else {
189 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
190 }
191 }
192 }
193
194 send_request(ifc->ifp, NULL, 0);
195 send_update(ifc->ifp, 0, NULL, 0);
196
197 return 0;
198}
199
200int
201babel_interface_address_delete (int cmd, struct zclient *client,
202 zebra_size_t length)
203{
204 babel_interface_nfo *babel_ifp;
205 struct connected *ifc;
206 struct prefix *prefix;
207
208 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
209
210 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
211 zclient->ibuf);
212
213 if (ifc == NULL)
214 return 0;
215
216 prefix = ifc->address;
217
218 if (prefix->family == AF_INET) {
219 flush_interface_routes(ifc->ifp, 0);
220 babel_ifp = babel_get_if_nfo(ifc->ifp);
221 if (babel_ifp->ipv4 != NULL
222 && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
223 free(babel_ifp->ipv4);
224 babel_ifp->ipv4 = NULL;
225 }
226 }
227
228 send_request(ifc->ifp, NULL, 0);
229 send_update(ifc->ifp, 0, NULL, 0);
230
231 return 0;
232}
233
234/* Lookup function. */
235static int
236babel_enable_if_lookup (const char *ifname)
237{
238 unsigned int i;
239 char *str;
240
241 for (i = 0; i < vector_active (babel_enable_if); i++)
242 if ((str = vector_slot (babel_enable_if, i)) != NULL)
243 if (strcmp (str, ifname) == 0)
244 return i;
245 return -1;
246}
247
248/* Add interface to babel_enable_if. */
249static int
250babel_enable_if_add (const char *ifname)
251{
252 int ret;
253 struct interface *ifp = NULL;
254
255 ret = babel_enable_if_lookup (ifname);
256 if (ret >= 0)
257 return -1;
258
259 vector_set (babel_enable_if, strdup (ifname));
260
261 ifp = if_lookup_by_name(ifname);
262 if (ifp != NULL)
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100263 interface_recalculate(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100264
265 return 1;
266}
267
268/* Delete interface from babel_enable_if. */
269static int
270babel_enable_if_delete (const char *ifname)
271{
272 int babel_enable_if_index;
273 char *str;
274 struct interface *ifp = NULL;
275
276 babel_enable_if_index = babel_enable_if_lookup (ifname);
277 if (babel_enable_if_index < 0)
278 return -1;
279
280 str = vector_slot (babel_enable_if, babel_enable_if_index);
281 free (str);
282 vector_unset (babel_enable_if, babel_enable_if_index);
283
284 ifp = if_lookup_by_name(ifname);
285 if (ifp != NULL)
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100286 interface_reset(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100287
288 return 1;
289}
290
Paul Jakma57345092011-12-25 17:52:09 +0100291/* [Babel Command] Babel enable on specified interface or matched network. */
292DEFUN (babel_network,
293 babel_network_cmd,
294 "network IF_OR_ADDR",
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100295 "Enable Babel protocol on specified interface or network.\n"
Paul Jakma57345092011-12-25 17:52:09 +0100296 "Interface or address")
297{
298 int ret;
299 struct prefix p;
300
301 ret = str2prefix (argv[0], &p);
302
303 /* Given string is: */
304 if (ret) /* an IPv4 or v6 network */
305 return CMD_ERR_NO_MATCH; /* not implemented yet */
306 else /* an interface name */
307 ret = babel_enable_if_add (argv[0]);
308
309 if (ret < 0) {
310 vty_out (vty, "There is same network configuration %s%s", argv[0],
311 VTY_NEWLINE);
312 return CMD_WARNING;
313 }
314
315 return CMD_SUCCESS;
316}
317
318/* [Babel Command] Babel enable on specified interface or matched network. */
319DEFUN (no_babel_network,
320 no_babel_network_cmd,
321 "no network IF_OR_ADDR",
322 NO_STR
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100323 "Disable Babel protocol on specified interface or network.\n"
Paul Jakma57345092011-12-25 17:52:09 +0100324 "Interface or address")
325{
326 int ret;
327 struct prefix p;
328
329 ret = str2prefix (argv[0], &p);
330
331 /* Given string is: */
332 if (ret) /* an IPv4 or v6 network */
333 return CMD_ERR_NO_MATCH; /* not implemented yet */
334 else /* an interface name */
335 ret = babel_enable_if_delete (argv[0]);
336
337 if (ret < 0) {
338 vty_out (vty, "can't find network %s%s", argv[0],
339 VTY_NEWLINE);
340 return CMD_WARNING;
341 }
342
343 return CMD_SUCCESS;
344}
345
Juliusz Chroboczek260948c2012-02-14 09:09:32 +0100346/* There are a number of interface parameters that must be changed when
347 an interface becomes wired/wireless. In Quagga, they cannot be
348 configured separately. */
349
350static void
351babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
352{
353 if(wired) {
354 babel_ifp->flags |= BABEL_IF_WIRED;
355 babel_ifp->cost = 96;
356 babel_ifp->flags &= ~BABEL_IF_LQ;
357 } else {
358 babel_ifp->flags &= ~BABEL_IF_WIRED;
359 babel_ifp->cost = 256;
360 babel_ifp->flags |= BABEL_IF_LQ;
361 }
362
363}
364
Paul Jakma57345092011-12-25 17:52:09 +0100365/* [Interface Command] Tell the interface is wire. */
366DEFUN (babel_set_wired,
367 babel_set_wired_cmd,
Matthieu Boutier3c442e82012-02-08 23:30:46 +0100368 "babel wired",
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100369 "Babel interface commands\n"
370 "Enable wired optimisations")
Paul Jakma57345092011-12-25 17:52:09 +0100371{
372 struct interface *ifp;
373 babel_interface_nfo *babel_ifp;
374
375 ifp = vty->index;
376 babel_ifp = babel_get_if_nfo(ifp);
377
378 assert (babel_ifp != NULL);
Juliusz Chroboczek260948c2012-02-14 09:09:32 +0100379 babel_set_wired_internal(babel_ifp, 1);
Paul Jakma57345092011-12-25 17:52:09 +0100380 return CMD_SUCCESS;
381}
382
383/* [Interface Command] Tell the interface is wireless (default). */
384DEFUN (babel_set_wireless,
385 babel_set_wireless_cmd,
Matthieu Boutier3c442e82012-02-08 23:30:46 +0100386 "babel wireless",
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100387 "Babel interface commands\n"
388 "Disable wired optimiations (assume wireless)")
Paul Jakma57345092011-12-25 17:52:09 +0100389{
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);
Juliusz Chroboczek260948c2012-02-14 09:09:32 +0100397 babel_set_wired_internal(babel_ifp, 0);
Paul Jakma57345092011-12-25 17:52:09 +0100398 return CMD_SUCCESS;
399}
400
401/* [Interface Command] Enable split horizon. */
402DEFUN (babel_split_horizon,
403 babel_split_horizon_cmd,
404 "babel split-horizon",
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100405 "Babel interface commands\n"
406 "Enable split horizon processing")
Paul Jakma57345092011-12-25 17:52:09 +0100407{
408 struct interface *ifp;
409 babel_interface_nfo *babel_ifp;
410
411 ifp = vty->index;
412 babel_ifp = babel_get_if_nfo(ifp);
413
414 assert (babel_ifp != NULL);
415 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
416 return CMD_SUCCESS;
417}
418
419/* [Interface Command] Disable split horizon (default). */
420DEFUN (no_babel_split_horizon,
421 no_babel_split_horizon_cmd,
422 "no babel split-horizon",
423 NO_STR
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100424 "Babel interface commands\n"
425 "Disable split horizon processing")
Paul Jakma57345092011-12-25 17:52:09 +0100426{
427 struct interface *ifp;
428 babel_interface_nfo *babel_ifp;
429
430 ifp = vty->index;
431 babel_ifp = babel_get_if_nfo(ifp);
432
433 assert (babel_ifp != NULL);
434 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
435 return CMD_SUCCESS;
436}
437
438/* [Interface Command]. */
439DEFUN (babel_set_hello_interval,
440 babel_set_hello_interval_cmd,
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100441 "babel hello-interval <20-655340>",
442 "Babel interface commands\n"
443 "Time between scheduled hellos\n"
444 "Milliseconds\n")
Paul Jakma57345092011-12-25 17:52:09 +0100445{
446 struct interface *ifp;
447 babel_interface_nfo *babel_ifp;
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100448 int interval;
Paul Jakma57345092011-12-25 17:52:09 +0100449
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100450 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
Paul Jakma57345092011-12-25 17:52:09 +0100451
452 ifp = vty->index;
453 babel_ifp = babel_get_if_nfo(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100454 assert (babel_ifp != NULL);
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100455
Paul Jakma57345092011-12-25 17:52:09 +0100456 babel_ifp->hello_interval = interval;
457 return CMD_SUCCESS;
458}
459
460/* [Interface Command]. */
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100461DEFUN (babel_set_update_interval,
462 babel_set_update_interval_cmd,
463 "babel update-interval <20-655340>",
464 "Babel interface commands\n"
465 "Time between scheduled updates\n"
466 "Milliseconds\n")
467{
468 struct interface *ifp;
469 babel_interface_nfo *babel_ifp;
470 int interval;
471
472 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
473
474 ifp = vty->index;
475 babel_ifp = babel_get_if_nfo(ifp);
476 assert (babel_ifp != NULL);
477
478 babel_ifp->update_interval = interval;
479 return CMD_SUCCESS;
480}
481
482/* [Interface Command]. */
Paul Jakma57345092011-12-25 17:52:09 +0100483DEFUN (babel_passive_interface,
484 babel_passive_interface_cmd,
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100485 "babel passive-interface",
486 "Babel interface commands\n"
487 "Only announce redistributed routes on this interface\n")
Paul Jakma57345092011-12-25 17:52:09 +0100488{
489 if (allow_duplicates) {
490 return CMD_WARNING;
491 }
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100492 parasitic = 1;
Paul Jakma57345092011-12-25 17:52:09 +0100493 return CMD_SUCCESS;
494}
495
496/* [Interface Command]. */
497DEFUN (no_babel_passive_interface,
498 no_babel_passive_interface_cmd,
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100499 "no babel passive-interface",
Paul Jakma57345092011-12-25 17:52:09 +0100500 NO_STR
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100501 "Babel interface commands\n"
502 "Announce all routes on this interface\n")
Paul Jakma57345092011-12-25 17:52:09 +0100503{
504 parasitic = 0;
505 return CMD_SUCCESS;
506}
507
Paul Jakma57345092011-12-25 17:52:09 +0100508/* This should be no more than half the hello interval, so that hellos
509 aren't sent late. The result is in milliseconds. */
510unsigned
511jitter(babel_interface_nfo *babel_ifp, int urgent)
512{
513 unsigned interval = babel_ifp->hello_interval;
514 if(urgent)
515 interval = MIN(interval, 100);
516 else
517 interval = MIN(interval, 4000);
518 return roughly(interval) / 4;
519}
520
521unsigned
522update_jitter(babel_interface_nfo *babel_ifp, int urgent)
523{
524 unsigned interval = babel_ifp->hello_interval;
525 if(urgent)
526 interval = MIN(interval, 100);
527 else
528 interval = MIN(interval, 4000);
529 return roughly(interval);
530}
531
532/* calculate babeld's specific datas of an interface (change when the interface
533 change) */
534static int
535interface_recalculate(struct interface *ifp)
536{
537 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
538 unsigned char *tmp = NULL;
539 int mtu, rc;
540 struct ipv6_mreq mreq;
541
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100542 if (!IS_ENABLE(ifp))
543 return -1;
544
Matthieu Boutier0ee8a1f2012-01-18 00:52:06 +0100545 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
546 interface_reset(ifp);
547 return -1;
548 }
549
550 babel_ifp->flags |= BABEL_IF_IS_UP;
551
Paul Jakma57345092011-12-25 17:52:09 +0100552 mtu = MIN(ifp->mtu, ifp->mtu6);
553
554 /* We need to be able to fit at least two messages into a packet,
555 so MTUs below 116 require lower layer fragmentation. */
556 /* In IPv6, the minimum MTU is 1280, and every host must be able
557 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
558 if(mtu < 128) {
559 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
560 mtu, ifp->name, ifp->ifindex);
561 mtu = 128;
562 }
563
564 /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
565 babel_ifp->bufsize = mtu - sizeof(packet_header) - 60;
566 tmp = babel_ifp->sendbuf;
567 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
568 if(babel_ifp->sendbuf == NULL) {
Matthieu Boutier4eedea52012-01-17 22:46:21 +0100569 zlog_err("Couldn't reallocate sendbuf.");
Paul Jakma57345092011-12-25 17:52:09 +0100570 free(tmp);
571 babel_ifp->bufsize = 0;
572 return -1;
573 }
574 tmp = NULL;
575
576 resize_receive_buffer(mtu);
577
Paul Jakma57345092011-12-25 17:52:09 +0100578 memset(&mreq, 0, sizeof(mreq));
579 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
580 mreq.ipv6mr_interface = ifp->ifindex;
581
582 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
583 (char*)&mreq, sizeof(mreq));
584 if(rc < 0) {
585 zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
586 ifp->name, safe_strerror(errno));
587 /* This is probably due to a missing link-local address,
588 so down this interface, and wait until the main loop
589 tries to up it again. */
590 interface_reset(ifp);
591 return -1;
592 }
593
594 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
595 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
596 send_hello(ifp);
597 send_request(ifp, NULL, 0);
598
599 update_interface_metric(ifp);
600
601 debugf(BABEL_DEBUG_COMMON,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100602 "Upped interface %s (%s, cost=%d, channel=%d%s).",
Paul Jakma57345092011-12-25 17:52:09 +0100603 ifp->name,
604 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
605 babel_ifp->cost,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100606 babel_ifp->channel,
Paul Jakma57345092011-12-25 17:52:09 +0100607 babel_ifp->ipv4 ? ", IPv4" : "");
608
609 if(rc > 0)
610 send_update(ifp, 0, NULL, 0);
611
Paul Jakma57345092011-12-25 17:52:09 +0100612 return 1;
613}
614
615/* Reset the interface as it was new: it's not removed from the interface list,
616 and may be considered as a upped interface. */
617static int
618interface_reset(struct interface *ifp)
619{
620 int rc;
621 struct ipv6_mreq mreq;
622 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
623
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100624 if (!(babel_ifp->flags & BABEL_IF_IS_UP))
625 return 0;
626
Matthieu Boutier0ee8a1f2012-01-18 00:52:06 +0100627 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
628 babel_ifp->flags &= ~BABEL_IF_IS_UP;
629
Paul Jakma57345092011-12-25 17:52:09 +0100630 flush_interface_routes(ifp, 0);
631 babel_ifp->buffered = 0;
632 babel_ifp->bufsize = 0;
633 free(babel_ifp->sendbuf);
634 babel_ifp->num_buffered_updates = 0;
635 babel_ifp->update_bufsize = 0;
636 if(babel_ifp->buffered_updates)
637 free(babel_ifp->buffered_updates);
638 babel_ifp->buffered_updates = NULL;
639 babel_ifp->sendbuf = NULL;
640
641 if(ifp->ifindex > 0) {
642 memset(&mreq, 0, sizeof(mreq));
643 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
644 mreq.ipv6mr_interface = ifp->ifindex;
645 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
646 (char*)&mreq, sizeof(mreq));
647 if(rc < 0)
648 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
649 ifp->name, safe_strerror(errno));
650 }
651
652 update_interface_metric(ifp);
653
654 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
655 ifp->name,
656 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
657 babel_ifp->cost,
658 babel_ifp->ipv4 ? ", IPv4" : "");
659
660 return 1;
661}
662
663/* Send retraction to all, and reset all interfaces statistics. */
664void
665babel_interface_close_all(void)
666{
667 struct interface *ifp = NULL;
668 struct listnode *linklist_node = NULL;
669
670 FOR_ALL_INTERFACES(ifp, linklist_node) {
671 if(!if_up(ifp))
672 continue;
673 send_wildcard_retraction(ifp);
674 /* Make sure that we expire quickly from our neighbours'
675 association caches. */
676 send_hello_noupdate(ifp, 10);
677 flushbuf(ifp);
678 usleep(roughly(1000));
679 gettime(&babel_now);
680 }
681 FOR_ALL_INTERFACES(ifp, linklist_node) {
682 if(!if_up(ifp))
683 continue;
684 /* Make sure they got it. */
685 send_wildcard_retraction(ifp);
686 send_hello_noupdate(ifp, 1);
687 flushbuf(ifp);
688 usleep(roughly(10000));
689 gettime(&babel_now);
690 interface_reset(ifp);
691 }
692}
693
694/* return "true" if address is one of our ipv6 addresses */
695int
696is_interface_ll_address(struct interface *ifp, const unsigned char *address)
697{
698 struct connected *connected;
699 struct listnode *node;
700
701 if(!if_up(ifp))
702 return 0;
703
704 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
705 if(connected->address->family == AF_INET6 &&
706 memcmp(&connected->address->u.prefix6, address, 16) == 0)
707 return 1;
708 }
709
710 return 0;
711}
712
Denis Ovsienkod4e46e62012-01-17 19:25:03 +0400713static void
714show_babel_interface_sub (struct vty *vty, struct interface *ifp)
715{
716 int is_up;
717 babel_interface_nfo *babel_ifp;
718
719 vty_out (vty, "%s is %s%s", ifp->name,
720 ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE);
721 vty_out (vty, " ifindex %u, MTU %u bytes %s%s",
722 ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE);
723
724 if (babel_enable_if_lookup (ifp->name) < 0)
725 {
726 vty_out (vty, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
727 return;
728 }
729 if (!is_up)
730 {
731 vty_out (vty, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
732 return;
733 }
734 babel_ifp = babel_get_if_nfo (ifp);
735 vty_out (vty, " Babel protocol is running on this interface%s", VTY_NEWLINE);
736 vty_out (vty, " Operating mode is \"%s\"%s",
737 CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE);
738 vty_out (vty, " Split horizon mode is %s%s",
739 CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE);
740 vty_out (vty, " Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE);
Juliusz Chroboczek9c298c72012-02-11 14:06:24 +0100741 vty_out (vty, " Update interval is %u ms%s", babel_ifp->update_interval, VTY_NEWLINE);
Denis Ovsienkod4e46e62012-01-17 19:25:03 +0400742}
743
744DEFUN (show_babel_interface,
745 show_babel_interface_cmd,
746 "show babel interface [INTERFACE]",
747 SHOW_STR
748 IP_STR
749 "Babel information\n"
750 "Interface information\n"
751 "Interface name\n")
752{
753 struct interface *ifp;
754 struct listnode *node;
755
756 if (argc == 0)
757 {
758 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
759 show_babel_interface_sub (vty, ifp);
760 return CMD_SUCCESS;
761 }
762 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
763 {
764 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
765 return CMD_WARNING;
766 }
767 show_babel_interface_sub (vty, ifp);
768 return CMD_SUCCESS;
769}
Paul Jakma57345092011-12-25 17:52:09 +0100770
Matthieu Boutier297a55b2012-01-18 16:39:29 +0100771static void
772show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
773{
774 vty_out (vty,
775 "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s",
776 format_address(neigh->address),
777 neigh->ifp->name,
778 neigh->reach,
779 neighbour_rxcost(neigh),
780 neigh->txcost,
781 if_up(neigh->ifp) ? "" : " (down)",
782 VTY_NEWLINE);
783}
784
785DEFUN (show_babel_neighbour,
786 show_babel_neighbour_cmd,
787 "show babel neighbour [INTERFACE]",
788 SHOW_STR
789 IP_STR
790 "Babel information\n"
791 "Print neighbours\n"
792 "Interface name\n")
793{
794 struct neighbour *neigh;
795 struct interface *ifp;
796
797 if (argc == 0) {
798 FOR_ALL_NEIGHBOURS(neigh) {
799 show_babel_neighbour_sub(vty, neigh);
800 }
801 return CMD_SUCCESS;
802 }
803 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
804 {
805 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
806 return CMD_WARNING;
807 }
808 FOR_ALL_NEIGHBOURS(neigh) {
809 if(ifp->ifindex == neigh->ifp->ifindex) {
810 show_babel_neighbour_sub(vty, neigh);
811 }
812 }
813 return CMD_SUCCESS;
814}
815
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100816static void
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100817show_babel_routes_sub (struct babel_route *route, void *closure)
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100818{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100819 struct vty *vty = (struct vty*) closure;
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100820 const unsigned char *nexthop =
821 memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
822 NULL : route->nexthop;
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100823 char channels[100];
824
825 if(route->channels[0] == 0)
826 channels[0] = '\0';
827 else {
828 int k, j = 0;
829 snprintf(channels, 100, " chan (");
830 j = strlen(channels);
831 for(k = 0; k < DIVERSITY_HOPS; k++) {
832 if(route->channels[k] == 0)
833 break;
834 if(k > 0)
835 channels[j++] = ',';
836 snprintf(channels + j, 100 - j, "%d", route->channels[k]);
837 j = strlen(channels);
838 }
839 snprintf(channels + j, 100 - j, ")");
840 if(k == 0)
841 channels[0] = '\0';
842 }
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100843
844 vty_out(vty,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100845 "%s metric %d refmetric %d id %s seqno %d%s age %d "
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100846 "via %s neigh %s%s%s%s%s",
847 format_prefix(route->src->prefix, route->src->plen),
848 route_metric(route), route->refmetric,
849 format_eui64(route->src->id),
850 (int)route->seqno,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100851 channels,
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100852 (int)(babel_now.tv_sec - route->time),
853 route->neigh->ifp->name,
854 format_address(route->neigh->address),
855 nexthop ? " nexthop " : "",
856 nexthop ? format_address(nexthop) : "",
857 route->installed ? " (installed)" :
858 route_feasible(route) ? " (feasible)" : "",
859 VTY_NEWLINE);
860}
861
862static void
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100863show_babel_xroutes_sub (struct xroute *xroute, void *closure)
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100864{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100865 struct vty *vty = (struct vty *) closure;
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100866 vty_out(vty, "%s metric %d (exported)%s",
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100867 format_prefix(xroute->prefix, xroute->plen),
868 xroute->metric,
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100869 VTY_NEWLINE);
870}
871
872DEFUN (show_babel_database,
873 show_babel_database_cmd,
874 "show babel database",
875 SHOW_STR
876 IP_STR
877 "Babel information\n"
878 "Database information\n"
879 "No attributes\n")
880{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100881 for_all_routes(show_babel_routes_sub, vty);
882 for_all_xroutes(show_babel_xroutes_sub, vty);
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100883 return CMD_SUCCESS;
884}
885
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +0400886DEFUN (show_babel_parameters,
887 show_babel_parameters_cmd,
888 "show babel parameters",
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100889 SHOW_STR
890 IP_STR
891 "Babel information\n"
892 "Configuration information\n"
893 "No attributes\n")
894{
895 vty_out(vty, " -- Babel running configuration --%s", VTY_NEWLINE);
896 show_babel_main_configuration(vty);
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100897 vty_out(vty, " -- distribution lists --%s", VTY_NEWLINE);
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100898 config_show_distribute(vty);
899
900 return CMD_SUCCESS;
901}
902
Paul Jakma57345092011-12-25 17:52:09 +0100903void
904babel_if_init ()
905{
906 /* initialize interface list */
907 if_init();
908 if_add_hook (IF_NEW_HOOK, babel_if_new_hook);
909 if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
910
911 babel_enable_if = vector_init (1);
912
913 /* install interface node and commands */
914 install_element (CONFIG_NODE, &interface_cmd);
915 install_element (CONFIG_NODE, &no_interface_cmd);
916 install_node (&babel_interface_node, interface_config_write);
917 install_default(INTERFACE_NODE);
918 install_element(INTERFACE_NODE, &interface_cmd);
919 install_element(INTERFACE_NODE, &no_interface_cmd);
920
921 install_element(BABEL_NODE, &babel_network_cmd);
922 install_element(BABEL_NODE, &no_babel_network_cmd);
923 install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
924 install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
925 install_element(INTERFACE_NODE, &babel_set_wired_cmd);
926 install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
927 install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100928 install_element(INTERFACE_NODE, &babel_set_update_interval_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100929 install_element(INTERFACE_NODE, &babel_passive_interface_cmd);
930 install_element(INTERFACE_NODE, &no_babel_passive_interface_cmd);
Denis Ovsienkod4e46e62012-01-17 19:25:03 +0400931
Juliusz Chroboczekec0c8482012-02-07 05:44:41 +0100932 /* "show babel ..." commands */
933 install_element(VIEW_NODE, &show_babel_interface_cmd);
934 install_element(ENABLE_NODE, &show_babel_interface_cmd);
Matthieu Boutier297a55b2012-01-18 16:39:29 +0100935 install_element(VIEW_NODE, &show_babel_neighbour_cmd);
936 install_element(ENABLE_NODE, &show_babel_neighbour_cmd);
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100937 install_element(VIEW_NODE, &show_babel_database_cmd);
938 install_element(ENABLE_NODE, &show_babel_database_cmd);
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +0400939 install_element(VIEW_NODE, &show_babel_parameters_cmd);
940 install_element(ENABLE_NODE, &show_babel_parameters_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100941}
942
943/* hooks: functions called respectively when struct interface is
944 created or deleted. */
945static int
946babel_if_new_hook (struct interface *ifp)
947{
948 ifp->info = babel_interface_allocate();
949 return 0;
950}
951
952static int
953babel_if_delete_hook (struct interface *ifp)
954{
955 babel_interface_free(ifp->info);
956 ifp->info = NULL;
957 return 0;
958}
959
Denis Ovsienkocb4b13d2012-02-13 22:13:37 +0400960/* Output an "interface" section for each of the known interfaces with
961babeld-specific statement lines where appropriate. */
Paul Jakma57345092011-12-25 17:52:09 +0100962static int
963interface_config_write (struct vty *vty)
964{
965 struct listnode *node;
966 struct interface *ifp;
Paul Jakma57345092011-12-25 17:52:09 +0100967 int write = 0;
968
969 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) {
Paul Jakma57345092011-12-25 17:52:09 +0100970 vty_out (vty, "interface %s%s", ifp->name,
971 VTY_NEWLINE);
972 if (ifp->desc)
973 vty_out (vty, " description %s%s", ifp->desc,
974 VTY_NEWLINE);
Denis Ovsienkocb4b13d2012-02-13 22:13:37 +0400975 if (IS_ENABLE (ifp))
976 {
977 babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
978 /* wireless/no split-horizon is the default */
979 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
980 {
981 vty_out (vty, " babel wired%s", VTY_NEWLINE);
982 write++;
983 }
984 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON))
985 {
986 vty_out (vty, " babel split-horizon%s", VTY_NEWLINE);
987 write++;
988 }
989 }
Paul Jakma57345092011-12-25 17:52:09 +0100990 vty_out (vty, "!%s", VTY_NEWLINE);
Paul Jakma57345092011-12-25 17:52:09 +0100991 write++;
992 }
993 return write;
994}
995
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +0400996/* Output a "network" statement line for each of the enabled interfaces. */
997int
998babel_enable_if_config_write (struct vty * vty)
999{
1000 unsigned int i, lines = 0;
1001 char *str;
1002
1003 for (i = 0; i < vector_active (babel_enable_if); i++)
1004 if ((str = vector_slot (babel_enable_if, i)) != NULL)
1005 {
1006 vty_out (vty, " network %s%s", str, VTY_NEWLINE);
1007 lines++;
1008 }
1009 return lines;
1010}
1011
Paul Jakma57345092011-12-25 17:52:09 +01001012/* functions to allocate or free memory for a babel_interface_nfo, filling
1013 needed fields */
1014static babel_interface_nfo *
Matthieu Boutierc7c53fa2012-01-08 16:43:08 +01001015babel_interface_allocate (void)
Paul Jakma57345092011-12-25 17:52:09 +01001016{
1017 babel_interface_nfo *babel_ifp;
1018 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
1019 if(babel_ifp == NULL)
1020 return NULL;
1021
1022 /* Here are set the default values for an interface. */
1023 memset(babel_ifp, 0, sizeof(babel_interface_nfo));
1024 /* All flags are unset */
Paul Jakma57345092011-12-25 17:52:09 +01001025 babel_ifp->bucket_time = babel_now.tv_sec;
1026 babel_ifp->bucket = BUCKET_TOKENS_MAX;
1027 babel_ifp->hello_seqno = (random() & 0xFFFF);
Juliusz Chroboczek36329c02012-02-14 08:49:57 +01001028 babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL;
1029 babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL;
Matthieu Boutierc35fafd2012-01-23 23:46:32 +01001030 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
Juliusz Chroboczek260948c2012-02-14 09:09:32 +01001031 babel_set_wired_internal(babel_ifp, 0);
Paul Jakma57345092011-12-25 17:52:09 +01001032
1033 return babel_ifp;
1034}
1035
1036static void
1037babel_interface_free (babel_interface_nfo *babel_ifp)
1038{
1039 XFREE(MTYPE_BABEL_IF, babel_ifp);
1040}