3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5 * RIB implementation (c) 2007, Hannes Gredler (hannes@gredler.at)
8 * export_route_entry interface added by Immo 'FaUl Wehrenberg
9 * <immo@chaostreff-dortmund.de> and reworked by sven-ola 2007
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 * Visit http://www.olsr.org for more information.
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
50 #include "kernel_routes.h"
51 #include "common/avl.h"
54 #include "olsr_cookie.h"
55 #include "olsr_niit.h"
58 char *StrError(unsigned int ErrNo);
60 #define strerror(x) StrError(x)
63 static struct list_node chg_kernel_list;
67 * Calculate the kernel route flags.
68 * Called before enqueuing a change/delete operation
72 olsr_rt_flags(const struct rt_entry *rt)
74 const struct rt_nexthop *nh;
75 uint8_t flags = RTF_UP;
77 /* destination is host */
78 if (rt->rt_dst.prefix_len == olsr_cnf->maxplen) {
84 if (!ipequal(&rt->rt_dst.prefix, &nh->gateway)) {
91 export_route_function olsr_addroute_function;
92 export_route_function olsr_addroute6_function;
93 export_route_function olsr_delroute_function;
94 export_route_function olsr_delroute6_function;
97 olsr_init_export_route(void)
99 /* the add/chg/del kernel queues */
100 //list_head_init(&add_kernel_list);
101 list_head_init(&chg_kernel_list);
103 olsr_addroute_function = olsr_ioctl_add_route;
104 olsr_addroute6_function = olsr_ioctl_add_route6;
105 olsr_delroute_function = olsr_ioctl_del_route;
106 olsr_delroute6_function = olsr_ioctl_del_route6;
110 * Delete all OLSR routes.
112 * This is extremely simple - Just increment the version of the
113 * tree and then olsr_update_rib_routes() will see all routes in the tree
114 * as outdated and olsr_update_kernel_routes() will finally flush it.
118 olsr_delete_all_kernel_routes(void)
120 OLSR_PRINTF(1, "Deleting all routes...\n");
122 olsr_bump_routingtree_version();
123 olsr_update_rib_routes();
124 olsr_update_kernel_routes();
128 * Enqueue a route on a kernel add/chg/del queue.
131 olsr_enqueue_rt(struct list_node *head_node, struct rt_entry *rt)
133 const struct rt_nexthop *nh;
135 /* if this node is already on some changelist we are done */
136 if (list_node_on_list(&rt->rt_change_node)) {
141 * For easier route dependency tracking we enqueue nexthop routes
142 * at the head of the queue and non-nexthop routes at the tail of the queue.
144 nh = olsr_get_nh(rt);
146 if (ipequal(&rt->rt_dst.prefix, &nh->gateway)) {
147 list_add_after(head_node, &rt->rt_change_node);
149 list_add_before(head_node, &rt->rt_change_node);
154 * Process a route from the kernel deletion list.
156 *@return -1 on error, else 0
159 olsr_delete_kernel_route(struct rt_entry *rt)
161 if (rt->rt_metric.hops > 1) {
163 if (ip_is_linklocal(&rt->rt_dst.prefix)) {
164 /* do not delete a route with a LL IP as a destination */
169 if (!olsr_cnf->host_emul) {
170 int16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt);
173 const char *const err_msg = strerror(errno);
174 const char *const routestr = olsr_rt_to_string(rt);
175 OLSR_PRINTF(1, "KERN: ERROR deleting %s: %s\n", routestr, err_msg);
177 olsr_syslog(OLSR_LOG_ERR, "Delete route %s: %s", routestr, err_msg);
180 #ifdef LINUX_NETLINK_ROUTING
181 /* call NIIT handler (always)*/
182 if (olsr_cnf->use_niit) {
183 olsr_niit_handle_route(rt, false);
191 * Process a route from the kernel addition list.
196 olsr_add_kernel_route(struct rt_entry *rt)
198 if (rt->rt_best->rtp_metric.hops > 1) {
200 if (ip_is_linklocal(&rt->rt_best->rtp_dst.prefix)) {
201 /* do not create a route with a LL IP as a destination */
205 if (!olsr_cnf->host_emul) {
206 int16_t error = (olsr_cnf->ip_version == AF_INET) ? olsr_addroute_function(rt) : olsr_addroute6_function(rt);
209 const char *const err_msg = strerror(errno);
210 const char *const routestr = olsr_rtp_to_string(rt->rt_best);
211 OLSR_PRINTF(1, "KERN: ERROR adding %s: %s\n", routestr, err_msg);
213 olsr_syslog(OLSR_LOG_ERR, "Add route %s: %s", routestr, err_msg);
215 /* route addition has suceeded */
217 /* save the nexthop and metric in the route entry */
218 rt->rt_nexthop = rt->rt_best->rtp_nexthop;
219 rt->rt_metric = rt->rt_best->rtp_metric;
221 #ifdef LINUX_NETLINK_ROUTING
222 /* call NIIT handler */
223 if (olsr_cnf->use_niit) {
224 olsr_niit_handle_route(rt, true);
232 * process the kernel change list.
233 * the routes are already ordered such that nexthop routes
234 * are on the head of the queue.
235 * non-nexthop routes need to be changed first and therefore
236 * the queue needs to be traversed from tail to head.
239 olsr_chg_kernel_routes(struct list_node *head_node)
243 if (list_is_empty(head_node)) {
248 * Traverse from the beginning to the end of the list,
249 * such that nexthop routes are added first.
251 while (!list_is_empty(head_node)) {
252 rt = changelist2rt(head_node->next);
254 /*deleting routes should not be required anymore as we use (NLM_F_CREATE | NLM_F_REPLACE) in linux rtnetlink*/
255 #ifdef LINUX_NETLINK_ROUTING
256 /*delete routes with ipv6 only as it still doesn`t support NLM_F_REPLACE or with any fib_metric != flat*/
257 if (((olsr_cnf->ip_version != AF_INET ) || (olsr_cnf->fib_metric != FIBM_FLAT)
258 || (olsr_addroute_function != olsr_ioctl_add_route) || (olsr_addroute6_function != olsr_ioctl_add_route6)
259 || (olsr_delroute_function != olsr_ioctl_del_route) || (olsr_delroute6_function != olsr_ioctl_del_route6))
260 && (rt->rt_nexthop.iif_index > -1)) {
261 olsr_delete_kernel_route(rt);
264 /*no rtnetlink we have to delete routes*/
265 if (rt->rt_nexthop.iif_index > -1) olsr_delete_kernel_route(rt);
266 #endif /*LINUX_NETLINK_ROUTING*/
268 olsr_add_kernel_route(rt);
270 list_remove(&rt->rt_change_node);
275 * Check the version number of all route paths hanging off a route entry.
276 * If a route does not match the current routing tree number, remove it
277 * from the global originator tree for that rt_entry.
278 * Reset the best route pointer.
281 olsr_delete_outdated_routes(struct rt_entry *rt)
284 struct avl_node *rtp_tree_node, *next_rtp_tree_node;
286 for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
288 * pre-fetch the next node before loosing context.
290 next_rtp_tree_node = avl_walk_next(rtp_tree_node);
292 rtp = rtp_tree2rtp(rtp_tree_node);
295 * check the version number which gets incremented on every SPF run.
296 * comparing for unequalness avoids handling version number wraps.
298 if (routingtree_version != rtp->rtp_version) {
299 /* remove from the originator tree */
300 avl_delete(&rt->rt_path_tree, rtp_tree_node);
303 if (rt->rt_best == rtp) {
311 * Walk all the routes, remove outdated routes and run
312 * best path selection on the remaining set.
313 * Finally compare the nexthop of the route head and the best
314 * path and enqueue an add/chg operation.
317 olsr_update_rib_routes(void)
321 OLSR_PRINTF(3, "Updating kernel routes...\n");
323 /* walk all routes in the RIB. */
325 OLSR_FOR_ALL_RT_ENTRIES(rt) {
327 /* eliminate first unused routes */
328 olsr_delete_outdated_routes(rt);
330 if (!rt->rt_path_tree.count) {
332 /* oops, all routes are gone - flush the route head */
334 if (olsr_delete_kernel_route(rt) == 0) {
335 /*only remove if deletion was successful*/
336 avl_delete(&routingtree, &rt->rt_tree_node);
337 olsr_cookie_free(rt_mem_cookie, rt);
343 /* run best route election */
346 /* nexthop or hopcount change ? */
347 if (olsr_nh_change(&rt->rt_best->rtp_nexthop, &rt->rt_nexthop)
348 || (FIBM_CORRECT == olsr_cnf->fib_metric && olsr_hopcount_change(&rt->rt_best->rtp_metric, &rt->rt_metric))) {
350 /* this is a route add or change. */
351 olsr_enqueue_rt(&chg_kernel_list, rt);
354 OLSR_FOR_ALL_RT_ENTRIES_END(rt);
358 olsr_delete_interface_routes(int if_index) {
360 bool triggerUpdate = false;
362 OLSR_FOR_ALL_RT_ENTRIES(rt) {
363 bool mightTrigger = false;
365 struct avl_node *rtp_tree_node, *next_rtp_tree_node;
367 /* run through all routing paths of route */
368 for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
370 * pre-fetch the next node before loosing context.
372 next_rtp_tree_node = avl_walk_next(rtp_tree_node);
374 rtp = rtp_tree2rtp(rtp_tree_node);
376 /* nexthop use lost interface ? */
377 if (rtp->rtp_nexthop.iif_index == if_index) {
378 /* remove from the originator tree */
379 avl_delete(&rt->rt_path_tree, rtp_tree_node);
382 if (rt->rt_best == rtp) {
390 if (!rt->rt_path_tree.count) {
391 /* oops, all routes are gone - flush the route head */
392 avl_delete(&routingtree, rt_tree_node);
394 /* do not dequeue route because they are already gone */
396 triggerUpdate = true;
398 } OLSR_FOR_ALL_RT_ENTRIES_END(rt)
400 /* trigger route update if necessary */
402 olsr_update_rib_routes();
403 olsr_update_kernel_routes();
408 * Propagate the accumulated changes from the last rib update to the kernel.
411 olsr_update_kernel_routes(void)
414 olsr_chg_kernel_routes(&chg_kernel_list);
417 olsr_print_routing_table(&routingtree);
422 olsr_force_kernelroutes_refresh(void) {
425 /* enqueue all existing routes for a rewrite */
426 OLSR_FOR_ALL_RT_ENTRIES(rt) {
427 olsr_enqueue_rt(&chg_kernel_list, rt);
428 } OLSR_FOR_ALL_RT_ENTRIES_END(rt)
430 /* trigger kernel route refresh */
431 olsr_chg_kernel_routes(&chg_kernel_list);
437 * indent-tabs-mode: nil