* pave the way to add -Wshadow
[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.41 2007/08/02 22:07:19 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\n",
232               olsr_ip_to_string(&message->originator));
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       /* Delete possible empty TC entry */
277       if(changes_topology)
278         olsr_tc_delete_entry_if_empty(tc_last);
279     }
280
281   else
282     {
283       /*if message is empty then skip it */
284       if(message->multipoint_relay_selector_address != NULL)
285         {
286           /* New entry */
287           tc_last = olsr_add_tc_entry(&message->originator);      
288           
289           /* Update destinations */
290           olsr_tc_update_mprs(tc_last, message);
291           
292           changes_topology = OLSR_TRUE;
293         }
294       else
295         {
296           OLSR_PRINTF(3, "Dropping empty TC from %s\n",
297                       olsr_ip_to_string(&message->originator));
298         }
299     }
300
301   /* Process changes */
302   //olsr_process_changes();
303
304  forward:
305
306   olsr_forward_message(m, 
307                        &message->originator, 
308                        message->packet_seq_number, 
309                        in_if,
310                        from_addr);
311
312   olsr_free_tc_packet(message);
313
314   return;
315 }
316
317 /**
318  *Process a received TopologyControl message
319  *
320  *
321  *@param m the incoming OLSR message
322  *@return 0 on success
323  */
324 void
325 olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
326
327   struct tc_message               message;
328
329   tc_chgestruct(&message, m, from_addr);
330
331   if(!olsr_validate_address(&message.source_addr))
332     {
333       olsr_free_tc_packet(&message);
334       return;
335     }
336
337   olsr_tc_tap(&message, in_if, from_addr, m);
338 }
339
340
341
342
343
344
345 /**
346  *Process a received(and parsed) MID message
347  *For every address check if there is a topology node
348  *registered with it and update its addresses.
349  *
350  *@param m the OLSR message received.
351  *@return 1 on success
352  */
353
354 void
355 olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
356 {
357   struct mid_alias *tmp_adr;
358   struct mid_message message;
359
360   mid_chgestruct(&message, m);
361
362   if(!olsr_validate_address(&message.mid_origaddr))
363     {
364       olsr_free_mid_packet(&message);
365       return;
366     }
367
368   if(!olsr_check_dup_table_proc(&message.mid_origaddr, 
369                                 message.mid_seqno))
370     {
371       goto forward;
372     }
373
374 #ifdef DEBUG
375   OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr));
376 #endif
377   tmp_adr = message.mid_addr;
378
379   /*
380    *      If the sender interface (NB: not originator) of this message
381    *      is not in the symmetric 1-hop neighborhood of this node, the
382    *      message MUST be discarded.
383    */
384
385   if(check_neighbor_link(from_addr) != SYM_LINK)
386     {
387       OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
388       olsr_free_mid_packet(&message);
389       return;
390     }
391
392   /* Update the timeout of the MID */
393   olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
394
395   while(tmp_adr)
396     {
397       if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
398         {
399           OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr));
400           OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr));
401           insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
402         }
403
404
405       tmp_adr = tmp_adr->next;
406     } 
407   
408   olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
409
410  forward:  
411   olsr_forward_message(m, 
412                        &message.mid_origaddr, 
413                        message.mid_seqno, 
414                        in_if,
415                        from_addr);
416   olsr_free_mid_packet(&message);
417
418   return;
419 }
420
421
422
423
424
425 /**
426  *Process incoming HNA message.
427  *Forwards the message if that is to be done.
428  *
429  *@param m the incoming OLSR message
430  *the OLSR message.
431  *@return 1 on success
432  */
433
434 void
435 olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
436 {
437   struct hna_net_addr  *hna_tmp;
438   struct  hna_message message;
439
440 #ifdef DEBUG
441   OLSR_PRINTF(5, "Processing HNA\n");
442 #endif
443
444   hna_chgestruct(&message, m);
445
446   if(!olsr_validate_address(&message.originator))
447     {
448       olsr_free_hna_packet(&message);
449       return;
450     }
451
452   if(!olsr_check_dup_table_proc(&message.originator, 
453                                 message.packet_seq_number))
454     {
455       goto forward;
456     }
457
458   hna_tmp = message.hna_net;
459
460   /*
461    *      If the sender interface (NB: not originator) of this message
462    *      is not in the symmetric 1-hop neighborhood of this node, the
463    *      message MUST be discarded.
464    */
465   if(check_neighbor_link(from_addr) != SYM_LINK)
466     {
467       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
468       olsr_free_hna_packet(&message);
469       return;
470     }
471
472   while(hna_tmp)
473     {
474       /* Don't add an HNA entry that we are advertising ourselves. */
475       if (!find_local_hna4_entry(&hna_tmp->net, hna_tmp->netmask.v4) &&
476           !find_local_hna6_entry(&hna_tmp->net, hna_tmp->netmask.v6))
477         {
478           olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime);
479         } 
480
481       hna_tmp = hna_tmp->next;
482     }
483
484  forward:
485   olsr_forward_message(m, 
486                        &message.originator, 
487                        message.packet_seq_number, 
488                        in_if,
489                        from_addr);
490   olsr_free_hna_packet(&message);
491
492   return;
493 }
494
495
496
497
498
499
500
501 /**
502  *Processes an list of neighbors from an incoming HELLO message.
503  *@param neighbor the neighbor who sent the message.
504  *@param message the HELLO message
505  *@return nada
506  */
507 void
508 olsr_process_message_neighbors(struct neighbor_entry *neighbor,
509                                struct hello_message *message)
510 {
511   struct hello_neighbor        *message_neighbors;
512
513   for(message_neighbors = message->neighbors;
514       message_neighbors != NULL;
515       message_neighbors = message_neighbors->next)
516     {
517       union olsr_ip_addr      *neigh_addr;
518       struct neighbor_2_entry *two_hop_neighbor;
519
520       /*
521        *check all interfaces
522        *so that we don't add ourselves to the
523        *2 hop list
524        *IMPORTANT!
525        */
526       if(if_ifwithaddr(&message_neighbors->address) != NULL)
527         continue;
528
529       /* Get the main address */
530       neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
531
532       if (neigh_addr != NULL)
533         COPY_IP(&message_neighbors->address, neigh_addr);
534       
535       if(((message_neighbors->status == SYM_NEIGH) ||
536           (message_neighbors->status == MPR_NEIGH)))
537         {
538           struct neighbor_2_list_entry *two_hop_neighbor_yet =
539             olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
540 #ifdef DEBUG
541           OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address));
542 #endif
543           if (two_hop_neighbor_yet != NULL)
544             {
545               /* Updating the holding time for this neighbor */
546               two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
547               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
548
549               // For link quality OLSR, reset the path link quality here.
550               // The path link quality will be calculated in the second pass, below.
551               // Keep the saved_path_link_quality for reference.
552
553               if (olsr_cnf->lq_level > 0)
554                 {
555                   // loop through the one-hop neighbors that see this
556                   // 'two_hop_neighbor'
557
558                   struct neighbor_list_entry *walker;
559
560                   for (walker = two_hop_neighbor->neighbor_2_nblist.next;
561                        walker != &two_hop_neighbor->neighbor_2_nblist;
562                        walker = walker->next)
563                     {
564                       // have we found the one-hop neighbor that sent the
565                       // HELLO message that we're current processing?
566
567                       if (walker->neighbor == neighbor)
568                         {
569                           walker->path_link_quality = 0.0;
570                         }
571                     }
572                 }
573             }
574           else
575             {
576               two_hop_neighbor =
577                 olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
578               if (two_hop_neighbor == NULL)
579                 {
580 #ifdef DEBUG
581                   OLSR_PRINTF(5, 
582                               "Adding 2 hop neighbor %s\n\n", 
583                               olsr_ip_to_string(&message_neighbors->address));
584 #endif
585                   changes_neighborhood = OLSR_TRUE;
586                   changes_topology = OLSR_TRUE;
587
588                   two_hop_neighbor =
589                     olsr_malloc(sizeof(struct neighbor_2_entry),
590                                 "Process HELLO");
591                   
592                   two_hop_neighbor->neighbor_2_nblist.next =
593                     &two_hop_neighbor->neighbor_2_nblist;
594
595                   two_hop_neighbor->neighbor_2_nblist.prev =
596                     &two_hop_neighbor->neighbor_2_nblist;
597
598                   two_hop_neighbor->neighbor_2_pointer = 0;
599                   
600                   COPY_IP(&two_hop_neighbor->neighbor_2_addr,
601                           &message_neighbors->address);
602
603                   olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
604
605                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
606                                               (float)message->vtime);
607                 }
608               else
609                 {
610                   /*
611                     linking to this two_hop_neighbor entry
612                   */    
613                   changes_neighborhood = OLSR_TRUE;
614                   changes_topology = OLSR_TRUE;
615                   
616                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor,
617                                               (float)message->vtime); 
618                 }
619             }
620         }
621     }
622
623   // Separate, second and third pass for link quality OLSR
624
625   if (olsr_cnf->lq_level > 0)
626     {
627       struct link_entry *lnk =
628         get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
629
630       if(!lnk)
631         return;
632
633       // Second pass for link quality OLSR: calculate the best 2-hop
634       // path costs to all the 2-hop neighbors indicated in the
635       // HELLO message. Since the same 2-hop neighbor may be listed
636       // more than once in the same HELLO message (each at a possibly
637       // different quality) we want to select only the best one, not just
638       // the last one listed in the HELLO message.
639
640       for(message_neighbors = message->neighbors;
641           message_neighbors != NULL;
642           message_neighbors = message_neighbors->next)
643         {
644           if(if_ifwithaddr(&message_neighbors->address) != NULL)
645             continue;
646
647           if(((message_neighbors->status == SYM_NEIGH) ||
648               (message_neighbors->status == MPR_NEIGH)))
649             {
650               struct neighbor_list_entry *walker;
651               struct neighbor_2_entry *two_hop_neighbor;
652               struct neighbor_2_list_entry *two_hop_neighbor_yet =
653                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
654
655               if(!two_hop_neighbor_yet)
656                 continue;
657
658               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
659
660               // loop through the one-hop neighbors that see this
661               // 'two_hop_neighbor'
662
663               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
664                    walker != &two_hop_neighbor->neighbor_2_nblist;
665                    walker = walker->next)
666                 {
667                   // have we found the one-hop neighbor that sent the
668                   // HELLO message that we're current processing?
669
670                   if (walker->neighbor == neighbor)
671                     {
672                       double new_second_hop_link_quality, new_path_link_quality;
673
674                       // path link quality = link quality between us
675                       // and our one-hop neighbor x link quality between
676                       // our one-hop neighbor and the two-hop neighbor
677
678                       // let's compare this to ETX:
679
680                       // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
681                       // LQ1 * LQ2 > LQ3 * LQ4
682
683                       // so comparing path link quality values with ">" is
684                       // equivalent to comparing ETX values with "<"
685
686                       // the link quality between the 1-hop neighbour and the
687                       // 2-hop neighbour
688
689                       new_second_hop_link_quality = 
690                         message_neighbors->link_quality *
691                         message_neighbors->neigh_link_quality;
692
693                       // the total quality for the route
694                       // "us --- 1-hop --- 2-hop"
695
696                       new_path_link_quality =
697                         new_second_hop_link_quality *
698                         lnk->loss_link_quality * lnk->neigh_link_quality;
699
700                       // Only copy the link quality if it is better than what we have
701                       // for this 2-hop neighbor
702                       if (new_path_link_quality > walker->path_link_quality)
703                         {
704                           walker->second_hop_link_quality = new_second_hop_link_quality;
705                           walker->path_link_quality = new_path_link_quality;
706                         }
707                     }
708                 }
709             }
710         }
711
712       // Third pass for link quality OLSR: check if the 2-hop path qualities have
713       // actually changed. If so, signal this through the 'changes_neighborhood'
714       // and 'changes_topology' booleans. Keep a 'saved_path_link_quality' for
715       // later reference.
716       for(message_neighbors = message->neighbors;
717           message_neighbors != NULL;
718           message_neighbors = message_neighbors->next)
719         {
720           if(if_ifwithaddr(&message_neighbors->address) != NULL)
721             continue;
722
723           if(((message_neighbors->status == SYM_NEIGH) ||
724               (message_neighbors->status == MPR_NEIGH)))
725             {
726               struct neighbor_list_entry *walker;
727               struct neighbor_2_entry *two_hop_neighbor;
728               struct neighbor_2_list_entry *two_hop_neighbor_yet =
729                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
730
731               if(!two_hop_neighbor_yet)
732                 continue;
733
734               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
735
736               // loop through the one-hop neighbors that see this
737               // 'two_hop_neighbor'
738
739               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
740                    walker != &two_hop_neighbor->neighbor_2_nblist;
741                    walker = walker->next)
742                 {
743                   // have we found the one-hop neighbor that sent the
744                   // HELLO message that we're current processing?
745
746                   if (walker->neighbor == neighbor)
747                     {
748                       double saved_lq, rel_lq;
749
750                       // saved previous total link quality
751
752                       saved_lq = walker->saved_path_link_quality;
753
754                       if (saved_lq == 0.0)
755                         saved_lq = -1.0;
756
757                       // if the link cost has changed by more than 10
758                       // percent, signal
759
760                       rel_lq = walker->path_link_quality / saved_lq;
761
762                       if (rel_lq > 1.1 || rel_lq < 0.9)
763                         {
764                           walker->saved_path_link_quality =
765                             walker->path_link_quality;
766
767                           if (olsr_cnf->lq_dlimit > 0)
768                           {
769                             changes_neighborhood = OLSR_TRUE;
770                             changes_topology = OLSR_TRUE;
771                           }
772
773                           else
774                             OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
775                         }
776                     }
777                 }
778             }
779         }
780     }
781 }
782
783
784
785
786
787
788
789
790 /**
791  *Links a one-hop neighbor with a 2-hop neighbor.
792  *
793  *@param neighbor the 1-hop neighbor
794  *@param two_hop_neighbor the 2-hop neighbor
795  *@return nada
796  */
797 void
798 olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
799 {
800   struct neighbor_list_entry    *list_of_1_neighbors;
801   struct neighbor_2_list_entry  *list_of_2_neighbors;
802
803   list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
804
805   list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
806
807   list_of_1_neighbors->neighbor = neighbor;
808
809   list_of_1_neighbors->path_link_quality = 0.0;
810   list_of_1_neighbors->saved_path_link_quality = 0.0;
811   list_of_1_neighbors->second_hop_link_quality = 0.0;
812
813   /* Queue */
814   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
815   list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
816   two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
817   list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
818
819
820   list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
821   
822   list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
823
824   /* Queue */
825   neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
826   list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
827   neighbor->neighbor_2_list.next = list_of_2_neighbors;
828   list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
829   
830   /*increment the pointer counter*/
831   two_hop_neighbor->neighbor_2_pointer++;
832 }
833
834
835
836
837
838
839 /**
840  *Check if a hello message states this node as a MPR.
841  *
842  *@param message the message to check
843  *@param n_link the buffer to put the link status in
844  *@param n_status the buffer to put the status in
845  *
846  *@return 1 if we are selected as MPR 0 if not
847  */
848 int
849 olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
850 {
851   
852   struct hello_neighbor  *neighbors;
853
854   neighbors=message->neighbors;
855   
856   while(neighbors!=NULL)
857     {  
858       //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
859       //printf("against %s\n",olsr_ip_to_string(&main_addr));
860
861
862     if(olsr_cnf->ip_version == AF_INET)
863       { 
864         /* IPv4 */  
865         if(COMP_IP(&neighbors->address, &in_if->ip_addr))
866           {
867             //printf("ok");
868             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
869               return 1;
870             
871             return 0;
872           }
873       }
874     else
875       { 
876         /* IPv6 */  
877         if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
878           {
879             //printf("ok");
880             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
881               return 1;
882             
883             return 0;
884           }
885       }
886  
887       neighbors = neighbors->next; 
888     }
889
890   /* Not found */
891   return 0;
892 }