* patch by Hannes Gredler <hannes@gredler.at> to consolidate the the link-state datab...
[olsrd.git] / src / process_package.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
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: process_package.c,v 1.42 2007/09/13 15:31:59 bernd67 Exp $
40  */
41
42
43 #include "defs.h"
44 #include "process_package.h"
45 #include "lq_packet.h"
46 #include "hysteresis.h"
47 #include "two_hop_neighbor_table.h"
48 #include "tc_set.h"
49 #include "mpr_selector_set.h"
50 #include "mid_set.h"
51 #include "olsr.h"
52 #include "parser.h"
53 #include "duplicate_set.h"
54 #include "rebuild_packet.h"
55 #include "scheduler.h"
56 #include "local_hna_set.h"
57
58
59 /**
60  *Initializing the parser functions we are using
61  */
62 void
63 olsr_init_package_process(void)
64 {
65   if (olsr_cnf->lq_level == 0)
66     {
67       olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
68       olsr_parser_add_function(&olsr_process_received_tc, TC_MESSAGE, 1);
69     }
70   else
71     {
72       olsr_parser_add_function(&olsr_input_lq_hello, LQ_HELLO_MESSAGE, 1);
73       olsr_parser_add_function(&olsr_input_lq_tc, LQ_TC_MESSAGE, 1);
74     }
75
76   olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
77   olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
78 }
79
80 void
81 olsr_hello_tap(struct hello_message *message, struct interface *in_if,
82                union olsr_ip_addr *from_addr)
83 {
84   struct neighbor_entry     *neighbor;
85
86   /*
87    * Update link status
88    */
89   struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
90
91   if (olsr_cnf->lq_level > 0)
92     {
93       double saved_lq;
94       double rel_lq;
95       struct hello_neighbor *walker;
96       // just in case our neighbor has changed its HELLO interval
97       olsr_update_packet_loss_hello_int(lnk, message->htime);
98
99       // find the input interface in the list of neighbor interfaces
100
101       for (walker = message->neighbors; walker != NULL; walker = walker->next)
102         if (COMP_IP(&walker->address, &in_if->ip_addr))
103           break;
104
105       // the current reference link quality
106
107       saved_lq = lnk->saved_neigh_link_quality;
108
109       if (saved_lq == 0.0)
110         saved_lq = -1.0;
111
112       // memorize our neighbour's idea of the link quality, so that we
113       // know the link quality in both directions
114
115       if (walker != NULL)
116         lnk->neigh_link_quality = walker->link_quality;
117
118       else
119         lnk->neigh_link_quality = 0.0;
120
121       // if the link quality has changed by more than 10 percent,
122       // print the new link quality table
123
124       rel_lq = lnk->neigh_link_quality / saved_lq;
125
126       if (rel_lq > 1.1 || rel_lq < 0.9)
127         {
128           lnk->saved_neigh_link_quality = lnk->neigh_link_quality;
129
130           if (olsr_cnf->lq_dlimit > 0)
131           {
132             changes_neighborhood = OLSR_TRUE;
133             changes_topology = OLSR_TRUE;
134           }
135
136           else
137             OLSR_PRINTF(3, "Skipping Dijkstra (2)\n");
138
139           // create a new ANSN
140
141           // XXX - we should check whether we actually
142           // announce this neighbour
143
144           signal_link_changes(OLSR_TRUE);
145         }
146     }
147   
148   neighbor = lnk->neighbor;
149
150   /*
151    * Hysteresis
152    */
153   if(olsr_cnf->use_hysteresis)
154     {
155       /* Update HELLO timeout */
156       //printf("MESSAGE HTIME: %f\n", message->htime);
157       olsr_update_hysteresis_hello(lnk, message->htime);
158     }
159
160   /* Check if we are chosen as MPR */
161   if(olsr_lookup_mpr_status(message, in_if))
162     /* source_addr is always the main addr of a node! */
163     olsr_update_mprs_set(&message->source_addr, message->vtime);
164
165
166
167   /* Check willingness */
168   if(neighbor->willingness != message->willingness)
169     {
170       OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
171                   olsr_ip_to_string(&neighbor->neighbor_main_addr),
172                   neighbor->willingness,
173                   message->willingness);
174       /*
175        *If willingness changed - recalculate
176        */
177       neighbor->willingness = message->willingness;
178       changes_neighborhood = OLSR_TRUE;
179       changes_topology = OLSR_TRUE;
180     }
181
182
183   /* Don't register neighbors of neighbors that announces WILL_NEVER */
184   if(neighbor->willingness != WILL_NEVER)
185     olsr_process_message_neighbors(neighbor, message);
186
187   /* Process changes immedeatly in case of MPR updates */
188   olsr_process_changes();
189
190   olsr_free_hello_packet(message);
191
192   return;
193 }
194
195 /**
196  *Processes a received HELLO message. 
197  *
198  *@param m the incoming OLSR message
199  *@return 0 on sucess
200  */
201
202 void
203 olsr_process_received_hello(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
204 {
205   struct hello_message      message;
206
207   hello_chgestruct(&message, m);
208
209   if(!olsr_validate_address(&message.source_addr))
210     {
211       olsr_free_hello_packet(&message);
212       return;
213     }
214
215   olsr_hello_tap(&message, in_if, from_addr);
216 }
217
218 void
219 olsr_tc_tap(struct tc_message *message, struct interface *in_if,
220             union olsr_ip_addr *from_addr, union olsr_message *m)
221 {
222   struct tc_mpr_addr              *mpr;
223   struct tc_entry                 *tc_last;
224
225   if(!olsr_check_dup_table_proc(&message->originator, 
226                                 message->packet_seq_number))
227     {
228       goto forward;
229     }
230
231   OLSR_PRINTF(3, "Processing TC from %s, seq 0x%04x\n",
232               olsr_ip_to_string(&message->originator), message->ansn);
233
234   /*
235    *      If the sender interface (NB: not originator) of this message
236    *      is not in the symmetric 1-hop neighborhood of this node, the
237    *      message MUST be discarded.
238    */
239
240   if(check_neighbor_link(from_addr) != SYM_LINK)
241     {
242       OLSR_PRINTF(2, "Received TC from NON SYM neighbor %s\n",
243                   olsr_ip_to_string(from_addr));
244       olsr_free_tc_packet(message);
245       return;
246     }
247
248   if(olsr_cnf->debug_level > 2)
249     {
250       mpr = message->multipoint_relay_selector_address;
251       OLSR_PRINTF(3, "mpr_selector_list:[");
252
253       while(mpr!=NULL)
254         {
255           OLSR_PRINTF(3, "%s:", olsr_ip_to_string(&mpr->address));
256           mpr=mpr->next;
257         }
258
259       OLSR_PRINTF(3, "]\n");
260     }
261
262   tc_last = olsr_lookup_tc_entry(&message->originator);
263    
264   if(tc_last != NULL)
265     {
266       /* Update entry */
267
268       /* Delete destinations with lower ANSN */
269       if(olsr_tc_delete_mprs(tc_last, message))
270         changes_topology = OLSR_TRUE; 
271
272       /* Update destinations */
273       if(olsr_tc_update_mprs(tc_last, message))
274         changes_topology = OLSR_TRUE;
275     }
276
277   else
278     {
279       /*if message is empty then skip it */
280       if(message->multipoint_relay_selector_address != NULL)
281         {
282           /* New entry */
283           tc_last = olsr_add_tc_entry(&message->originator);      
284           
285           /* Update destinations */
286           olsr_tc_update_mprs(tc_last, message);
287           
288           changes_topology = OLSR_TRUE;
289         }
290       else
291         {
292           OLSR_PRINTF(3, "Dropping empty TC from %s\n",
293                       olsr_ip_to_string(&message->originator));
294         }
295     }
296
297   /* Process changes */
298   //olsr_process_changes();
299
300  forward:
301
302   olsr_forward_message(m, 
303                        &message->originator, 
304                        message->packet_seq_number, 
305                        in_if,
306                        from_addr);
307
308   olsr_free_tc_packet(message);
309
310   return;
311 }
312
313 /**
314  *Process a received TopologyControl message
315  *
316  *
317  *@param m the incoming OLSR message
318  *@return 0 on success
319  */
320 void
321 olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
322
323   struct tc_message               message;
324
325   tc_chgestruct(&message, m, from_addr);
326
327   if(!olsr_validate_address(&message.source_addr))
328     {
329       olsr_free_tc_packet(&message);
330       return;
331     }
332
333   olsr_tc_tap(&message, in_if, from_addr, m);
334 }
335
336
337
338
339
340
341 /**
342  *Process a received(and parsed) MID message
343  *For every address check if there is a topology node
344  *registered with it and update its addresses.
345  *
346  *@param m the OLSR message received.
347  *@return 1 on success
348  */
349
350 void
351 olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
352 {
353   struct mid_alias *tmp_adr;
354   struct mid_message message;
355
356   mid_chgestruct(&message, m);
357
358   if(!olsr_validate_address(&message.mid_origaddr))
359     {
360       olsr_free_mid_packet(&message);
361       return;
362     }
363
364   if(!olsr_check_dup_table_proc(&message.mid_origaddr, 
365                                 message.mid_seqno))
366     {
367       goto forward;
368     }
369
370 #ifdef DEBUG
371   OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr));
372 #endif
373   tmp_adr = message.mid_addr;
374
375   /*
376    *      If the sender interface (NB: not originator) of this message
377    *      is not in the symmetric 1-hop neighborhood of this node, the
378    *      message MUST be discarded.
379    */
380
381   if(check_neighbor_link(from_addr) != SYM_LINK)
382     {
383       OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
384       olsr_free_mid_packet(&message);
385       return;
386     }
387
388   /* Update the timeout of the MID */
389   olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
390
391   while(tmp_adr)
392     {
393       if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
394         {
395           OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr));
396           OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr));
397           insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
398         }
399
400
401       tmp_adr = tmp_adr->next;
402     } 
403   
404   olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
405
406  forward:  
407   olsr_forward_message(m, 
408                        &message.mid_origaddr, 
409                        message.mid_seqno, 
410                        in_if,
411                        from_addr);
412   olsr_free_mid_packet(&message);
413
414   return;
415 }
416
417
418
419
420
421 /**
422  *Process incoming HNA message.
423  *Forwards the message if that is to be done.
424  *
425  *@param m the incoming OLSR message
426  *the OLSR message.
427  *@return 1 on success
428  */
429
430 void
431 olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
432 {
433   struct hna_net_addr  *hna_tmp;
434   struct  hna_message message;
435
436 #ifdef DEBUG
437   OLSR_PRINTF(5, "Processing HNA\n");
438 #endif
439
440   hna_chgestruct(&message, m);
441
442   if(!olsr_validate_address(&message.originator))
443     {
444       olsr_free_hna_packet(&message);
445       return;
446     }
447
448   if(!olsr_check_dup_table_proc(&message.originator, 
449                                 message.packet_seq_number))
450     {
451       goto forward;
452     }
453
454   hna_tmp = message.hna_net;
455
456   /*
457    *      If the sender interface (NB: not originator) of this message
458    *      is not in the symmetric 1-hop neighborhood of this node, the
459    *      message MUST be discarded.
460    */
461   if(check_neighbor_link(from_addr) != SYM_LINK)
462     {
463       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
464       olsr_free_hna_packet(&message);
465       return;
466     }
467
468   while(hna_tmp)
469     {
470       /* Don't add an HNA entry that we are advertising ourselves. */
471       if (!find_local_hna4_entry(&hna_tmp->net, hna_tmp->netmask.v4) &&
472           !find_local_hna6_entry(&hna_tmp->net, hna_tmp->netmask.v6))
473         {
474           olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime);
475         } 
476
477       hna_tmp = hna_tmp->next;
478     }
479
480  forward:
481   olsr_forward_message(m, 
482                        &message.originator, 
483                        message.packet_seq_number, 
484                        in_if,
485                        from_addr);
486   olsr_free_hna_packet(&message);
487
488   return;
489 }
490
491
492
493
494
495
496
497 /**
498  *Processes an list of neighbors from an incoming HELLO message.
499  *@param neighbor the neighbor who sent the message.
500  *@param message the HELLO message
501  *@return nada
502  */
503 void
504 olsr_process_message_neighbors(struct neighbor_entry *neighbor,
505                                struct hello_message *message)
506 {
507   struct hello_neighbor        *message_neighbors;
508
509   for(message_neighbors = message->neighbors;
510       message_neighbors != NULL;
511       message_neighbors = message_neighbors->next)
512     {
513       union olsr_ip_addr      *neigh_addr;
514       struct neighbor_2_entry *two_hop_neighbor;
515
516       /*
517        *check all interfaces
518        *so that we don't add ourselves to the
519        *2 hop list
520        *IMPORTANT!
521        */
522       if(if_ifwithaddr(&message_neighbors->address) != NULL)
523         continue;
524
525       /* Get the main address */
526       neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
527
528       if (neigh_addr != NULL)
529         COPY_IP(&message_neighbors->address, neigh_addr);
530       
531       if(((message_neighbors->status == SYM_NEIGH) ||
532           (message_neighbors->status == MPR_NEIGH)))
533         {
534           struct neighbor_2_list_entry *two_hop_neighbor_yet =
535             olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
536 #ifdef DEBUG
537           OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address));
538 #endif
539           if (two_hop_neighbor_yet != NULL)
540             {
541               /* Updating the holding time for this neighbor */
542               two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
543               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
544
545               // For link quality OLSR, reset the path link quality here.
546               // The path link quality will be calculated in the second pass, below.
547               // Keep the saved_path_link_quality for reference.
548
549               if (olsr_cnf->lq_level > 0)
550                 {
551                   // loop through the one-hop neighbors that see this
552                   // 'two_hop_neighbor'
553
554                   struct neighbor_list_entry *walker;
555
556                   for (walker = two_hop_neighbor->neighbor_2_nblist.next;
557                        walker != &two_hop_neighbor->neighbor_2_nblist;
558                        walker = walker->next)
559                     {
560                       // have we found the one-hop neighbor that sent the
561                       // HELLO message that we're current processing?
562
563                       if (walker->neighbor == neighbor)
564                         {
565                           walker->path_link_quality = 0.0;
566                         }
567                     }
568                 }
569             }
570           else
571             {
572               two_hop_neighbor =
573                 olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
574               if (two_hop_neighbor == NULL)
575                 {
576 #ifdef DEBUG
577                   OLSR_PRINTF(5, 
578                               "Adding 2 hop neighbor %s\n\n", 
579                               olsr_ip_to_string(&message_neighbors->address));
580 #endif
581                   changes_neighborhood = OLSR_TRUE;
582                   changes_topology = OLSR_TRUE;
583
584                   two_hop_neighbor =
585                     olsr_malloc(sizeof(struct neighbor_2_entry),
586                                 "Process HELLO");
587                   
588                   two_hop_neighbor->neighbor_2_nblist.next =
589                     &two_hop_neighbor->neighbor_2_nblist;
590
591                   two_hop_neighbor->neighbor_2_nblist.prev =
592                     &two_hop_neighbor->neighbor_2_nblist;
593
594                   two_hop_neighbor->neighbor_2_pointer = 0;
595                   
596                   COPY_IP(&two_hop_neighbor->neighbor_2_addr,
597                           &message_neighbors->address);
598
599                   olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
600
601                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
602                                               (float)message->vtime);
603                 }
604               else
605                 {
606                   /*
607                     linking to this two_hop_neighbor entry
608                   */    
609                   changes_neighborhood = OLSR_TRUE;
610                   changes_topology = OLSR_TRUE;
611                   
612                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
613                                               (float)message->vtime); 
614                 }
615             }
616         }
617     }
618
619   // Separate, second and third pass for link quality OLSR
620
621   if (olsr_cnf->lq_level > 0)
622     {
623       struct link_entry *lnk =
624         get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
625
626       if(!lnk)
627         return;
628
629       // Second pass for link quality OLSR: calculate the best 2-hop
630       // path costs to all the 2-hop neighbors indicated in the
631       // HELLO message. Since the same 2-hop neighbor may be listed
632       // more than once in the same HELLO message (each at a possibly
633       // different quality) we want to select only the best one, not just
634       // the last one listed in the HELLO message.
635
636       for(message_neighbors = message->neighbors;
637           message_neighbors != NULL;
638           message_neighbors = message_neighbors->next)
639         {
640           if(if_ifwithaddr(&message_neighbors->address) != NULL)
641             continue;
642
643           if(((message_neighbors->status == SYM_NEIGH) ||
644               (message_neighbors->status == MPR_NEIGH)))
645             {
646               struct neighbor_list_entry *walker;
647               struct neighbor_2_entry *two_hop_neighbor;
648               struct neighbor_2_list_entry *two_hop_neighbor_yet =
649                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
650
651               if(!two_hop_neighbor_yet)
652                 continue;
653
654               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
655
656               // loop through the one-hop neighbors that see this
657               // 'two_hop_neighbor'
658
659               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
660                    walker != &two_hop_neighbor->neighbor_2_nblist;
661                    walker = walker->next)
662                 {
663                   // have we found the one-hop neighbor that sent the
664                   // HELLO message that we're current processing?
665
666                   if (walker->neighbor == neighbor)
667                     {
668                       double new_second_hop_link_quality, new_path_link_quality;
669
670                       // path link quality = link quality between us
671                       // and our one-hop neighbor x link quality between
672                       // our one-hop neighbor and the two-hop neighbor
673
674                       // let's compare this to ETX:
675
676                       // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
677                       // LQ1 * LQ2 > LQ3 * LQ4
678
679                       // so comparing path link quality values with ">" is
680                       // equivalent to comparing ETX values with "<"
681
682                       // the link quality between the 1-hop neighbour and the
683                       // 2-hop neighbour
684
685                       new_second_hop_link_quality = 
686                         message_neighbors->link_quality *
687                         message_neighbors->neigh_link_quality;
688
689                       // the total quality for the route
690                       // "us --- 1-hop --- 2-hop"
691
692                       new_path_link_quality =
693                         new_second_hop_link_quality *
694                         lnk->loss_link_quality * lnk->neigh_link_quality;
695
696                       // Only copy the link quality if it is better than what we have
697                       // for this 2-hop neighbor
698                       if (new_path_link_quality > walker->path_link_quality)
699                         {
700                           walker->second_hop_link_quality = new_second_hop_link_quality;
701                           walker->path_link_quality = new_path_link_quality;
702                         }
703                     }
704                 }
705             }
706         }
707
708       // Third pass for link quality OLSR: check if the 2-hop path qualities have
709       // actually changed. If so, signal this through the 'changes_neighborhood'
710       // and 'changes_topology' booleans. Keep a 'saved_path_link_quality' for
711       // later reference.
712       for(message_neighbors = message->neighbors;
713           message_neighbors != NULL;
714           message_neighbors = message_neighbors->next)
715         {
716           if(if_ifwithaddr(&message_neighbors->address) != NULL)
717             continue;
718
719           if(((message_neighbors->status == SYM_NEIGH) ||
720               (message_neighbors->status == MPR_NEIGH)))
721             {
722               struct neighbor_list_entry *walker;
723               struct neighbor_2_entry *two_hop_neighbor;
724               struct neighbor_2_list_entry *two_hop_neighbor_yet =
725                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
726
727               if(!two_hop_neighbor_yet)
728                 continue;
729
730               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
731
732               // loop through the one-hop neighbors that see this
733               // 'two_hop_neighbor'
734
735               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
736                    walker != &two_hop_neighbor->neighbor_2_nblist;
737                    walker = walker->next)
738                 {
739                   // have we found the one-hop neighbor that sent the
740                   // HELLO message that we're current processing?
741
742                   if (walker->neighbor == neighbor)
743                     {
744                       double saved_lq, rel_lq;
745
746                       // saved previous total link quality
747
748                       saved_lq = walker->saved_path_link_quality;
749
750                       if (saved_lq == 0.0)
751                         saved_lq = -1.0;
752
753                       // if the link cost has changed by more than 10
754                       // percent, signal
755
756                       rel_lq = walker->path_link_quality / saved_lq;
757
758                       if (rel_lq > 1.1 || rel_lq < 0.9)
759                         {
760                           walker->saved_path_link_quality =
761                             walker->path_link_quality;
762
763                           if (olsr_cnf->lq_dlimit > 0)
764                           {
765                             changes_neighborhood = OLSR_TRUE;
766                             changes_topology = OLSR_TRUE;
767                           }
768
769                           else
770                             OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
771                         }
772                     }
773                 }
774             }
775         }
776     }
777 }
778
779
780
781
782
783
784
785
786 /**
787  *Links a one-hop neighbor with a 2-hop neighbor.
788  *
789  *@param neighbor the 1-hop neighbor
790  *@param two_hop_neighbor the 2-hop neighbor
791  *@return nada
792  */
793 void
794 olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
795 {
796   struct neighbor_list_entry    *list_of_1_neighbors;
797   struct neighbor_2_list_entry  *list_of_2_neighbors;
798
799   list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
800
801   list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
802
803   list_of_1_neighbors->neighbor = neighbor;
804
805   list_of_1_neighbors->path_link_quality = 0.0;
806   list_of_1_neighbors->saved_path_link_quality = 0.0;
807   list_of_1_neighbors->second_hop_link_quality = 0.0;
808
809   /* Queue */
810   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
811   list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
812   two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
813   list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
814
815
816   list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
817   
818   list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
819
820   /* Queue */
821   neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
822   list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
823   neighbor->neighbor_2_list.next = list_of_2_neighbors;
824   list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
825   
826   /*increment the pointer counter*/
827   two_hop_neighbor->neighbor_2_pointer++;
828 }
829
830
831
832
833
834
835 /**
836  *Check if a hello message states this node as a MPR.
837  *
838  *@param message the message to check
839  *@param n_link the buffer to put the link status in
840  *@param n_status the buffer to put the status in
841  *
842  *@return 1 if we are selected as MPR 0 if not
843  */
844 int
845 olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
846 {
847   
848   struct hello_neighbor  *neighbors;
849
850   neighbors=message->neighbors;
851   
852   while(neighbors!=NULL)
853     {  
854       //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
855       //printf("against %s\n",olsr_ip_to_string(&main_addr));
856
857
858     if(olsr_cnf->ip_version == AF_INET)
859       { 
860         /* IPv4 */  
861         if(COMP_IP(&neighbors->address, &in_if->ip_addr))
862           {
863             //printf("ok");
864             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
865               return 1;
866             
867             return 0;
868           }
869       }
870     else
871       { 
872         /* IPv6 */  
873         if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
874           {
875             //printf("ok");
876             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
877               return 1;
878             
879             return 0;
880           }
881       }
882  
883       neighbors = neighbors->next; 
884     }
885
886   /* Not found */
887   return 0;
888 }