Fixed LQ MPR selection problem. Fixed LQ route addition crash.
[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.26 2005/02/16 14:44:44 tlopatic Exp $
40  */
41
42 #include "defs.h"
43 #include "tc_set.h"
44 #include "neighbor_table.h"
45 #include "two_hop_neighbor_table.h"
46 #include "link_set.h"
47 #include "routing_table.h"
48 #include "mid_set.h"
49 #include "hna_set.h"
50 #include "lq_list.h"
51 #include "lq_avl.h"
52 #include "lq_route.h"
53
54 struct dijk_edge
55 {
56   struct avl_node tree_node;
57   struct list_node node;
58   struct dijk_vertex *dest;
59   float etx;
60 };
61
62 struct dijk_vertex
63 {
64   struct avl_node tree_node;
65   struct list_node node;
66   union olsr_ip_addr addr;
67   struct avl_tree edge_tree;
68   struct list edge_list;
69   float path_etx;
70   struct dijk_vertex *prev;
71   olsr_bool done;
72 };
73
74 static int avl_comp_ipv6(void *ip1, void *ip2)
75 {
76   return memcmp(ip1, ip2, ipsize);
77 }
78
79 static int avl_comp_ipv4(void *ip1, void *ip2)
80 {
81   if (*(unsigned int *)ip1 < *(unsigned int *)ip2)
82     return -1;
83
84   if (*(unsigned int *)ip1 == *(unsigned int *)ip2)
85     return 0;
86
87   return 1;
88 }
89
90 static int (*avl_comp)(void *, void *);
91
92 static void add_vertex(struct avl_tree *vertex_tree, struct list *vertex_list,
93                        union olsr_ip_addr *addr, float path_etx)
94 {
95   struct avl_node *node;
96   struct dijk_vertex *vert;
97
98   // see whether this destination is already in our list
99
100   node = avl_find(vertex_tree, addr);
101
102   // if it's not in our list, add it
103
104   if (node == NULL)
105   {
106     vert = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra vertex");
107
108     vert->tree_node.data = vert;
109     vert->tree_node.key = &vert->addr;
110
111     vert->node.data = vert;
112
113     COPY_IP(&vert->addr, addr);
114     
115     vert->path_etx = path_etx;
116     vert->prev = NULL;
117     vert->done = OLSR_FALSE;
118
119     avl_init(&vert->edge_tree, avl_comp);
120     list_init(&vert->edge_list);
121
122     avl_insert(vertex_tree, &vert->tree_node);
123     list_add_tail(vertex_list, &vert->node);
124   }
125 }
126
127 static void add_edge(struct avl_tree *vertex_tree, struct list *vertex_list,
128                      union olsr_ip_addr *src, union olsr_ip_addr *dst,
129                      float etx)
130 {
131   struct avl_node *node;
132   struct dijk_vertex *svert;
133   struct dijk_vertex *dvert;
134   struct dijk_edge *edge;
135
136   // source lookup
137
138   node = avl_find(vertex_tree, src);
139
140   // source vertex does not exist
141
142   if (node == NULL)
143     return;
144
145   svert = node->data;
146
147   // destination lookup
148
149   node = avl_find(vertex_tree, dst);
150
151   // destination vertex does not exist
152
153   if (node == NULL)
154     return;
155
156   dvert = node->data;
157
158   // check for existing forward edge
159
160   if (avl_find(&svert->edge_tree, dst) == NULL)
161   {
162     // add forward edge
163
164     edge = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra edge 1");
165
166     edge->tree_node.data = edge;
167     edge->tree_node.key = &dvert->addr;
168
169     edge->node.data = edge;
170
171     edge->dest = dvert;
172     edge->etx = etx;
173
174     avl_insert(&svert->edge_tree, &edge->tree_node);
175     list_add_tail(&svert->edge_list, &edge->node);
176   }
177
178   // check for existing inverse edge
179
180   if (avl_find(&dvert->edge_tree, src) == NULL)
181   {
182     // add inverse edge
183
184     edge = olsr_malloc(sizeof (struct dijk_vertex), "Dijkstra edge 2");
185
186     edge->tree_node.data = edge;
187     edge->tree_node.key = &svert->addr;
188
189     edge->node.data = edge;
190
191     edge->dest = svert;
192     edge->etx = etx;
193
194     avl_insert(&dvert->edge_tree, &edge->tree_node);
195     list_add_tail(&dvert->edge_list, &edge->node);
196   }
197 }
198
199 static void free_everything(struct list *vertex_list)
200 {
201   struct list_node *vnode, *enode;
202   struct dijk_vertex *vert;
203   struct dijk_edge *edge;
204
205   vnode = list_get_head(vertex_list);
206
207   // loop through all vertices
208
209   while (vnode != NULL)
210   {
211     vert = vnode->data;
212
213     enode = list_get_head(&vert->edge_list);
214
215     // loop through all edges of the current vertex
216
217     while (enode != NULL)
218     {
219       edge = enode->data;
220
221       enode = list_get_next(enode);
222       free(edge);
223     }
224
225     vnode = list_get_next(vnode);
226     free(vert);
227   }
228 }
229
230 // XXX - bad complexity
231
232 static struct dijk_vertex *extract_best(struct list *vertex_list)
233 {
234   float best_etx = INFINITE_ETX + 1.0;
235   struct list_node *node;
236   struct dijk_vertex *vert;
237   struct dijk_vertex *res = NULL;
238
239   node = list_get_head(vertex_list);
240
241   // loop through all vertices
242   
243   while (node != NULL)
244   {
245     vert = node->data;
246
247     // see whether the current vertex is better than what we have
248
249     if (!vert->done && vert->path_etx < best_etx)
250     {
251       best_etx = vert->path_etx;
252       res = vert;
253     }
254
255     node = list_get_next(node);
256   }
257
258   // if we've found a vertex, remove it from the set
259
260   if (res != NULL)
261     res->done = OLSR_TRUE;
262
263   return res;
264 }
265
266 static void relax(struct dijk_vertex *vert)
267 {
268   struct dijk_edge *edge;
269   float new_etx;
270   struct list_node *node;
271
272   node = list_get_head(&vert->edge_list);
273
274   // loop through all edges of this vertex
275
276   while (node != NULL)
277   {
278     edge = node->data;
279
280     // total quality of the path through this vertex to the
281     // destination of this edge
282
283     new_etx = vert->path_etx + edge->etx;
284
285     // if it's better than the current path quality of this
286     // edge's destination, then we've found a better path to
287     // this destination
288
289     if (new_etx < edge->dest->path_etx)
290     {
291       edge->dest->path_etx = new_etx;
292       edge->dest->prev = vert;
293     }
294
295     node = list_get_next(node);
296   }
297 }
298
299 static char *etx_to_string(float etx)
300 {
301   static char buff[20];
302
303   if (etx == INFINITE_ETX)
304     return "INF";
305
306   sprintf(buff, "%.2f", etx);
307   return buff;
308 }
309
310 void olsr_calculate_lq_routing_table(void)
311 {
312   struct avl_tree vertex_tree;
313   struct list vertex_list;
314   int i;
315   struct tc_entry *tcsrc;
316   struct topo_dst *tcdst;
317   struct dijk_vertex *vert;
318   struct link_entry *link;
319   struct neighbor_entry *neigh;
320   struct list_node *node;
321   struct dijk_vertex *myself;
322   struct dijk_vertex *walker;
323   int hops;
324   struct mid_address *mid_walker;
325   float etx;
326   struct hna_entry *hna_gw;
327   struct hna_net *hna;
328   struct rt_entry *gw_rt, *hna_rt, *head_rt;
329   struct neighbor_2_entry *neigh2;
330   struct neighbor_list_entry *neigh_walker;
331
332   if (ipsize == 4)
333     avl_comp = avl_comp_ipv4;
334
335   else
336     avl_comp = avl_comp_ipv6;
337
338   // initialize the graph
339
340   avl_init(&vertex_tree, avl_comp);
341   list_init(&vertex_list);
342
343   // add ourselves to the vertex list
344
345   add_vertex(&vertex_tree, &vertex_list, &main_addr, 0.0);
346
347   // add our neighbours
348
349   for (i = 0; i < HASHSIZE; i++)
350     for (neigh = neighbortable[i].next; neigh != &neighbortable[i];
351          neigh = neigh->next)
352       if (neigh->status == SYM)
353         add_vertex(&vertex_tree, &vertex_list, &neigh->neighbor_main_addr,
354                    INFINITE_ETX);
355
356   // add our two-hop neighbours
357
358   for (i = 0; i < HASHSIZE; i++)
359     for (neigh2 = two_hop_neighbortable[i].next;
360          neigh2 != &two_hop_neighbortable[i];
361          neigh2 = neigh2->next)
362       add_vertex(&vertex_tree, &vertex_list, &neigh2->neighbor_2_addr,
363                  INFINITE_ETX);
364
365   // add remaining vertices
366
367   for (i = 0; i < HASHSIZE; i++)
368     for (tcsrc = tc_table[i].next; tcsrc != &tc_table[i]; tcsrc = tcsrc->next)
369     {
370       // add source
371
372       add_vertex(&vertex_tree, &vertex_list, &tcsrc->T_last_addr,
373                  INFINITE_ETX);
374
375       // add destinations of this source
376
377       for (tcdst = tcsrc->destinations.next; tcdst != &tcsrc->destinations;
378            tcdst = tcdst->next)
379         add_vertex(&vertex_tree, &vertex_list, &tcdst->T_dest_addr,
380                    INFINITE_ETX);
381     }
382
383   // add edges to and from our neighbours
384
385   for (i = 0; i < HASHSIZE; i++)
386     for (neigh = neighbortable[i].next; neigh != &neighbortable[i];
387          neigh = neigh->next)
388       if (neigh->status == SYM)
389       {
390         link = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
391
392         if (link->loss_link_quality >= MIN_LINK_QUALITY &&
393             link->neigh_link_quality >= MIN_LINK_QUALITY)
394           {
395             etx = 1.0 / (link->loss_link_quality * link->neigh_link_quality);
396
397             add_edge(&vertex_tree, &vertex_list, &neigh->neighbor_main_addr,
398                      &main_addr, etx);
399           }
400       }
401
402   // add edges between our neighbours and our two-hop neighbours
403
404   for (i = 0; i < HASHSIZE; i++)
405     for (neigh2 = two_hop_neighbortable[i].next;
406          neigh2 != &two_hop_neighbortable[i];
407          neigh2 = neigh2->next)
408       for (neigh_walker = neigh2->neighbor_2_nblist.next;
409            neigh_walker != &neigh2->neighbor_2_nblist;
410            neigh_walker = neigh_walker->next)
411       {
412         if (neigh_walker->second_hop_link_quality >=
413             MIN_LINK_QUALITY * MIN_LINK_QUALITY)
414         {
415           neigh = neigh_walker->neighbor;
416
417           etx = 1.0 / neigh_walker->second_hop_link_quality;
418
419           add_edge(&vertex_tree, &vertex_list, &neigh2->neighbor_2_addr,
420                    &neigh->neighbor_main_addr, etx);
421         }
422       }
423
424   // add remaining edges
425
426   for (i = 0; i < HASHSIZE; i++)
427     for (tcsrc = tc_table[i].next; tcsrc != &tc_table[i]; tcsrc = tcsrc->next)
428       for (tcdst = tcsrc->destinations.next; tcdst != &tcsrc->destinations;
429            tcdst = tcdst->next)
430       {
431         if (tcdst->link_quality >= MIN_LINK_QUALITY &&
432             tcdst->inverse_link_quality >= MIN_LINK_QUALITY)
433           {
434             etx = 1.0 / (tcdst->link_quality * tcdst->inverse_link_quality);
435
436             add_edge(&vertex_tree, &vertex_list, &tcdst->T_dest_addr,
437                      &tcsrc->T_last_addr, etx);
438           }
439       }
440
441   // run Dijkstra's algorithm
442
443   for (;;)
444   {
445     vert = extract_best(&vertex_list);
446
447     if (vert == NULL)
448       break;
449
450     relax(vert);
451   }
452
453   // save the old routing table
454
455   olsr_move_route_table(routingtable, old_routes);
456
457   node = list_get_head(&vertex_list);
458
459   // we're the first vertex in the list
460   
461   myself = node->data;
462
463   olsr_printf(2, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- DIJKSTRA\n\n",
464               nowtm->tm_hour,
465               nowtm->tm_min,
466               nowtm->tm_sec,
467               now.tv_usec/10000);
468
469   for (node = list_get_next(node); node != NULL; node = list_get_next(node))
470   {
471     vert = node->data;
472
473     hops = 1;
474
475     // count hops to until the path ends or until we have reached a
476     // one-hop neighbour
477
478     for (walker = vert; walker != NULL && walker->prev != myself;
479          walker = walker->prev)
480     {
481       olsr_printf(2, "%s:%s <- ", olsr_ip_to_string(&walker->addr),
482                   etx_to_string(walker->path_etx));
483       hops++;
484     }
485
486     // if no path to a one-hop neighbour was found, ignore this node
487
488     if (walker != NULL)
489     {
490       olsr_printf(2, "%s:%s (one-hop)\n", olsr_ip_to_string(&walker->addr),
491                   etx_to_string(walker->path_etx));
492
493       // node reachable => add to the set of unprocessed nodes
494       // for HNA processing
495
496       vert->done = OLSR_FALSE;
497     }
498
499     else
500     {
501       olsr_printf(2, "FAILED\n", olsr_ip_to_string(&vert->addr));
502       continue;
503     }
504
505 #if defined linux && 0
506     /*
507      * on Linux we can add a new route for a destination before removing
508      * the old route, so frequent route updates are not a problem, as
509      * we never have a time window in which there isn't any route; hence
510      * we can use the more volatile ETX value instead of the hop count
511      */
512
513     hops = (int)vert->path_etx;
514
515     if (hops > 100)
516       hops = 100;
517 #endif
518
519     // add a route to the main address of the destination node
520
521     link = get_best_link_to_neighbor(&walker->addr);
522
523     olsr_insert_routing_table(&vert->addr,
524                               &link->neighbor_iface_addr,
525                               if_ifwithaddr(&link->local_iface_addr),
526                               hops);
527
528     // add routes to the remaining interfaces of the destination node
529
530     for (mid_walker = mid_lookup_aliases(&vert->addr); mid_walker != NULL;
531          mid_walker = mid_walker->next_alias)
532     {
533       olsr_insert_routing_table(&mid_walker->alias,
534                                 &link->neighbor_iface_addr,
535                                 if_ifwithaddr(&link->local_iface_addr),
536                                 hops);
537     }
538   }
539
540   // add HNA routes - the set of unprocessed network nodes contains
541   // all reachable network nodes
542
543   for (;;)
544   {
545     // extract the network node with the best ETX and remove it
546     // from the set of unprocessed network nodes
547
548     vert = extract_best(&vertex_list);
549
550     // no more nodes left
551
552     if (vert == NULL)
553       break;
554
555     // find the node's HNAs
556
557     hna_gw = olsr_lookup_hna_gw(&vert->addr);
558
559     // node doesn't announce any HNAs
560
561     if (hna_gw == NULL)
562       continue;
563
564     // loop through the node's HNAs
565
566     for (hna = hna_gw->networks.next; hna != &hna_gw->networks;
567          hna = hna->next)
568     {
569       // we already have a route via a previous (better) node
570
571       if (olsr_lookup_routing_table(&hna->A_network_addr) != NULL)
572         continue;
573
574       // find route to the node
575
576       gw_rt = olsr_lookup_routing_table(&hna_gw->A_gateway_addr);
577
578       // should never happen as we only process reachable nodes
579
580       if (gw_rt == NULL)
581       {
582         fprintf(stderr, "LQ HNA processing: Gateway without a route.");
583         continue;
584       }
585
586       // create route for the HNA
587
588       hna_rt = olsr_malloc(sizeof(struct rt_entry), "LQ HNA route entry");
589
590       // set HNA IP address and netmask
591
592       COPY_IP(&hna_rt->rt_dst, &hna->A_network_addr);
593       hna_rt->rt_mask = hna->A_netmask;
594
595       // copy remaining fields from the node's route
596
597       COPY_IP(&hna_rt->rt_router, &gw_rt->rt_router);
598       hna_rt->rt_metric = gw_rt->rt_metric;
599       hna_rt->rt_if = gw_rt->rt_if;
600
601       // we're not a host route
602
603       hna_rt->rt_flags = RTF_UP | RTF_GATEWAY;
604
605       // find the correct list
606
607       head_rt = &routingtable[olsr_hashing(&hna->A_network_addr)];
608
609       // enqueue
610
611       head_rt->next->prev = hna_rt;
612       hna_rt->next = head_rt->next;
613
614       head_rt->next = hna_rt;
615       hna_rt->prev = head_rt;
616     }
617   }
618
619   // free the graph
620
621   free_everything(&vertex_list);
622
623   // move the route changes into the kernel
624
625   olsr_update_kernel_routes();
626
627   // free the saved routing table
628
629   olsr_free_routing_table(old_routes);
630 }