4bbe3fc9c64b2b2294332740648074776a310cf1
[olsrd.git] / src / lq_route.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
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 
15  *   distribution.
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.
19  *
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.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
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.
38  *
39  * $Id: lq_route.c,v 1.42 2006/12/14 11:29:20 bernd67 Exp $
40  */
41
42 #include "defs.h"
43 #include "olsr.h"
44 #include "tc_set.h"
45 #include "neighbor_table.h"
46 #include "two_hop_neighbor_table.h"
47 #include "link_set.h"
48 #include "routing_table.h"
49 #include "mid_set.h"
50 #include "hna_set.h"
51 #include "lq_list.h"
52 #include "lq_avl.h"
53 #include "lq_route.h"
54
55 struct dijk_edge
56 {
57   struct avl_node tree_node;
58   struct list_node node;
59   struct dijk_vertex *dest;
60   float etx;
61 };
62
63 struct dijk_vertex
64 {
65   struct avl_node tree_node;
66   struct list_node node;
67   union olsr_ip_addr addr;
68   struct avl_tree edge_tree;
69   struct list edge_list;
70   float path_etx;
71   struct dijk_vertex *prev;
72   olsr_bool done;
73 };
74
75 static int avl_comp_ipv6(void *ip1, void *ip2)
76 {
77   return memcmp(ip1, ip2, olsr_cnf->ipsize);
78 }
79
80 static int avl_comp_ipv4(void *ip1, void *ip2)
81 {
82   if (*(unsigned int *)ip1 < *(unsigned int *)ip2)
83     return -1;
84
85   if (*(unsigned int *)ip1 == *(unsigned int *)ip2)
86     return 0;
87
88   return 1;
89 }
90
91 static int (*avl_comp)(void *, void *);
92
93 static void add_vertex(struct avl_tree *vertex_tree, union olsr_ip_addr *addr,
94                        float path_etx)
95 {
96   struct avl_node *node;
97   struct dijk_vertex *vert;
98
99   // see whether this destination is already in our list
100
101   node = avl_find(vertex_tree, addr);
102
103   // if it's not in our list, add it
104
105   if (node == NULL)
106   {
107     vert = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra vertex");
108
109     vert->tree_node.data = vert;
110     vert->tree_node.key = &vert->addr;
111
112     COPY_IP(&vert->addr, addr);
113     
114     vert->path_etx = path_etx;
115     vert->prev = NULL;
116     vert->done = OLSR_FALSE;
117
118     avl_init(&vert->edge_tree, avl_comp);
119     list_init(&vert->edge_list);
120
121     avl_insert(vertex_tree, &vert->tree_node);
122   }
123 }
124
125 static void add_edge(struct avl_tree *vertex_tree,
126                      union olsr_ip_addr *src, union olsr_ip_addr *dst,
127                      float etx)
128 {
129   struct avl_node *node;
130   struct dijk_vertex *svert;
131   struct dijk_vertex *dvert;
132   struct dijk_edge *edge;
133
134   // source lookup
135
136   node = avl_find(vertex_tree, src);
137
138   // source vertex does not exist
139
140   if (node == NULL)
141     return;
142
143   svert = node->data;
144
145   // destination lookup
146
147   node = avl_find(vertex_tree, dst);
148
149   // destination vertex does not exist
150
151   if (node == NULL)
152     return;
153
154   dvert = node->data;
155
156   // check for existing forward edge
157
158   if (avl_find(&svert->edge_tree, dst) == NULL)
159   {
160     // add forward edge
161
162     edge = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra edge 1");
163
164     edge->tree_node.data = edge;
165     edge->tree_node.key = &dvert->addr;
166
167     edge->node.data = edge;
168
169     edge->dest = dvert;
170     edge->etx = etx;
171
172     avl_insert(&svert->edge_tree, &edge->tree_node);
173     list_add_tail(&svert->edge_list, &edge->node);
174   }
175
176   // check for existing inverse edge
177
178   if (avl_find(&dvert->edge_tree, src) == NULL)
179   {
180     // add inverse edge
181
182     edge = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra edge 2");
183
184     edge->tree_node.data = edge;
185     edge->tree_node.key = &svert->addr;
186
187     edge->node.data = edge;
188
189     edge->dest = svert;
190     edge->etx = etx;
191
192     avl_insert(&dvert->edge_tree, &edge->tree_node);
193     list_add_tail(&dvert->edge_list, &edge->node);
194   }
195 }
196
197 static void create_vertex_list_rec(struct list *vertex_list,
198                                    struct avl_node *node,
199                                    int (*comp)(void *, void *))
200 {
201   struct dijk_vertex *vert = node->data;
202
203   if (node->left != NULL)
204     create_vertex_list_rec(vertex_list, node->left, comp);
205
206   // add the vertex to the list, if it's not us
207
208   if ((*comp)(&olsr_cnf->main_addr, node->key) != 0)
209   {
210     vert->node.data = vert;
211     list_add_tail(vertex_list, &vert->node);
212   }
213
214   if (node->right != NULL)
215     create_vertex_list_rec(vertex_list, node->right, comp);
216 }
217
218 static void create_vertex_list(struct avl_tree *vertex_tree,
219                                struct list *vertex_list)
220 {
221   struct avl_node *node;
222   struct dijk_vertex *vert;
223
224   // make ourselves the first vertex in the list
225
226   node = avl_find(vertex_tree, &olsr_cnf->main_addr);
227   vert = node->data;
228
229   vert->node.data = vert;
230   list_add_tail(vertex_list, &vert->node);
231
232   // add the remaining vertices ordered by their main address
233
234   create_vertex_list_rec(vertex_list, vertex_tree->root, vertex_tree->comp);
235 }
236
237 static void free_everything(struct list *vertex_list)
238 {
239   struct list_node *vnode, *enode;
240   struct dijk_vertex *vert;
241   struct dijk_edge *edge;
242
243   vnode = list_get_head(vertex_list);
244
245   // loop through all vertices
246
247   while (vnode != NULL)
248   {
249     vert = vnode->data;
250
251     enode = list_get_head(&vert->edge_list);
252
253     // loop through all edges of the current vertex
254
255     while (enode != NULL)
256     {
257       edge = enode->data;
258
259       enode = list_get_next(enode);
260       free(edge);
261     }
262
263     vnode = list_get_next(vnode);
264     free(vert);
265   }
266 }
267
268 // XXX - bad complexity
269
270 static struct dijk_vertex *extract_best(struct list *vertex_list)
271 {
272   float best_etx = INFINITE_ETX + 1.0;
273   struct list_node *node;
274   struct dijk_vertex *vert;
275   struct dijk_vertex *res = NULL;
276
277   node = list_get_head(vertex_list);
278
279   // loop through all vertices
280   
281   while (node != NULL)
282   {
283     vert = node->data;
284
285     // see whether the current vertex is better than what we have
286
287     if (!vert->done && vert->path_etx < best_etx)
288     {
289       best_etx = vert->path_etx;
290       res = vert;
291     }
292
293     node = list_get_next(node);
294   }
295
296   // if we've found a vertex, remove it from the set
297
298   if (res != NULL)
299     res->done = OLSR_TRUE;
300
301   return res;
302 }
303
304 static void relax(struct dijk_vertex *vert)
305 {
306   struct dijk_edge *edge;
307   float new_etx;
308   struct list_node *node;
309
310   node = list_get_head(&vert->edge_list);
311
312   // loop through all edges of this vertex
313
314   while (node != NULL)
315   {
316     edge = node->data;
317
318     // total quality of the path through this vertex to the
319     // destination of this edge
320
321     new_etx = vert->path_etx + edge->etx;
322
323     // if it's better than the current path quality of this
324     // edge's destination, then we've found a better path to
325     // this destination
326
327     if (new_etx < edge->dest->path_etx)
328     {
329       edge->dest->path_etx = new_etx;
330       edge->dest->prev = vert;
331     }
332
333     node = list_get_next(node);
334   }
335 }
336
337 static char *etx_to_string(float etx)
338 {
339   static char buff[20];
340
341   if (etx == INFINITE_ETX)
342     return "INF";
343
344   snprintf(buff, 20, "%.2f", etx);
345   return buff;
346 }
347
348 void olsr_calculate_lq_routing_table(void)
349 {
350   struct avl_tree vertex_tree;
351   struct list vertex_list;
352   int i;
353   struct tc_entry *tcsrc;
354   struct topo_dst *tcdst;
355   struct dijk_vertex *vert;
356   struct link_entry *link;
357   struct neighbor_entry *neigh;
358   struct list_node *node;
359   struct dijk_vertex *myself;
360   struct dijk_vertex *walker;
361   int hops;
362   struct mid_address *mid_walker;
363   float etx;
364   struct hna_entry *hna_gw;
365   struct hna_net *hna;
366   struct rt_entry *gw_rt, *hna_rt, *head_rt;
367   struct neighbor_2_entry *neigh2;
368 #if 0
369   struct neighbor_list_entry *neigh_walker;
370 #endif
371   struct interface *inter;
372
373   if (olsr_cnf->ipsize == 4)
374     avl_comp = avl_comp_ipv4;
375
376   else
377     avl_comp = avl_comp_ipv6;
378
379   // initialize the graph
380
381   avl_init(&vertex_tree, avl_comp);
382   list_init(&vertex_list);
383
384   // add ourselves to the vertex tree
385
386   add_vertex(&vertex_tree, &olsr_cnf->main_addr, 0.0);
387
388   // add our neighbours
389
390   for (i = 0; i < HASHSIZE; i++)
391     for (neigh = neighbortable[i].next; neigh != &neighbortable[i];
392          neigh = neigh->next)
393       if (neigh->status == SYM)
394         add_vertex(&vertex_tree, &neigh->neighbor_main_addr, INFINITE_ETX);
395
396   // add our two-hop neighbours
397
398   for (i = 0; i < HASHSIZE; i++)
399     for (neigh2 = two_hop_neighbortable[i].next;
400          neigh2 != &two_hop_neighbortable[i];
401          neigh2 = neigh2->next)
402       add_vertex(&vertex_tree, &neigh2->neighbor_2_addr, INFINITE_ETX);
403
404   // add remaining vertices
405
406   for (i = 0; i < HASHSIZE; i++)
407     for (tcsrc = tc_table[i].next; tcsrc != &tc_table[i]; tcsrc = tcsrc->next)
408     {
409       // add source
410
411       add_vertex(&vertex_tree, &tcsrc->T_last_addr, INFINITE_ETX);
412
413       // add destinations of this source
414
415       for (tcdst = tcsrc->destinations.next; tcdst != &tcsrc->destinations;
416            tcdst = tcdst->next)
417         add_vertex(&vertex_tree, &tcdst->T_dest_addr, INFINITE_ETX);
418     }
419
420   // add edges to and from our neighbours
421
422   for (i = 0; i < HASHSIZE; i++)
423     for (neigh = neighbortable[i].next; neigh != &neighbortable[i];
424          neigh = neigh->next)
425       if (neigh->status == SYM)
426       {
427         link = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
428
429         if(!link)
430           continue;
431
432         if (link->loss_link_quality2 >= MIN_LINK_QUALITY &&
433             link->neigh_link_quality2 >= MIN_LINK_QUALITY)
434           {
435             etx = 1.0 / (link->loss_link_quality2 * link->neigh_link_quality2);
436
437             add_edge(&vertex_tree, &neigh->neighbor_main_addr, &olsr_cnf->main_addr, etx);
438           }
439       }
440
441 // we now rely solely on TC messages for routes to our two-hop neighbours
442
443 #if 0
444
445   // add edges between our neighbours and our two-hop neighbours
446
447   for (i = 0; i < HASHSIZE; i++)
448     for (neigh2 = two_hop_neighbortable[i].next;
449          neigh2 != &two_hop_neighbortable[i];
450          neigh2 = neigh2->next)
451       for (neigh_walker = neigh2->neighbor_2_nblist.next;
452            neigh_walker != &neigh2->neighbor_2_nblist;
453            neigh_walker = neigh_walker->next)
454       {
455         if (neigh_walker->second_hop_link_quality >=
456             MIN_LINK_QUALITY * MIN_LINK_QUALITY)
457         {
458           neigh = neigh_walker->neighbor;
459
460           etx = 1.0 / neigh_walker->second_hop_link_quality;
461
462           add_edge(&vertex_tree, &neigh2->neighbor_2_addr,
463                    &neigh->neighbor_main_addr, etx);
464         }
465       }
466
467 #endif
468
469   // add remaining edges
470
471   for (i = 0; i < HASHSIZE; i++)
472     for (tcsrc = tc_table[i].next; tcsrc != &tc_table[i]; tcsrc = tcsrc->next)
473       for (tcdst = tcsrc->destinations.next; tcdst != &tcsrc->destinations;
474            tcdst = tcdst->next)
475       {
476         if (tcdst->link_quality >= MIN_LINK_QUALITY &&
477             tcdst->inverse_link_quality >= MIN_LINK_QUALITY)
478           {
479             etx = 1.0 / (tcdst->link_quality * tcdst->inverse_link_quality);
480
481             add_edge(&vertex_tree, &tcdst->T_dest_addr, &tcsrc->T_last_addr,
482                      etx);
483           }
484       }
485
486   // create a sorted vertex list from the vertex tree
487
488   create_vertex_list(&vertex_tree, &vertex_list);
489
490   // run Dijkstra's algorithm
491
492   for (;;)
493   {
494     vert = extract_best(&vertex_list);
495
496     if (vert == NULL)
497       break;
498
499     relax(vert);
500   }
501
502   // save the old routing table
503
504   olsr_move_route_table(routingtable, old_routes);
505
506   node = list_get_head(&vertex_list);
507
508   // we're the first vertex in the list
509   
510   myself = node->data;
511
512   OLSR_PRINTF(2, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- DIJKSTRA\n\n",
513               nowtm->tm_hour,
514               nowtm->tm_min,
515               nowtm->tm_sec,
516               (int)now.tv_usec/10000)
517
518   for (node = list_get_next(node); node != NULL; node = list_get_next(node))
519   {
520     vert = node->data;
521
522     hops = 1;
523
524     // count hops to until the path ends or until we have reached a
525     // one-hop neighbour
526
527     for (walker = vert; walker != NULL && walker->prev != myself;
528          walker = walker->prev)
529     {
530       OLSR_PRINTF(2, "%s:%s <- ", olsr_ip_to_string(&walker->addr),
531                   etx_to_string(walker->path_etx))
532       hops++;
533     }
534
535     // if no path to a one-hop neighbour was found, ignore this node
536
537     if (walker != NULL)
538     {
539       OLSR_PRINTF(2, "%s:%s (one-hop)\n", olsr_ip_to_string(&walker->addr),
540                   etx_to_string(walker->path_etx))
541
542       // node reachable => add to the set of unprocessed nodes
543       // for HNA processing
544
545       vert->done = OLSR_FALSE;
546     }
547
548     else
549     {
550       OLSR_PRINTF(2, "%s FAILED\n", olsr_ip_to_string(&vert->addr))
551       continue;
552     }
553
554     // find the best link to the one-hop neighbour
555
556     link = get_best_link_to_neighbor(&walker->addr);
557
558     // we may see NULL here, if the one-hop neighbour is not in the
559     // link and neighbour sets any longer, but we have derived an edge
560     // between us and the one-hop neighbour from the TC set
561
562     if (link != NULL)
563     {
564       // find the interface for the found link
565       inter = link->if_name ? if_ifwithname(link->if_name) : 
566               if_ifwithaddr(&link->local_iface_addr);
567
568       // we may see NULL here if the interface is down, but we have
569       // links that haven't timed out, yet
570
571       if (inter != NULL)
572       {
573         // XXX - fix me: structurally prevent duplicates, don't test via
574         //       olsr_lookup_routing_table()
575
576         // route addition, case A - add a route to the main address of the
577         // destination node
578
579         if (olsr_lookup_routing_table(&vert->addr) == NULL)
580           olsr_insert_routing_table(&vert->addr, &link->neighbor_iface_addr,
581                                     inter, hops, vert->path_etx);
582
583         // route addition, case B - add routes to the remaining interfaces
584         // of the destination node
585
586         for (mid_walker = mid_lookup_aliases(&vert->addr); mid_walker != NULL;
587              mid_walker = mid_walker->next_alias)
588           if (olsr_lookup_routing_table(&mid_walker->alias) == NULL)
589             olsr_insert_routing_table(&mid_walker->alias,
590                                       &link->neighbor_iface_addr, inter, hops, 
591                                       vert->path_etx);
592
593         // XXX - we used to use olsr_lookup_routing_table() only here, but
594         //       this assumed that case A or case B had already happened for
595         //       this destination; if case A or case B happened after case C
596         //       for the same destination, we had duplicates, as cases A and
597         //       B would not test whether case C had already happened
598
599         // route addition, case C - make sure that we have a route to the
600         // router - e.g. in case the router's not the main address and it's
601         // MID entry has timed out
602
603         if (olsr_lookup_routing_table(&link->neighbor_iface_addr) == NULL)
604           olsr_insert_routing_table(&link->neighbor_iface_addr,
605                                     &link->neighbor_iface_addr, inter, 1,
606                                     vert->path_etx);
607       }
608     }
609   }
610
611   // save the old HNA routing table
612
613   olsr_move_route_table(hna_routes, old_hna);
614
615   // add HNA routes - the set of unprocessed network nodes contains
616   // all reachable network nodes
617
618   for (;;)
619   {
620     // extract the network node with the best ETX and remove it
621     // from the set of unprocessed network nodes
622
623     vert = extract_best(&vertex_list);
624
625     // no more nodes left
626
627     if (vert == NULL)
628       break;
629
630     // find the node's HNAs
631
632     hna_gw = olsr_lookup_hna_gw(&vert->addr);
633
634     // node doesn't announce any HNAs
635
636     if (hna_gw == NULL)
637       continue;
638
639     // find route to the node
640
641     gw_rt = olsr_lookup_routing_table(&hna_gw->A_gateway_addr);
642
643     // maybe we haven't found a link or an interface for the gateway above
644     // and hence haven't added a route - skip the HNA in this case
645
646     if (gw_rt == NULL)
647       continue;
648
649     // loop through the node's HNAs
650
651     for (hna = hna_gw->networks.next; hna != &hna_gw->networks;
652          hna = hna->next)
653     {
654       // we already have a route via a previous (better) node
655
656       if (olsr_lookup_hna_routing_table(&hna->A_network_addr) != NULL)
657         continue;
658
659       // create route for the HNA
660
661       hna_rt = olsr_malloc(sizeof(struct rt_entry), "LQ HNA route entry");
662
663       // set HNA IP address and netmask
664
665       COPY_IP(&hna_rt->rt_dst, &hna->A_network_addr);
666       hna_rt->rt_mask = hna->A_netmask;
667
668       // copy remaining fields from the node's route
669
670       COPY_IP(&hna_rt->rt_router, &gw_rt->rt_router);
671       hna_rt->rt_metric = gw_rt->rt_metric;
672       hna_rt->rt_etx = gw_rt->rt_etx;
673       hna_rt->rt_if = gw_rt->rt_if;
674
675       // we're not a host route
676
677       hna_rt->rt_flags = RTF_UP | RTF_GATEWAY;
678
679       // find the correct list
680
681       head_rt = &hna_routes[olsr_hashing(&hna->A_network_addr)];
682
683       // enqueue
684
685       head_rt->next->prev = hna_rt;
686       hna_rt->next = head_rt->next;
687
688       head_rt->next = hna_rt;
689       hna_rt->prev = head_rt;
690     }
691   }
692
693   // free the graph
694
695   free_everything(&vertex_list);
696
697   // move the route changes into the kernel
698
699   olsr_update_kernel_routes();
700   olsr_update_kernel_hna_routes();
701
702   // free the saved routing table
703
704   olsr_free_routing_table(old_routes);
705   olsr_free_routing_table(old_hna);
706 }