2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of olsr.org, olsrd nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Visit http://www.olsr.org for more information.
35 * If you find this software useful feel free to make a donation
36 * to the project. For more information see the website or contact
37 * the copyright holders.
39 * $Id: routing_table.c,v 1.28 2007/08/02 21:54:54 bernd67 Exp $
45 #include "two_hop_neighbor_table.h"
48 #include "neighbor_table.h"
51 #include "routing_table.h"
54 struct rt_entry routingtable[HASHSIZE];
55 struct rt_entry hna_routes[HASHSIZE];
59 * Prototypes for internal functions
63 olsr_fill_routing_table_with_neighbors(void);
65 static struct destination_n *
66 olsr_fill_routing_table_with_two_hop_neighbors(void);
68 static struct rt_entry *
69 olsr_check_for_higher_quality(struct rt_entry *, struct hna_net *, float);
72 olsr_check_for_lower_quality(struct rt_entry *, struct hna_net *, float);
75 two_hop_neighbor_reachable(struct neighbor_2_list_entry *);
78 * Prototypes for internal functions
83 *Initialize the routing table
86 olsr_init_routing_table(void)
90 *The hna routes hash will almost always
92 *But it is kept as a hash to be compatible
93 *with the functions used on the regular
96 for(idx=0;idx<HASHSIZE;idx++)
98 routingtable[idx].next = &routingtable[idx];
99 routingtable[idx].prev = &routingtable[idx];
100 hna_routes[idx].next = &hna_routes[idx];
101 hna_routes[idx].prev = &hna_routes[idx];
107 *Look up an entry in the routing table.
109 *@param dst the address of the entry
111 *@return a pointer to a rt_entry struct
112 *representing the route entry.
115 olsr_lookup_routing_table(union olsr_ip_addr *dst)
118 struct rt_entry *rt_table;
119 olsr_u32_t hash = olsr_hashing(dst);
121 for(rt_table = routingtable[hash].next;
122 rt_table != &routingtable[hash];
123 rt_table = rt_table->next)
125 if (COMP_IP(&rt_table->rt_dst, dst))
135 * Look up an entry in the HNA routing table.
137 * @param dst the address of the entry
139 * @return a pointer to a rt_entry struct
140 * representing the route entry.
144 olsr_lookup_hna_routing_table(union olsr_ip_addr *dst)
146 struct rt_entry *walker;
147 olsr_u32_t hash = olsr_hashing(dst);
149 for (walker = hna_routes[hash].next; walker != &hna_routes[hash];
150 walker = walker->next)
151 if (COMP_IP(&walker->rt_dst, dst))
158 *Delete all the entries in the routing table hash
160 *@param table the routing hash table
165 olsr_free_routing_table(struct rt_entry *table)
169 for(idx=0;idx<HASHSIZE;idx++)
171 struct rt_entry *destination = table[idx].next;
173 while(destination != &table[idx])
175 struct rt_entry *dst_to_delete = destination;
176 destination = destination->next;
178 DEQUEUE_ELEM(dst_to_delete);
187 *Insert an 1 or 2 neighbor-entry into the routing table.
189 *@param dst the destination
191 *@return the new rt_entry struct
194 olsr_insert_routing_table(union olsr_ip_addr *dst,
195 const union olsr_ip_addr *router,
196 struct interface *iface,
200 const olsr_u32_t hash = olsr_hashing(dst);
201 struct rt_entry *rt_list = &routingtable[hash];
202 struct rt_entry *new_route_entry = olsr_malloc(sizeof(struct rt_entry), "Insert routing table");
204 COPY_IP(&new_route_entry->rt_dst, dst);
205 COPY_IP(&new_route_entry->rt_router, router);
206 new_route_entry->rt_if = iface;
208 new_route_entry->rt_metric = metric;
211 new_route_entry->rt_etx = (float)metric;
214 new_route_entry->rt_etx = etx;
216 if(COMP_IP(dst, router))
218 new_route_entry->rt_flags = (RTF_UP|RTF_HOST);
220 new_route_entry->rt_flags = (RTF_UP|RTF_HOST|RTF_GATEWAY);
222 if(olsr_cnf->ip_version == AF_INET)
224 new_route_entry->rt_mask.v4 = NETMASK_HOST;
227 new_route_entry->rt_mask.v6 = 128;
230 rt_list->next->prev = new_route_entry;
231 new_route_entry->next = rt_list->next;
232 rt_list->next = new_route_entry;
233 new_route_entry->prev = rt_list;
235 return(new_route_entry);
241 *Insert all the one hop neighbors in the routing table.
246 olsr_fill_routing_table_with_neighbors(void)
251 OLSR_PRINTF(7, "FILL ROUTING TABLE WITH NEIGHBORS\n");
254 for(idx=0;idx<HASHSIZE;idx++)
256 struct neighbor_entry *neighbor;
257 for(neighbor = neighbortable[idx].next;
258 neighbor != &neighbortable[idx];
259 neighbor=neighbor->next)
261 if(neighbor->status == SYM)
263 static struct mid_address addrs;
264 struct mid_address *addrs2;
267 *Insert all the neighbors addresses
270 COPY_IP(&addrs.alias, &neighbor->neighbor_main_addr);
271 addrs.next_alias = mid_lookup_aliases(&neighbor->neighbor_main_addr);
273 for(addrs2 = &addrs;addrs2!=NULL;addrs2 = addrs2->next_alias)
275 const struct link_entry *lnk = get_best_link_to_neighbor(&addrs2->alias);
277 OLSR_PRINTF(7, "(ROUTE)Adding neighbor %s\n", olsr_ip_to_string(&addrs.alias));
281 struct interface *iface = lnk->if_name ? if_ifwithname(lnk->if_name) :
282 if_ifwithaddr(&lnk->local_iface_addr);
285 olsr_insert_routing_table(&addrs2->alias,
286 &lnk->neighbor_iface_addr,
301 * Check if a two hop neighbor is reachable trough
302 * a one hop neighbor with willingness != WILL_NEVER
304 * @return OLSR_TRUE if reachable OLSR_FALSE if not
307 two_hop_neighbor_reachable(struct neighbor_2_list_entry *neigh_2_list)
309 struct neighbor_list_entry *neighbors;
311 for(neighbors = neigh_2_list->neighbor_2->neighbor_2_nblist.next;
312 neighbors != &neigh_2_list->neighbor_2->neighbor_2_nblist;
313 neighbors = neighbors->next)
315 if((neighbors->neighbor->status != NOT_NEIGH) &&
316 (neighbors->neighbor->willingness != WILL_NEVER))
325 *Insert all the two hop neighbors that is not already added
326 *in the routing table.
328 *@return a pointer to a destination_n linked-list of the neighbors.
331 static struct destination_n *
332 olsr_fill_routing_table_with_two_hop_neighbors(void)
334 struct destination_n *list_destination_n=NULL;
337 //printf("FILL ROUTING TABLE WITH TWO HOP NEIGHBORS\n");
339 for(idx=0;idx<HASHSIZE;idx++)
341 struct neighbor_entry *neighbor;
343 for(neighbor = neighbortable[idx].next;
344 neighbor != &neighbortable[idx];
345 neighbor=neighbor->next)
347 struct neighbor_2_list_entry *neigh_2_list;
349 if(neighbor->status != SYM)
353 *Insert all the two hop neighbors
355 for(neigh_2_list = neighbor->neighbor_2_list.next;
356 neigh_2_list != &neighbor->neighbor_2_list;
357 neigh_2_list = neigh_2_list->next)
359 union olsr_ip_addr *n2_addr;
360 static struct mid_address addrs;
361 struct mid_address *addrsp;
363 n2_addr = &neigh_2_list->neighbor_2->neighbor_2_addr;
365 if(olsr_lookup_routing_table(n2_addr))
368 OLSR_PRINTF(7, "2hop: %s already added\n", olsr_ip_to_string(n2_addr));
373 if(!two_hop_neighbor_reachable(neigh_2_list))
375 OLSR_PRINTF(1, "Two hop neighbor %s not added - no one hop neighbors.\n",
376 olsr_ip_to_string(n2_addr));
380 COPY_IP(&addrs.alias, n2_addr);
381 addrs.next_alias = mid_lookup_aliases(n2_addr);
383 for(addrsp = &addrs; addrsp; addrsp = addrsp->next_alias)
385 const struct link_entry * const lnk = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
387 OLSR_PRINTF(7, "(ROUTE)Adding neighbor %s\n", olsr_ip_to_string(&addrsp->alias));
391 struct interface *iface = lnk->if_name ? if_ifwithname(lnk->if_name) :
392 if_ifwithaddr(&lnk->local_iface_addr);
395 struct rt_entry *new_route_entry =
396 olsr_insert_routing_table(&addrsp->alias,
397 &lnk->neighbor_iface_addr,
402 if(new_route_entry != NULL)
404 struct destination_n *tmp = olsr_malloc(sizeof(struct destination_n),
405 "Fill rt table 2 hop tmp");
406 tmp->destination = new_route_entry;
407 tmp->next = list_destination_n;
408 list_destination_n = tmp;
416 return list_destination_n;
420 *Recalculate the routing table
425 olsr_calculate_routing_table(void)
427 struct destination_n *list_destination_n_1;
429 olsr_move_route_table(routingtable, old_routes);
432 olsr_fill_routing_table_with_neighbors();
433 /* Add two hop enighbors - now they are the "outer rim" */
435 list_destination_n_1 = olsr_fill_routing_table_with_two_hop_neighbors();
436 while(list_destination_n_1)
438 /* List_destination_n_1 holds the "outer rim" */
439 struct destination_n *list_destination_n = list_destination_n_1;
441 list_destination_n_1=NULL;
443 /* Next "outer rim" */
444 while(list_destination_n!=NULL)
446 struct destination_n *destination_n_1=NULL;
447 struct tc_entry *topo_entry;
449 if((topo_entry = olsr_lookup_tc_entry(&list_destination_n->destination->rt_dst)) != NULL)
451 struct topo_dst *topo_dest = topo_entry->destinations.next;
453 /* Loop trough this nodes MPR selectors */
454 while(topo_dest != &topo_entry->destinations)
456 static struct mid_address tmp_addrs;
457 struct mid_address *tmp_addrsp;
459 /* Do not add ourselves */
460 if(if_ifwithaddr(&topo_dest->T_dest_addr))
462 topo_dest=topo_dest->next;
467 COPY_IP(&tmp_addrs.alias, &topo_dest->T_dest_addr);
468 tmp_addrs.next_alias = mid_lookup_aliases(&topo_dest->T_dest_addr);
469 tmp_addrsp = &tmp_addrs;
471 while(tmp_addrsp!=NULL)
473 if(NULL==olsr_lookup_routing_table(&tmp_addrsp->alias))
475 /* PRINT OUT: Last Hop to Final Destination */
476 /* The function ip_to_string has to be seperately */
477 OLSR_PRINTF(3, "%s -> ", olsr_ip_to_string(&list_destination_n->destination->rt_dst));
478 OLSR_PRINTF(3, "%s\n", olsr_ip_to_string(&tmp_addrsp->alias));
480 destination_n_1 = olsr_malloc(sizeof(struct destination_n),
481 "Calculate routing table 2");
483 /* Add this entry to the "outer rim" */
484 destination_n_1->destination =
485 olsr_insert_routing_table(&tmp_addrsp->alias,
486 &list_destination_n->destination->rt_router,
487 list_destination_n->destination->rt_if,
488 list_destination_n->destination->rt_metric+1,
490 if(destination_n_1->destination != NULL)
492 destination_n_1->next=list_destination_n_1;
493 list_destination_n_1=destination_n_1;
496 tmp_addrsp = tmp_addrsp->next_alias;
499 /* Next MPR selector */
500 topo_dest=topo_dest->next;
502 } /* End loop trought MPR selectors */
504 } /* End check if already added */
506 /* Delete this entry - do next */
507 destination_n_1 = list_destination_n;
508 list_destination_n = list_destination_n->next;
509 free(destination_n_1);
516 if(olsr_cnf->debug_level > 5)
518 printf("************** TABLES ****************\n");
519 printf("Routing table:\n");
520 olsr_print_routing_table(routingtable);
521 printf("Old table:\n");
522 olsr_print_routing_table(old_routes);
523 printf("**************************************\n");
528 olsr_update_kernel_routes();
530 olsr_free_routing_table(old_routes);
537 *Check for an entry with a higher quality (lower etx) than
538 *a given value in a routing table
540 *@param routes the routingtable to look in
541 *@param net the network entry to look for
542 *@param etx the metric to check for
544 *@return the located entry if found. NULL if not
546 static struct rt_entry *
547 olsr_check_for_higher_quality(struct rt_entry *routes, struct hna_net *net, float etx)
551 for(idx=0;idx<HASHSIZE;idx++)
553 struct rt_entry *tmp_routes;
555 for(tmp_routes = routes[idx].next;
556 tmp_routes != &routes[idx];
557 tmp_routes = tmp_routes->next)
559 if(COMP_IP(&tmp_routes->rt_dst, &net->A_network_addr) &&
560 (memcmp(&tmp_routes->rt_mask, &net->A_netmask, netmask_size) == 0))
563 if(tmp_routes->rt_etx < etx)
577 *Check for an entry with a lower or equal quality (higher or equal etx) than
578 *a given value in a routing table
580 *@param routes the routingtable to look in
581 *@param net the network entry to look for
582 *@param etx the metric to check for
584 *@return the located entry if found. NULL if not
587 olsr_check_for_lower_quality(struct rt_entry *routes, struct hna_net *net, float etx)
591 for(idx=0;idx<HASHSIZE;idx++)
593 struct rt_entry *tmp_routes;
595 for(tmp_routes = routes[idx].next;
596 tmp_routes != &routes[idx];
597 tmp_routes = tmp_routes->next)
599 if(COMP_IP(&tmp_routes->rt_dst, &net->A_network_addr) &&
600 (memcmp(&tmp_routes->rt_mask, &net->A_netmask, netmask_size) == 0))
603 if(tmp_routes->rt_etx >= etx)
620 *Calculate the HNA routes
624 olsr_calculate_hna_routes(void)
629 OLSR_PRINTF(3, "Calculating HNA routes\n");
632 olsr_move_route_table(hna_routes, old_hna);
634 for(idx=0;idx<HASHSIZE;idx++)
636 struct hna_entry *tmp_hna;
638 for(tmp_hna = hna_set[idx].next;
639 tmp_hna != &hna_set[idx];
640 tmp_hna = tmp_hna->next)
642 struct hna_net *tmp_net;
644 for(tmp_net = tmp_hna->networks.next;
645 tmp_net != &tmp_hna->networks;
646 tmp_net = tmp_net->next)
648 struct rt_entry *tmp_rt, *new_rt;
649 //printf("HNA: checking %s -> ", olsr_ip_to_string(&tmp_hna->A_gateway_addr));
650 //printf("%s", olsr_ip_to_string(&tmp_net->A_network_addr));
652 /* If no route to gateway - skip */
653 if((tmp_rt = olsr_lookup_routing_table(&tmp_hna->A_gateway_addr)) == NULL)
656 /* If there exists a better or equal entry - skip */
657 if(olsr_check_for_higher_quality(hna_routes, tmp_net, tmp_rt->rt_etx) != NULL)
660 /* If we find an entry with lower quality we just edit it */
661 if((new_rt = olsr_check_for_lower_quality(hna_routes, tmp_net, tmp_rt->rt_etx)) != NULL)
665 COPY_IP(&new_rt->rt_dst, &tmp_net->A_network_addr);
666 new_rt->rt_mask = tmp_net->A_netmask;
668 COPY_IP(&new_rt->rt_router, &tmp_rt->rt_router);
670 new_rt->rt_etx = tmp_rt->rt_etx;
671 new_rt->rt_metric = tmp_rt->rt_metric;
673 new_rt->rt_flags = RTF_UP | RTF_GATEWAY;
675 new_rt->rt_if = tmp_rt->rt_if;
677 /* If not - create a new one */
682 new_rt = olsr_malloc(sizeof(struct rt_entry), "New rt entry");
686 COPY_IP(&new_rt->rt_dst, &tmp_net->A_network_addr);
687 new_rt->rt_mask = tmp_net->A_netmask;
689 COPY_IP(&new_rt->rt_router, &tmp_rt->rt_router);
691 new_rt->rt_etx = tmp_rt->rt_etx;
692 new_rt->rt_metric = tmp_rt->rt_metric;
694 new_rt->rt_flags = RTF_UP | RTF_GATEWAY;
697 new_rt->rt_if = tmp_rt->rt_if;
699 /* Queue HASH will almost always be 0 */
700 hna_hash = olsr_hashing(&tmp_net->A_network_addr);
701 hna_routes[hna_hash].next->prev = new_rt;
702 new_rt->next = hna_routes[hna_hash].next;
703 hna_routes[hna_hash].next = new_rt;
704 new_rt->prev = &hna_routes[hna_hash];
711 olsr_update_kernel_hna_routes();
713 if(olsr_cnf->debug_level > 2)
715 OLSR_PRINTF(3, "HNA table:\n");
716 olsr_print_routing_table(hna_routes);
719 olsr_free_routing_table(old_hna);
727 *Print the routingtable to STDOUT
732 olsr_print_routing_table(struct rt_entry *table)
736 printf("ROUTING TABLE\n");
737 printf("DESTINATION\tNEXT HOP\tHOPCNT\tINTERFACE\n");
738 for(idx = 0; idx < HASHSIZE; idx++)
740 struct rt_entry *destination;
741 for(destination = table[idx].next;
742 destination != &table[idx];
743 destination = destination->next)
745 printf("%s\t", olsr_ip_to_string(&destination->rt_dst));
746 printf("%s\t%d\t%s\n",
747 olsr_ip_to_string(&destination->rt_router),
748 destination->rt_metric,
749 destination->rt_if->int_name);