/** * process the kernel change list. * the routes are already ordered such that nexthop routes * are on the head of the queue. * non-nexthop routes need to be changed first and therefore * the queue needs to be traversed from tail to head. */ static void olsr_chg_kernel_routes(struct list_node *head_node) { struct rt_entry *rt; if (list_is_empty(head_node)) { return; } /* * Traverse from the beginning to the end of the list, * such that nexthop routes are added first. */ while (!list_is_empty(head_node)) { rt = changelist2rt(head_node->next); /*deleting routes should not be required anymore as we use (NLM_F_CREATE | NLM_F_REPLACE) in linux rtnetlink*/ #ifdef LINUX_NETLINK_ROUTING /*delete routes with ipv6 only as it still doesn`t support NLM_F_REPLACE*/ if (((olsr_cnf->ip_version != AF_INET ) || (olsr_addroute_function != olsr_ioctl_add_route) || (olsr_addroute6_function != olsr_ioctl_add_route6) || (olsr_delroute_function != olsr_ioctl_del_route) || (olsr_delroute6_function != olsr_ioctl_del_route6)) && (rt->rt_nexthop.iif_index > -1)) { olsr_delete_kernel_route(rt); } #else /*no rtnetlink we have to delete routes*/ if (rt->rt_nexthop.iif_index > -1) olsr_delete_kernel_route(rt); #endif /*LINUX_NETLINK_ROUTING*/ olsr_add_kernel_route(rt); list_remove(&rt->rt_change_node); } }
/** * process the kernel change list. * the routes are already ordered such that nexthop routes * are on the head of the queue. * non-nexthop routes need to be changed first and therefore * the queue needs to be traversed from tail to head. */ static void olsr_chg_kernel_routes(struct list_node *head_node) { struct rt_entry *rt; if (list_is_empty(head_node)) { return; } /* * Traverse from the beginning to the end of the list, * such that nexthop routes are added first. */ while (!list_is_empty(head_node)) { rt = changelist2rt(head_node->next); #ifdef linux /* * actively deleting routes is not necessary as we use (NLM_F_CREATE | NLM_F_REPLACE) with linux * (i.e. new routes simply overwrite the old ones in kernel) * BUT: We still have to actively delete routes if fib_metric != FLAT or we run on ipv6. * As NLM_F_REPLACE is not supported with IPv6, or simply of no use with varying route metrics. * We also actively delete routes if custom route functions are in place. (e.g. quagga plugin) */ if (((olsr_cnf->ip_version != AF_INET ) || (olsr_cnf->fib_metric != FIBM_FLAT) || (olsr_addroute_function != olsr_ioctl_add_route) || (olsr_addroute6_function != olsr_ioctl_add_route6) || (olsr_delroute_function != olsr_ioctl_del_route) || (olsr_delroute6_function != olsr_ioctl_del_route6)) && (rt->rt_nexthop.iif_index > -1)) { olsr_delete_kernel_route(rt); } #else /*no rtnetlink we have to delete routes*/ if (rt->rt_nexthop.iif_index > -1) olsr_delete_kernel_route(rt); #endif /* linux */ olsr_add_kernel_route(rt); list_remove(&rt->rt_change_node); } }
/** * Walk all the routes, remove outdated routes and run * best path selection on the remaining set. * Finally compare the nexthop of the route head and the best * path and enqueue an add/chg operation. */ void olsr_update_rib_routes(void) { struct rt_entry *rt; OLSR_PRINTF(3, "Updating kernel routes...\n"); /* walk all routes in the RIB. */ OLSR_FOR_ALL_RT_ENTRIES(rt) { /* eliminate first unused routes */ olsr_delete_outdated_routes(rt); if (!rt->rt_path_tree.count) { /* oops, all routes are gone - flush the route head */ if (olsr_delete_kernel_route(rt) == 0) { /*only remove if deletion was successful*/ avl_delete(&routingtree, &rt->rt_tree_node); olsr_cookie_free(rt_mem_cookie, rt); } continue; } /* run best route election */ olsr_rt_best(rt); /* nexthop or hopcount change ? */ if (olsr_nh_change(&rt->rt_best->rtp_nexthop, &rt->rt_nexthop) || (FIBM_CORRECT == olsr_cnf->fib_metric && olsr_hopcount_change(&rt->rt_best->rtp_metric, &rt->rt_metric))) { /* this is a route add or change. */ olsr_enqueue_rt(&chg_kernel_list, rt); } } OLSR_FOR_ALL_RT_ENTRIES_END(rt); }