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.
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.
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/>.
15 * This file incorporates work covered by the following copyright and
18 Copyright (c) 2007, 2008 by Juliusz Chroboczek
19 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
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:
28 The above copyright notice and this permission notice shall be included in
29 all copies or substantial portions of the Software.
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
46 #include "babel_interface.h"
48 #include "neighbour.h"
54 static void consider_route(struct babel_route
*route
);
56 struct babel_route
**routes
= NULL
;
57 static int route_slots
= 0, max_route_slots
= 0;
58 int kernel_metric
= 0;
59 int allow_duplicates
= -1;
60 int diversity_kind
= DIVERSITY_NONE
;
61 int diversity_factor
= 256; /* in units of 1/256 */
62 int keep_unfeasible
= 0;
64 /* We maintain a list of "slots", ordered by prefix. Every slot
65 contains a linked list of the routes to this prefix, with the
66 installed route, if any, at the head of the list. */
69 route_compare(const unsigned char *prefix
, unsigned char plen
,
70 struct babel_route
*route
)
72 int i
= memcmp(prefix
, route
->src
->prefix
, 16);
76 if(plen
< route
->src
->plen
)
78 else if(plen
> route
->src
->plen
)
84 /* Performs binary search, returns -1 in case of failure. In the latter
85 case, new_return is the place where to insert the new element. */
88 find_route_slot(const unsigned char *prefix
, unsigned char plen
,
99 p
= 0; g
= route_slots
- 1;
103 c
= route_compare(prefix
, plen
, routes
[m
]);
119 find_route(const unsigned char *prefix
, unsigned char plen
,
120 struct neighbour
*neigh
, const unsigned char *nexthop
)
122 struct babel_route
*route
;
123 int i
= find_route_slot(prefix
, plen
, NULL
);
131 if(route
->neigh
== neigh
&& memcmp(route
->nexthop
, nexthop
, 16) == 0)
140 find_installed_route(const unsigned char *prefix
, unsigned char plen
)
142 int i
= find_route_slot(prefix
, plen
, NULL
);
144 if(i
>= 0 && routes
[i
]->installed
)
150 /* Returns an overestimate of the number of installed routes. */
152 installed_routes_estimate(void)
158 resize_route_table(int new_slots
)
160 struct babel_route
**new_routes
;
161 assert(new_slots
>= route_slots
);
167 new_routes
= realloc(routes
, new_slots
* sizeof(struct babel_route
*));
168 if(new_routes
== NULL
)
172 max_route_slots
= new_slots
;
177 /* Insert a route into the table. If successful, retains the route.
178 On failure, caller must free the route. */
179 static struct babel_route
*
180 insert_route(struct babel_route
*route
)
184 assert(!route
->installed
);
186 i
= find_route_slot(route
->src
->prefix
, route
->src
->plen
, &n
);
189 if(route_slots
>= max_route_slots
)
190 resize_route_table(max_route_slots
< 1 ? 8 : 2 * max_route_slots
);
191 if(route_slots
>= max_route_slots
)
195 memmove(routes
+ n
+ 1, routes
+ n
,
196 (route_slots
- n
) * sizeof(struct babel_route
*));
200 struct babel_route
*r
;
212 flush_route(struct babel_route
*route
)
219 oldmetric
= route_metric(route
);
222 if(route
->installed
) {
223 uninstall_route(route
);
227 i
= find_route_slot(route
->src
->prefix
, route
->src
->plen
, NULL
);
228 assert(i
>= 0 && i
< route_slots
);
230 if(route
== routes
[i
]) {
231 routes
[i
] = route
->next
;
235 if(routes
[i
] == NULL
) {
236 if(i
< route_slots
- 1)
237 memmove(routes
+ i
, routes
+ i
+ 1,
238 (route_slots
- i
- 1) * sizeof(struct babel_route
*));
239 routes
[route_slots
- 1] = NULL
;
244 resize_route_table(0);
245 else if(max_route_slots
> 8 && route_slots
< max_route_slots
/ 4)
246 resize_route_table(max_route_slots
/ 2);
248 struct babel_route
*r
= routes
[i
];
249 while(r
->next
!= route
)
251 r
->next
= route
->next
;
257 route_lost(src
, oldmetric
);
267 /* Start from the end, to avoid shifting the table. */
270 while(i
< route_slots
) {
271 /* Uninstall first, to avoid calling route_lost. */
272 if(routes
[i
]->installed
)
273 uninstall_route(routes
[0]);
274 flush_route(routes
[i
]);
279 check_sources_released();
283 flush_neighbour_routes(struct neighbour
*neigh
)
288 while(i
< route_slots
) {
289 struct babel_route
*r
;
292 if(r
->neigh
== neigh
) {
305 flush_interface_routes(struct interface
*ifp
, int v4only
)
310 while(i
< route_slots
) {
311 struct babel_route
*r
;
314 if(r
->neigh
->ifp
== ifp
&&
315 (!v4only
|| v4mapped(r
->nexthop
))) {
327 /* Iterate a function over all routes. */
329 for_all_routes(void (*f
)(struct babel_route
*, void*), void *closure
)
333 for(i
= 0; i
< route_slots
; i
++) {
334 struct babel_route
*r
= routes
[i
];
343 for_all_installed_routes(void (*f
)(struct babel_route
*, void*), void *closure
)
347 for(i
= 0; i
< route_slots
; i
++) {
348 if(routes
[i
]->installed
)
349 (*f
)(routes
[i
], closure
);
354 metric_to_kernel(int metric
)
356 return metric
< INFINITY
? kernel_metric
: KERNEL_INFINITY
;
359 /* This is used to maintain the invariant that the installed route is at
360 the head of the list. */
362 move_installed_route(struct babel_route
*route
, int i
)
364 assert(i
>= 0 && i
< route_slots
);
365 assert(route
->installed
);
367 if(route
!= routes
[i
]) {
368 struct babel_route
*r
= routes
[i
];
369 while(r
->next
!= route
)
371 r
->next
= route
->next
;
372 route
->next
= routes
[i
];
378 install_route(struct babel_route
*route
)
385 if(!route_feasible(route
))
386 zlog_err("WARNING: installing unfeasible route "
387 "(this shouldn't happen).");
389 i
= find_route_slot(route
->src
->prefix
, route
->src
->plen
, NULL
);
390 assert(i
>= 0 && i
< route_slots
);
392 if(routes
[i
] != route
&& routes
[i
]->installed
) {
393 fprintf(stderr
, "WARNING: attempting to install duplicate route "
394 "(this shouldn't happen).");
398 rc
= kernel_route(ROUTE_ADD
, route
->src
->prefix
, route
->src
->plen
,
400 route
->neigh
->ifp
->ifindex
,
401 metric_to_kernel(route_metric(route
)), NULL
, 0, 0);
404 zlog_err("kernel_route(ADD): %s", safe_strerror(errno
));
408 route
->installed
= 1;
409 move_installed_route(route
, i
);
414 uninstall_route(struct babel_route
*route
)
418 if(!route
->installed
)
421 rc
= kernel_route(ROUTE_FLUSH
, route
->src
->prefix
, route
->src
->plen
,
423 route
->neigh
->ifp
->ifindex
,
424 metric_to_kernel(route_metric(route
)), NULL
, 0, 0);
426 zlog_err("kernel_route(FLUSH): %s", safe_strerror(errno
));
428 route
->installed
= 0;
431 /* This is equivalent to uninstall_route followed with install_route,
432 but without the race condition. The destination of both routes
436 switch_routes(struct babel_route
*old
, struct babel_route
*new)
448 if(!route_feasible(new))
449 zlog_err("WARNING: switching to unfeasible route "
450 "(this shouldn't happen).");
452 rc
= kernel_route(ROUTE_MODIFY
, old
->src
->prefix
, old
->src
->plen
,
453 old
->nexthop
, old
->neigh
->ifp
->ifindex
,
454 metric_to_kernel(route_metric(old
)),
455 new->nexthop
, new->neigh
->ifp
->ifindex
,
456 metric_to_kernel(route_metric(new)));
458 zlog_err("kernel_route(MODIFY): %s", safe_strerror(errno
));
464 move_installed_route(new, find_route_slot(new->src
->prefix
, new->src
->plen
,
469 change_route_metric(struct babel_route
*route
,
470 unsigned refmetric
, unsigned cost
, unsigned add
)
473 int newmetric
= MIN(refmetric
+ cost
+ add
, INFINITY
);
475 old
= metric_to_kernel(route_metric(route
));
476 new = metric_to_kernel(newmetric
);
478 if(route
->installed
&& old
!= new) {
480 rc
= kernel_route(ROUTE_MODIFY
, route
->src
->prefix
, route
->src
->plen
,
481 route
->nexthop
, route
->neigh
->ifp
->ifindex
,
483 route
->nexthop
, route
->neigh
->ifp
->ifindex
,
486 zlog_err("kernel_route(MODIFY metric): %s", safe_strerror(errno
));
491 route
->refmetric
= refmetric
;
493 route
->add_metric
= add
;
497 retract_route(struct babel_route
*route
)
499 change_route_metric(route
, INFINITY
, INFINITY
, 0);
503 route_feasible(struct babel_route
*route
)
505 return update_feasible(route
->src
, route
->seqno
, route
->refmetric
);
509 route_old(struct babel_route
*route
)
511 return route
->time
< babel_now
.tv_sec
- route
->hold_time
* 7 / 8;
515 route_expired(struct babel_route
*route
)
517 return route
->time
< babel_now
.tv_sec
- route
->hold_time
;
521 channels_interfere(int ch1
, int ch2
)
523 if(ch1
== BABEL_IF_CHANNEL_NONINTERFERING
524 || ch2
== BABEL_IF_CHANNEL_NONINTERFERING
)
526 if(ch1
== BABEL_IF_CHANNEL_INTERFERING
527 || ch2
== BABEL_IF_CHANNEL_INTERFERING
)
533 route_interferes(struct babel_route
*route
, struct interface
*ifp
)
535 struct babel_interface
*babel_ifp
= NULL
;
536 switch(diversity_kind
) {
539 case DIVERSITY_INTERFACE_1
:
540 return route
->neigh
->ifp
== ifp
;
541 case DIVERSITY_CHANNEL_1
:
542 case DIVERSITY_CHANNEL
:
543 if(route
->neigh
->ifp
== ifp
)
545 babel_ifp
= babel_get_if_nfo(ifp
);
546 if(channels_interfere(babel_ifp
->channel
,
547 babel_get_if_nfo(route
->neigh
->ifp
)->channel
))
549 if(diversity_kind
== DIVERSITY_CHANNEL
) {
551 for(i
= 0; i
< DIVERSITY_HOPS
; i
++) {
552 if(route
->channels
[i
] == 0)
554 if(channels_interfere(babel_ifp
->channel
, route
->channels
[i
]))
560 fprintf(stderr
, "Unknown kind of diversity.\n");
566 update_feasible(struct source
*src
,
567 unsigned short seqno
, unsigned short refmetric
)
572 if(src
->time
< babel_now
.tv_sec
- SOURCE_GC_TIME
)
573 /* Never mind what is probably stale data */
576 if(refmetric
>= INFINITY
)
577 /* Retractions are always feasible */
580 return (seqno_compare(seqno
, src
->seqno
) > 0 ||
581 (src
->seqno
== seqno
&& refmetric
< src
->metric
));
584 /* This returns the feasible route with the smallest metric. */
586 find_best_route(const unsigned char *prefix
, unsigned char plen
, int feasible
,
587 struct neighbour
*exclude
)
589 struct babel_route
*route
= NULL
, *r
= NULL
;
590 int i
= find_route_slot(prefix
, plen
, NULL
);
599 if(!route_expired(r
) &&
600 (!feasible
|| route_feasible(r
)) &&
601 (!exclude
|| r
->neigh
!= exclude
) &&
602 (route_metric(r
) < route_metric(route
)))
610 update_route_metric(struct babel_route
*route
)
612 int oldmetric
= route_metric(route
);
614 if(route_expired(route
)) {
615 if(route
->refmetric
< INFINITY
) {
616 route
->seqno
= seqno_plus(route
->src
->seqno
, 1);
617 retract_route(route
);
618 if(oldmetric
< INFINITY
)
619 route_changed(route
, route
->src
, oldmetric
);
622 struct neighbour
*neigh
= route
->neigh
;
623 int add_metric
= input_filter(route
->src
->id
,
624 route
->src
->prefix
, route
->src
->plen
,
626 neigh
->ifp
->ifindex
);
627 change_route_metric(route
, route
->refmetric
,
628 neighbour_cost(route
->neigh
), add_metric
);
629 if(route_metric(route
) != oldmetric
)
630 route_changed(route
, route
->src
, oldmetric
);
634 /* Called whenever a neighbour's cost changes, to update the metric of
635 all routes through that neighbour. Calls local_notify_neighbour. */
637 update_neighbour_metric(struct neighbour
*neigh
, int changed
)
643 for(i
= 0; i
< route_slots
; i
++) {
644 struct babel_route
*r
= routes
[i
];
646 if(r
->neigh
== neigh
)
647 update_route_metric(r
);
655 update_interface_metric(struct interface
*ifp
)
659 for(i
= 0; i
< route_slots
; i
++) {
660 struct babel_route
*r
= routes
[i
];
662 if(r
->neigh
->ifp
== ifp
)
663 update_route_metric(r
);
669 /* This is called whenever we receive an update. */
671 update_route(const unsigned char *router_id
,
672 const unsigned char *prefix
, unsigned char plen
,
673 unsigned short seqno
, unsigned short refmetric
,
674 unsigned short interval
,
675 struct neighbour
*neigh
, const unsigned char *nexthop
,
676 const unsigned char *channels
, int channels_len
)
678 struct babel_route
*route
;
680 int metric
, feasible
;
682 int hold_time
= MAX((4 * interval
) / 100 + interval
/ 50, 15);
684 if(memcmp(router_id
, myid
, 8) == 0)
687 if(martian_prefix(prefix
, plen
)) {
688 zlog_err("Rejecting martian route to %s through %s.",
689 format_prefix(prefix
, plen
), format_address(router_id
));
693 add_metric
= input_filter(router_id
, prefix
, plen
,
694 neigh
->address
, neigh
->ifp
->ifindex
);
695 if(add_metric
>= INFINITY
)
698 route
= find_route(prefix
, plen
, neigh
, nexthop
);
700 if(route
&& memcmp(route
->src
->id
, router_id
, 8) == 0)
701 /* Avoid scanning the source table. */
704 src
= find_source(router_id
, prefix
, plen
, 1, seqno
);
709 feasible
= update_feasible(src
, seqno
, refmetric
);
710 metric
= MIN((int)refmetric
+ neighbour_cost(neigh
) + add_metric
, INFINITY
);
713 struct source
*oldsrc
;
714 unsigned short oldmetric
;
718 oldmetric
= route_metric(route
);
720 /* If a successor switches sources, we must accept his update even
721 if it makes a route unfeasible in order to break any routing loops
722 in a timely manner. If the source remains the same, we ignore
724 if(!feasible
&& route
->installed
) {
725 debugf(BABEL_DEBUG_COMMON
,"Unfeasible update for installed route to %s "
726 "(%s %d %d -> %s %d %d).",
727 format_prefix(src
->prefix
, src
->plen
),
728 format_address(route
->src
->id
),
729 route
->seqno
, route
->refmetric
,
730 format_address(src
->id
), seqno
, refmetric
);
731 if(src
!= route
->src
) {
732 uninstall_route(route
);
737 route
->src
= retain_source(src
);
738 if((feasible
|| keep_unfeasible
) && refmetric
< INFINITY
)
739 route
->time
= babel_now
.tv_sec
;
740 route
->seqno
= seqno
;
741 change_route_metric(route
,
742 refmetric
, neighbour_cost(neigh
), add_metric
);
743 route
->hold_time
= hold_time
;
745 route_changed(route
, oldsrc
, oldmetric
);
747 route_lost(oldsrc
, oldmetric
);
750 send_unfeasible_request(neigh
, route
->installed
&& route_old(route
),
752 release_source(oldsrc
);
754 struct babel_route
*new_route
;
756 if(refmetric
>= INFINITY
)
757 /* Somebody's retracting a route we never saw. */
760 send_unfeasible_request(neigh
, 0, seqno
, metric
, src
);
765 route
= malloc(sizeof(struct babel_route
));
767 perror("malloc(route)");
771 route
->src
= retain_source(src
);
772 route
->refmetric
= refmetric
;
773 route
->cost
= neighbour_cost(neigh
);
774 route
->add_metric
= add_metric
;
775 route
->seqno
= seqno
;
776 route
->neigh
= neigh
;
777 memcpy(route
->nexthop
, nexthop
, 16);
778 route
->time
= babel_now
.tv_sec
;
779 route
->hold_time
= hold_time
;
780 route
->installed
= 0;
781 memset(&route
->channels
, 0, sizeof(route
->channels
));
783 memcpy(&route
->channels
, channels
,
784 MIN(channels_len
, DIVERSITY_HOPS
));
786 new_route
= insert_route(route
);
787 if(new_route
== NULL
) {
788 fprintf(stderr
, "Couldn't insert route.\n");
792 consider_route(route
);
797 /* We just received an unfeasible update. If it's any good, send
798 a request for a new seqno. */
800 send_unfeasible_request(struct neighbour
*neigh
, int force
,
801 unsigned short seqno
, unsigned short metric
,
804 struct babel_route
*route
= find_installed_route(src
->prefix
, src
->plen
);
806 if(seqno_minus(src
->seqno
, seqno
) > 100) {
807 /* Probably a source that lost its seqno. Let it time-out. */
811 if(force
|| !route
|| route_metric(route
) >= metric
+ 512) {
812 send_unicast_multihop_request(neigh
, src
->prefix
, src
->plen
,
813 src
->metric
>= INFINITY
?
815 seqno_plus(src
->seqno
, 1),
820 /* This takes a feasible route and decides whether to install it. */
822 consider_route(struct babel_route
*route
)
824 struct babel_route
*installed
;
825 struct xroute
*xroute
;
830 if(!route_feasible(route
))
833 xroute
= find_xroute(route
->src
->prefix
, route
->src
->plen
);
834 if(xroute
&& (allow_duplicates
< 0 || xroute
->metric
>= allow_duplicates
))
837 installed
= find_installed_route(route
->src
->prefix
, route
->src
->plen
);
839 if(installed
== NULL
)
842 if(route_metric(route
) >= INFINITY
)
845 if(route_metric(installed
) >= INFINITY
)
848 if(route_metric(installed
) >= route_metric(route
) + 64)
854 switch_routes(installed
, route
);
855 if(installed
&& route
->installed
)
856 send_triggered_update(route
, installed
->src
, route_metric(installed
));
858 send_update(NULL
, 1, route
->src
->prefix
, route
->src
->plen
);
863 retract_neighbour_routes(struct neighbour
*neigh
)
867 for(i
= 0; i
< route_slots
; i
++) {
868 struct babel_route
*r
= routes
[i
];
870 if(r
->neigh
== neigh
) {
871 if(r
->refmetric
!= INFINITY
) {
872 unsigned short oldmetric
= route_metric(r
);
874 if(oldmetric
!= INFINITY
)
875 route_changed(r
, r
->src
, oldmetric
);
885 send_triggered_update(struct babel_route
*route
, struct source
*oldsrc
,
888 unsigned newmetric
, diff
;
889 /* 1 means send speedily, 2 means resend */
892 if(!route
->installed
)
895 newmetric
= route_metric(route
);
897 newmetric
>= oldmetric
? newmetric
- oldmetric
: oldmetric
- newmetric
;
899 if(route
->src
!= oldsrc
|| (oldmetric
< INFINITY
&& newmetric
>= INFINITY
))
900 /* Switching sources can cause transient routing loops.
901 Retractions can cause blackholes. */
903 else if(newmetric
> oldmetric
&& oldmetric
< 6 * 256 && diff
>= 512)
904 /* Route getting significantly worse */
906 else if(unsatisfied_request(route
->src
->prefix
, route
->src
->plen
,
907 route
->seqno
, route
->src
->id
))
908 /* Make sure that requests are satisfied speedily */
910 else if(oldmetric
>= INFINITY
&& newmetric
< INFINITY
)
913 else if(newmetric
< oldmetric
&& diff
< 1024)
914 /* Route getting better. This may be a transient fluctuation, so
915 don't advertise it to avoid making routes unfeasible later on. */
918 /* Don't fret about trivialities */
924 send_update_resend(NULL
, route
->src
->prefix
, route
->src
->plen
);
926 send_update(NULL
, urgent
, route
->src
->prefix
, route
->src
->plen
);
928 if(oldmetric
< INFINITY
) {
929 if(newmetric
>= oldmetric
+ 512) {
930 send_request_resend(NULL
, route
->src
->prefix
, route
->src
->plen
,
931 route
->src
->metric
>= INFINITY
?
933 seqno_plus(route
->src
->seqno
, 1),
935 } else if(newmetric
>= oldmetric
+ 288) {
936 send_request(NULL
, route
->src
->prefix
, route
->src
->plen
);
941 /* A route has just changed. Decide whether to switch to a different route or
944 route_changed(struct babel_route
*route
,
945 struct source
*oldsrc
, unsigned short oldmetric
)
947 if(route
->installed
) {
948 if(route_metric(route
) > oldmetric
) {
949 struct babel_route
*better_route
;
951 find_best_route(route
->src
->prefix
, route
->src
->plen
, 1, NULL
);
953 route_metric(better_route
) <= route_metric(route
) - 96)
954 consider_route(better_route
);
958 /* We didn't change routes after all. */
959 send_triggered_update(route
, oldsrc
, oldmetric
);
961 /* Reconsider routes even when their metric didn't decrease,
962 they may not have been feasible before. */
963 consider_route(route
);
967 /* We just lost the installed route to a given destination. */
969 route_lost(struct source
*src
, unsigned oldmetric
)
971 struct babel_route
*new_route
;
972 new_route
= find_best_route(src
->prefix
, src
->plen
, 1, NULL
);
974 consider_route(new_route
);
975 } else if(oldmetric
< INFINITY
) {
976 /* Complain loudly. */
977 send_update_resend(NULL
, src
->prefix
, src
->plen
);
978 send_request_resend(NULL
, src
->prefix
, src
->plen
,
979 src
->metric
>= INFINITY
?
980 src
->seqno
: seqno_plus(src
->seqno
, 1),
985 /* This is called periodically to flush old routes. It will also send
986 requests for routes that are about to expire. */
990 struct babel_route
*r
;
993 debugf(BABEL_DEBUG_COMMON
,"Expiring old routes.");
996 while(i
< route_slots
) {
999 /* Protect against clock being stepped. */
1000 if(r
->time
> babel_now
.tv_sec
|| route_old(r
)) {
1005 update_route_metric(r
);
1007 if(r
->installed
&& r
->refmetric
< INFINITY
) {
1009 /* Route about to expire, send a request. */
1010 send_unicast_request(r
->neigh
,
1011 r
->src
->prefix
, r
->src
->plen
);