]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babeld.c
07dd92a37edfb136f34f471612de6d791159b826
[mirror_frr.git] / babeld / babeld.c
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
19 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20
21 Permission is hereby granted, free of charge, to any person obtaining a copy
22 of this software and associated documentation files (the "Software"), to deal
23 in the Software without restriction, including without limitation the rights
24 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 copies of the Software, and to permit persons to whom the Software is
26 furnished to do so, subject to the following conditions:
27
28 The above copyright notice and this permission notice shall be included in
29 all copies or substantial portions of the Software.
30
31 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 THE SOFTWARE.
38 */
39
40 #include <zebra.h>
41 #include "command.h"
42 #include "prefix.h"
43 #include "memory.h"
44 #include "memtypes.h"
45 #include "table.h"
46 #include "distribute.h"
47 #include "prefix.h"
48 #include "filter.h"
49 #include "plist.h"
50
51 #include "babel_main.h"
52 #include "babeld.h"
53 #include "util.h"
54 #include "net.h"
55 #include "kernel.h"
56 #include "babel_interface.h"
57 #include "neighbour.h"
58 #include "route.h"
59 #include "message.h"
60 #include "resend.h"
61 #include "babel_filter.h"
62
63
64 static int babel_init_routing_process(struct thread *thread);
65 static void babel_get_myid(void);
66 static void babel_initial_noise(void);
67 static int babel_read_protocol (struct thread *thread);
68 static int babel_main_loop(struct thread *thread);
69 static void babel_set_timer(struct timeval *timeout);
70 static void babel_fill_with_next_timeout(struct timeval *tv);
71
72
73 /* Informations relative to the babel running daemon. */
74 static struct babel *babel_routing_process = NULL;
75 static unsigned char *receive_buffer = NULL;
76 static int receive_buffer_size = 0;
77
78 /* timeouts */
79 struct timeval check_neighbours_timeout;
80 static time_t expiry_time;
81 static time_t source_expiry_time;
82
83 /* Babel node structure. */
84 static struct cmd_node cmd_babel_node =
85 {
86 .node = BABEL_NODE,
87 .prompt = "%s(config-router)# ",
88 .vtysh = 1,
89 };
90
91 /* print current babel configuration on vty */
92 static int
93 babel_config_write (struct vty *vty)
94 {
95 return 0;
96 }
97
98
99 static int
100 babel_create_routing_process (void)
101 {
102 assert (babel_routing_process == NULL);
103
104 /* Allocaste Babel instance. */
105 babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
106
107 /* Initialize timeouts */
108 gettime(&babel_now);
109 expiry_time = babel_now.tv_sec + roughly(30);
110 source_expiry_time = babel_now.tv_sec + roughly(300);
111
112 /* Make socket for Babel protocol. */
113 protocol_socket = babel_socket(protocol_port);
114 if (protocol_socket < 0) {
115 zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
116 goto fail;
117 }
118
119 /* Threads. */
120 babel_routing_process->t_read =
121 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
122 /* wait a little: zebra will announce interfaces, addresses, routes... */
123 babel_routing_process->t_update =
124 thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
125 return 0;
126
127 fail:
128 XFREE(MTYPE_BABEL, babel_routing_process);
129 babel_routing_process = NULL;
130 return -1;
131 }
132
133 /* thread reading entries form others babel daemons */
134 static int
135 babel_read_protocol (struct thread *thread)
136 {
137 int rc;
138 struct interface *ifp = NULL;
139 struct sockaddr_in6 sin6;
140 struct listnode *linklist_node = NULL;
141
142 assert(babel_routing_process != NULL);
143 assert(protocol_socket >= 0);
144
145 rc = babel_recv(protocol_socket,
146 receive_buffer, receive_buffer_size,
147 (struct sockaddr*)&sin6, sizeof(sin6));
148 if(rc < 0) {
149 if(errno != EAGAIN && errno != EINTR) {
150 zlog_err("recv: %s", safe_strerror(errno));
151 }
152 } else {
153 FOR_ALL_INTERFACES(ifp, linklist_node) {
154 if(!if_up(ifp))
155 continue;
156 if(ifp->ifindex == sin6.sin6_scope_id) {
157 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
158 receive_buffer, rc);
159 break;
160 }
161 }
162 }
163
164 /* re-add thread */
165 babel_routing_process->t_read =
166 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
167 return 0;
168 }
169
170 /* Zebra will give some information, especially about interfaces. This function
171 must be call with a litte timeout wich may give zebra the time to do his job,
172 making these inits have sense. */
173 static int
174 babel_init_routing_process(struct thread *thread)
175 {
176 myseqno = (random() & 0xFFFF);
177 babel_get_myid();
178 babel_load_state_file();
179 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
180 babel_initial_noise();
181 babel_main_loop(thread);/* this function self-add to the t_update thread */
182 return 0;
183 }
184
185 /* fill "myid" with an unique id (only if myid != {0}). */
186 static void
187 babel_get_myid(void)
188 {
189 struct interface *ifp = NULL;
190 struct listnode *linklist_node = NULL;
191 int rc;
192 int i;
193
194 /* if we already have an id (from state file), we return. */
195 if (memcmp(myid, zeroes, 8) != 0) {
196 return;
197 }
198
199 FOR_ALL_INTERFACES(ifp, linklist_node) {
200 /* ifp->ifindex is not necessarily valid at this point */
201 int ifindex = if_nametoindex(ifp->name);
202 if(ifindex > 0) {
203 unsigned char eui[8];
204 rc = if_eui64(ifp->name, ifindex, eui);
205 if(rc < 0)
206 continue;
207 memcpy(myid, eui, 8);
208 return;
209 }
210 }
211
212 /* We failed to get a global EUI64 from the interfaces we were given.
213 Let's try to find an interface with a MAC address. */
214 for(i = 1; i < 256; i++) {
215 char buf[IF_NAMESIZE], *ifname;
216 unsigned char eui[8];
217 ifname = if_indextoname(i, buf);
218 if(ifname == NULL)
219 continue;
220 rc = if_eui64(ifname, i, eui);
221 if(rc < 0)
222 continue;
223 memcpy(myid, eui, 8);
224 return;
225 }
226
227 zlog_err("Warning: couldn't find router id -- using random value.");
228
229 rc = read_random_bytes(myid, 8);
230 if(rc < 0) {
231 zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
232 exit(1);
233 }
234 /* Clear group and global bits */
235 myid[0] &= ~3;
236 }
237
238 /* Make some noise so that others notice us, and send retractions in
239 case we were restarted recently */
240 static void
241 babel_initial_noise(void)
242 {
243 struct interface *ifp = NULL;
244 struct listnode *linklist_node = NULL;
245
246 FOR_ALL_INTERFACES(ifp, linklist_node) {
247 if(!if_up(ifp))
248 continue;
249 /* Apply jitter before we send the first message. */
250 usleep(roughly(10000));
251 gettime(&babel_now);
252 send_hello(ifp);
253 send_wildcard_retraction(ifp);
254 }
255
256 FOR_ALL_INTERFACES(ifp, linklist_node) {
257 if(!if_up(ifp))
258 continue;
259 usleep(roughly(10000));
260 gettime(&babel_now);
261 send_hello(ifp);
262 send_wildcard_retraction(ifp);
263 send_self_update(ifp);
264 send_request(ifp, NULL, 0);
265 flushupdates(ifp);
266 flushbuf(ifp);
267 }
268 }
269
270 /* Delete all the added babel routes, make babeld only speak to zebra. */
271 static void
272 babel_clean_routing_process()
273 {
274 flush_all_routes();
275 babel_interface_close_all();
276
277 /* cancel threads */
278 if (babel_routing_process->t_read != NULL) {
279 thread_cancel(babel_routing_process->t_read);
280 }
281 if (babel_routing_process->t_update != NULL) {
282 thread_cancel(babel_routing_process->t_update);
283 }
284
285 XFREE(MTYPE_BABEL, babel_routing_process);
286 babel_routing_process = NULL;
287 }
288
289 /* Function used with timeout. */
290 static int
291 babel_main_loop(struct thread *thread)
292 {
293 struct timeval tv;
294 struct interface *ifp = NULL;
295 struct listnode *linklist_node = NULL;
296
297 while(1) {
298 gettime(&babel_now);
299
300 /* timeouts --------------------------------------------------------- */
301 /* get the next timeout */
302 babel_fill_with_next_timeout(&tv);
303 /* if there is no timeout, we must wait. */
304 if(timeval_compare(&tv, &babel_now) > 0) {
305 timeval_minus(&tv, &tv, &babel_now);
306 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
307 tv.tv_sec * 1000 + tv.tv_usec / 1000);
308 /* it happens often to have less than 1 ms, it's bad. */
309 timeval_add_msec(&tv, &tv, 300);
310 babel_set_timer(&tv);
311 return 0;
312 }
313
314 gettime(&babel_now);
315
316 /* update database -------------------------------------------------- */
317 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
318 int msecs;
319 msecs = check_neighbours();
320 msecs = MAX(msecs, 10);
321 schedule_neighbours_check(msecs, 1);
322 }
323
324 if(babel_now.tv_sec >= expiry_time) {
325 expire_routes();
326 expire_resend();
327 expiry_time = babel_now.tv_sec + roughly(30);
328 }
329
330 if(babel_now.tv_sec >= source_expiry_time) {
331 expire_sources();
332 source_expiry_time = babel_now.tv_sec + roughly(300);
333 }
334
335 FOR_ALL_INTERFACES(ifp, linklist_node) {
336 babel_interface_nfo *babel_ifp = NULL;
337 if(!if_up(ifp))
338 continue;
339 babel_ifp = babel_get_if_nfo(ifp);
340 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
341 send_hello(ifp);
342 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
343 send_update(ifp, 0, NULL, 0);
344 if(timeval_compare(&babel_now,
345 &babel_ifp->update_flush_timeout) >= 0)
346 flushupdates(ifp);
347 }
348
349 if(resend_time.tv_sec != 0) {
350 if(timeval_compare(&babel_now, &resend_time) >= 0)
351 do_resend();
352 }
353
354 if(unicast_flush_timeout.tv_sec != 0) {
355 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
356 flush_unicast(1);
357 }
358
359 FOR_ALL_INTERFACES(ifp, linklist_node) {
360 babel_interface_nfo *babel_ifp = NULL;
361 if(!if_up(ifp))
362 continue;
363 babel_ifp = babel_get_if_nfo(ifp);
364 if(babel_ifp->flush_timeout.tv_sec != 0) {
365 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
366 flushbuf(ifp);
367 }
368 }
369 }
370
371 assert(0); /* this line should never be reach */
372 }
373
374 static void
375 printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
376 {
377 static struct timeval curr_tv;
378 static char buffer[200];
379 static const char *curr_tag = NULL;
380
381 switch (cmd) {
382 case 0: /* reset timeval */
383 curr_tv = *tv;
384 if(ifname != NULL) {
385 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
386 curr_tag = buffer;
387 } else {
388 curr_tag = tag;
389 }
390 break;
391 case 1: /* take the min */
392 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
393 break;
394 }
395 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
396 tv->tv_usec < curr_tv.tv_usec)) {
397 curr_tv = *tv;
398 if(ifname != NULL) {
399 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
400 curr_tag = buffer;
401 } else {
402 curr_tag = tag;
403 }
404 }
405 break;
406 case 2: /* print message */
407 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
408 break;
409 default:
410 break;
411 }
412 }
413
414 static void
415 babel_fill_with_next_timeout(struct timeval *tv)
416 {
417 #if (defined NO_DEBUG)
418 #define printIfMin(a,b,c,d)
419 #else
420 #define printIfMin(a,b,c,d) \
421 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
422
423 struct interface *ifp = NULL;
424 struct listnode *linklist_node = NULL;
425
426 *tv = check_neighbours_timeout;
427 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
428 timeval_min_sec(tv, expiry_time);
429 printIfMin(tv, 1, "expiry_time", NULL);
430 timeval_min_sec(tv, source_expiry_time);
431 printIfMin(tv, 1, "source_expiry_time", NULL);
432 timeval_min(tv, &resend_time);
433 printIfMin(tv, 1, "resend_time", NULL);
434 FOR_ALL_INTERFACES(ifp, linklist_node) {
435 babel_interface_nfo *babel_ifp = NULL;
436 if(!if_up(ifp))
437 continue;
438 babel_ifp = babel_get_if_nfo(ifp);
439 timeval_min(tv, &babel_ifp->flush_timeout);
440 printIfMin(tv, 1, "flush_timeout", ifp->name);
441 timeval_min(tv, &babel_ifp->hello_timeout);
442 printIfMin(tv, 1, "hello_timeout", ifp->name);
443 timeval_min(tv, &babel_ifp->update_timeout);
444 printIfMin(tv, 1, "update_timeout", ifp->name);
445 timeval_min(tv, &babel_ifp->update_flush_timeout);
446 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
447 }
448 timeval_min(tv, &unicast_flush_timeout);
449 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
450 printIfMin(tv, 2, NULL, NULL);
451 #undef printIfMin
452 #endif
453 }
454
455 /* set the t_update thread of the babel routing process to be launch in
456 'timeout' (approximate at the milisecond) */
457 static void
458 babel_set_timer(struct timeval *timeout)
459 {
460 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
461 if (babel_routing_process->t_update != NULL) {
462 thread_cancel(babel_routing_process->t_update);
463 }
464 babel_routing_process->t_update =
465 thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
466 }
467
468 /* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
469 void
470 schedule_neighbours_check(int msecs, int override)
471 {
472 struct timeval timeout;
473
474 timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
475 if(override)
476 check_neighbours_timeout = timeout;
477 else
478 timeval_min(&check_neighbours_timeout, &timeout);
479 }
480
481 int
482 resize_receive_buffer(int size)
483 {
484 if(size <= receive_buffer_size)
485 return 0;
486
487 if(receive_buffer == NULL) {
488 receive_buffer = malloc(size);
489 if(receive_buffer == NULL) {
490 zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
491 return -1;
492 }
493 receive_buffer_size = size;
494 } else {
495 unsigned char *new;
496 new = realloc(receive_buffer, size);
497 if(new == NULL) {
498 zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
499 return -1;
500 }
501 receive_buffer = new;
502 receive_buffer_size = size;
503 }
504 return 1;
505 }
506
507 static void
508 babel_distribute_update (struct distribute *dist)
509 {
510 struct interface *ifp;
511 babel_interface_nfo *babel_ifp;
512 struct access_list *alist;
513 struct prefix_list *plist;
514
515 if (! dist->ifname)
516 return;
517
518 ifp = if_lookup_by_name (dist->ifname);
519 if (ifp == NULL)
520 return;
521
522 babel_ifp = babel_get_if_nfo(ifp);
523
524 if (dist->list[DISTRIBUTE_IN]) {
525 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
526 if (alist)
527 babel_ifp->list[BABEL_FILTER_IN] = alist;
528 else
529 babel_ifp->list[BABEL_FILTER_IN] = NULL;
530 } else {
531 babel_ifp->list[BABEL_FILTER_IN] = NULL;
532 }
533
534 if (dist->list[DISTRIBUTE_OUT]) {
535 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
536 if (alist)
537 babel_ifp->list[BABEL_FILTER_OUT] = alist;
538 else
539 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
540 } else {
541 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
542 }
543
544 if (dist->prefix[DISTRIBUTE_IN]) {
545 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
546 if (plist)
547 babel_ifp->prefix[BABEL_FILTER_IN] = plist;
548 else
549 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
550 } else {
551 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
552 }
553
554 if (dist->prefix[DISTRIBUTE_OUT]) {
555 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
556 if (plist)
557 babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
558 else
559 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
560 } else {
561 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
562 }
563 }
564
565 static void
566 babel_distribute_update_interface (struct interface *ifp)
567 {
568 struct distribute *dist;
569
570 dist = distribute_lookup (ifp->name);
571 if (dist)
572 babel_distribute_update (dist);
573 }
574
575 /* Update all interface's distribute list. */
576 static void
577 babel_distribute_update_all (struct prefix_list *notused)
578 {
579 struct interface *ifp;
580 struct listnode *node;
581
582 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
583 babel_distribute_update_interface (ifp);
584 }
585
586 static void
587 babel_distribute_update_all_wrapper (struct access_list *notused)
588 {
589 babel_distribute_update_all(NULL);
590 }
591
592
593 /* [Command] */
594 DEFUN (router_babel,
595 router_babel_cmd,
596 "router babel",
597 "Enable a routing process\n"
598 "Make Babel instance command\n"
599 "No attributes\n")
600 {
601 int ret;
602
603 vty->node = BABEL_NODE;
604
605 if (!babel_routing_process) {
606 ret = babel_create_routing_process ();
607
608 /* Notice to user we couldn't create Babel. */
609 if (ret < 0) {
610 zlog_warn ("can't create Babel");
611 return CMD_WARNING;
612 }
613 }
614
615 return CMD_SUCCESS;
616 }
617
618 /* [Command] */
619 DEFUN (no_router_babel,
620 no_router_babel_cmd,
621 "no router babel",
622 NO_STR
623 "Disable a routing process\n"
624 "Remove Babel instance command\n"
625 "No attributes\n")
626 {
627 if(babel_routing_process)
628 babel_clean_routing_process();
629 return CMD_SUCCESS;
630 }
631
632 /* [Babel Command] */
633 DEFUN (babel_set_resend_delay,
634 babel_set_resend_delay_cmd,
635 "babel resend-delay <20-655340>",
636 "Babel commands\n"
637 "Time before resending a message\n"
638 "Milliseconds\n")
639 {
640 int interval;
641
642 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
643
644 resend_delay = interval;
645 return CMD_SUCCESS;
646 }
647
648 void
649 babeld_quagga_init(void)
650 {
651
652 install_node(&cmd_babel_node, &babel_config_write);
653
654 install_element(CONFIG_NODE, &router_babel_cmd);
655 install_element(CONFIG_NODE, &no_router_babel_cmd);
656
657 install_default(BABEL_NODE);
658 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
659
660 babel_if_init();
661
662 /* Access list install. */
663 access_list_init ();
664 access_list_add_hook (babel_distribute_update_all_wrapper);
665 access_list_delete_hook (babel_distribute_update_all_wrapper);
666
667 /* Prefix list initialize.*/
668 prefix_list_init ();
669 prefix_list_add_hook (babel_distribute_update_all);
670 prefix_list_delete_hook (babel_distribute_update_all);
671
672 /* Distribute list install. */
673 distribute_list_init (BABEL_NODE);
674 distribute_list_add_hook (babel_distribute_update);
675 distribute_list_delete_hook (babel_distribute_update);
676 }
677
678 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
679
680 int
681 input_filter(const unsigned char *id,
682 const unsigned char *prefix, unsigned short plen,
683 const unsigned char *neigh, unsigned int ifindex)
684 {
685 return babel_filter(0, prefix, plen, ifindex);
686 }
687
688 int
689 output_filter(const unsigned char *id, const unsigned char *prefix,
690 unsigned short plen, unsigned int ifindex)
691 {
692 return babel_filter(1, prefix, plen, ifindex);
693 }
694
695 /* There's no redistribute filter in Quagga -- the zebra daemon does its
696 own filtering. */
697 int
698 redistribute_filter(const unsigned char *prefix, unsigned short plen,
699 unsigned int ifindex, int proto)
700 {
701 return 0;
702 }
703
704 void
705 show_babeld_configuration (struct vty *vty)
706 {
707 vty_out(vty, "babeld running process %s.%s",
708 babel_routing_process ? "enable" : "disable", VTY_NEWLINE);
709 }