7bcba24c9ca2826b004806a9e13c728dd0d2b913
[olsrd.git] / src / link_set.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: link_set.c,v 1.8 2004/10/09 22:32:47 kattemat Exp $
23  *
24  */
25
26
27 /*
28  * Link sensing database for the OLSR routing daemon
29  */
30
31 #include "link_set.h"
32 #include "hysteresis.h"
33 #include "mid_set.h"
34 #include "mpr.h"
35 #include "olsr.h"
36 #include "scheduler.h"
37
38 #include "link_layer.h"
39
40
41
42 /* Begin:
43  * Prototypes for internal functions 
44  */
45
46 static int
47 check_link_status(struct hello_message *);
48
49 static void
50 olsr_time_out_hysteresis(void);
51
52 static struct link_entry *
53 add_new_entry(union olsr_ip_addr *, union olsr_ip_addr *, union olsr_ip_addr *, double, double);
54
55 static void
56 olsr_time_out_link_set(void);
57
58 static int
59 get_neighbor_status(union olsr_ip_addr *);
60
61
62 /* End:
63  * Prototypes for internal functions 
64  */
65
66
67
68 void
69 olsr_init_link_set()
70 {
71
72   /* Timers */
73   olsr_init_timer((olsr_u32_t) (neighbor_hold_time*1000), &hold_time_neighbor);
74   olsr_init_timer((olsr_u32_t) (neighbor_hold_time_nw*1000), &hold_time_neighbor_nw);
75
76   olsr_register_timeout_function(&olsr_time_out_link_set);
77   if(use_hysteresis)
78     {
79       olsr_register_timeout_function(&olsr_time_out_hysteresis);
80     }
81   link_set = NULL;
82 }
83
84
85
86 /**
87  * Get the status of a link. The status is based upon different
88  * timeouts in the link entry.
89  *
90  *@param remote address of the remote interface
91  *
92  *@return the link status of the link
93  */
94 int
95 lookup_link_status(struct link_entry *entry)
96 {
97
98   if(entry == NULL || link_set == NULL)
99     {
100       return UNSPEC_LINK;
101     }
102
103   /*
104    * Hysteresis
105    */
106   if(use_hysteresis)
107     {
108       /*
109         if L_LOST_LINK_time is not expired, the link is advertised
110         with a link type of LOST_LINK.
111       */
112       if(!TIMED_OUT(&entry->L_LOST_LINK_time))
113         return LOST_LINK;
114       /*
115         otherwise, if L_LOST_LINK_time is expired and L_link_pending
116         is set to "true", the link SHOULD NOT be advertised at all;
117       */
118       if(entry->L_link_pending == 1)
119         {
120 #ifdef DEBUG
121           olsr_printf(3, "HYST[%s]: Setting to HIDE\n", olsr_ip_to_string(&entry->neighbor_iface_addr));
122 #endif
123           return HIDE_LINK;
124         }
125       /*
126         otherwise, if L_LOST_LINK_time is expired and L_link_pending
127         is set to "false", the link is advertised as described
128         previously in section 6.
129       */
130     }
131
132   if(!TIMED_OUT(&entry->SYM_time))
133     return SYM_LINK;
134
135   if(!TIMED_OUT(&entry->ASYM_time))
136     return ASYM_LINK;
137
138   return LOST_LINK;
139
140
141 }
142
143
144
145
146
147
148 /**
149  *Find the "best" link status to a
150  *neighbor
151  *
152  *@param address the address to check for
153  *
154  *@return SYM_LINK if a symmetric link exists 0 if not
155  */
156 static int
157 get_neighbor_status(union olsr_ip_addr *address)
158 {
159   union olsr_ip_addr *main_addr;
160   struct addresses   *aliases;
161   struct link_entry  *link;
162   struct interface   *ifs;
163
164   //printf("GET_NEIGHBOR_STATUS\n");
165
166   /* Find main address */
167   if(!(main_addr = mid_lookup_main_addr(address)))
168     main_addr = address;
169
170   //printf("\tmain: %s\n", olsr_ip_to_string(main_addr));
171
172   /* Loop trough local interfaces to check all possebilities */
173   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
174     {
175       //printf("\tChecking %s->", olsr_ip_to_string(&ifs->ip_addr));
176       //printf("%s : ", olsr_ip_to_string(main_addr)); 
177       if((link = lookup_link_entry(main_addr, &ifs->ip_addr)) != NULL)
178         {
179           //printf("%d\n", lookup_link_status(link));
180           if(lookup_link_status(link) == SYM_LINK)
181             return SYM_LINK;
182         }
183       /* Get aliases */
184       for(aliases = mid_lookup_aliases(main_addr);
185           aliases != NULL;
186           aliases = aliases->next)
187         {
188           //printf("\tChecking %s->", olsr_ip_to_string(&ifs->ip_addr));
189           //printf("%s : ", olsr_ip_to_string(&aliases->address)); 
190           if((link = lookup_link_entry(&aliases->address, &ifs->ip_addr)) != NULL)
191             {
192               //printf("%d\n", lookup_link_status(link));
193
194               if(lookup_link_status(link) == SYM_LINK)
195                 return SYM_LINK;
196             }
197         }
198     }
199   
200   return 0;
201 }
202
203
204
205
206 /**
207  *Get the remote interface address to use as nexthop
208  *to reach the remote host.
209  *
210  *@param address the address of the remote host
211  *@return the nexthop address to use. Returns the pointer
212  *passed as arg 1 if nothing is found(if no MID is registered).
213  */
214 union olsr_ip_addr *
215 get_neighbor_nexthop(union olsr_ip_addr *address)
216 {
217   union olsr_ip_addr *main_addr;
218   struct addresses   *aliases;
219   struct link_entry  *link;
220   struct interface   *ifs;
221
222   //printf("GET_NEIGHBOR_NEXTHOP\n");
223
224   /* Find main address */
225   if(!(main_addr = mid_lookup_main_addr(address)))
226     main_addr = address;
227
228   //printf("\tmain: %s\n", olsr_ip_to_string(main_addr));
229
230   /* Loop trough local interfaces to check all possebilities */
231   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
232     {
233       //printf("\tChecking %s->", olsr_ip_to_string(&ifs->ip_addr));
234       //printf("%s : ", olsr_ip_to_string(main_addr)); 
235       if((link = lookup_link_entry(main_addr, &ifs->ip_addr)) != NULL)
236         {
237           //printf("%d\n", lookup_link_status(link));
238           if(lookup_link_status(link) == SYM_LINK)
239             return main_addr;
240         }
241       /* Get aliases */
242       for(aliases = mid_lookup_aliases(main_addr);
243           aliases != NULL;
244           aliases = aliases->next)
245         {
246           //printf("\tChecking %s->", olsr_ip_to_string(&ifs->ip_addr));
247           //printf("%s : ", olsr_ip_to_string(&aliases->address)); 
248           if((link = lookup_link_entry(&aliases->address, &ifs->ip_addr)) != NULL)
249             {
250               //printf("%d\n", lookup_link_status(link));
251
252               if(lookup_link_status(link) == SYM_LINK)
253                 return &aliases->address;
254             }
255         }
256     }
257   
258   /* This shoud only happen if not MID addresses for the
259    * multi-homed remote host are registered yet
260    */
261   return address;
262 }
263
264
265
266
267 /**
268  *Get the interface to use when setting up
269  *a route to a neighbor. The interface with
270  *the lowest metric is used.
271  *
272  *As this function is only called by the route calculation
273  *functions it is considered that the caller is responsible
274  *for making sure the neighbor is symmetric.
275  *Due to experiences of route calculaition queryig for interfaces
276  *when no links with a valid SYM time is avalibe, the function
277  *will return a possible interface with an expired SYM time
278  *if no SYM links were discovered.
279  *
280  *@param address of the neighbor - does not have to
281  *be the main address
282  *
283  *@return a interface struct representing the interface to use
284  */
285 struct interface *
286 get_interface_link_set(union olsr_ip_addr *remote)
287 {
288   struct link_entry *tmp_link_set;
289   union olsr_ip_addr *remote_addr;
290   struct interface *if_to_use, *tmp_if, *backup_if;
291
292   if_to_use = NULL;
293   backup_if = NULL;
294
295   if(remote == NULL || link_set == NULL)
296     {
297       olsr_printf(1, "Get interface: not sane request or empty link set!\n");
298       return NULL;
299     }
300
301   /* Check for main address of address */
302   if((remote_addr = mid_lookup_main_addr(remote)) == NULL)
303     remote_addr = remote;
304
305   tmp_link_set = link_set;
306   
307   while(tmp_link_set)
308     {
309       //printf("Checking %s vs ", olsr_ip_to_string(&tmp_link_set->neighbor_iface_addr));
310       //printf("%s\n", olsr_ip_to_string(addr));
311       
312       if(COMP_IP(remote_addr, &tmp_link_set->neighbor->neighbor_main_addr) ||
313          COMP_IP(remote_addr, &tmp_link_set->neighbor_iface_addr))
314         {
315
316           tmp_if = if_ifwithaddr(&tmp_link_set->local_iface_addr);
317
318           /* Must be symmetric link! */
319           if(!TIMED_OUT(&tmp_link_set->SYM_time))
320             {
321               if((if_to_use == NULL) || (if_to_use->int_metric > tmp_if->int_metric))
322                 if_to_use = tmp_if;
323             }
324           /* Backup solution in case the links have timed out */
325           else
326             {
327               if((if_to_use == NULL) && ((backup_if == NULL) || (backup_if->int_metric > tmp_if->int_metric)))
328                 {
329                   backup_if = tmp_if;
330                 }
331             }
332         }
333       
334       tmp_link_set = tmp_link_set->next;
335     }
336   
337   /* Not found */
338   if(if_to_use == NULL)
339     return backup_if;
340   
341   return if_to_use;
342 }
343
344
345
346 /**
347  *Nothing mysterious here.
348  *Adding a new link entry to the link set.
349  *
350  *@param local the local IP address
351  *@param remote the remote IP address
352  *@param remote_main teh remote nodes main address
353  *@param vtime the validity time of the entry
354  *@param htime the HELLO interval of the remote node
355  */
356
357 static struct link_entry *
358 add_new_entry(union olsr_ip_addr *local, union olsr_ip_addr *remote, union olsr_ip_addr *remote_main, double vtime, double htime)
359 {
360   struct link_entry *tmp_link_set, *new_link;
361   struct neighbor_entry *neighbor;
362 #ifndef WIN32
363   struct interface *local_if;
364 #endif
365
366   tmp_link_set = link_set;
367
368   while(tmp_link_set)
369     {
370       if(COMP_IP(remote, &tmp_link_set->neighbor_iface_addr))
371         return tmp_link_set;
372       tmp_link_set = tmp_link_set->next;
373     }
374
375   /*
376    * if there exists no link tuple with
377    * L_neighbor_iface_addr == Source Address
378    */
379
380 #ifdef DEBUG
381   olsr_printf(3, "Adding %s to link set\n", olsr_ip_to_string(remote));
382 #endif
383
384   /* a new tuple is created with... */
385
386   new_link = olsr_malloc(sizeof(struct link_entry), "new link entry");
387
388   /*
389    * L_local_iface_addr = Address of the interface
390    * which received the HELLO message
391    */
392   //printf("\tLocal IF: %s\n", olsr_ip_to_string(local));
393   COPY_IP(&new_link->local_iface_addr, local);
394   /* L_neighbor_iface_addr = Source Address */
395   COPY_IP(&new_link->neighbor_iface_addr, remote);
396
397   /* L_SYM_time            = current time - 1 (expired) */
398   new_link->SYM_time = now;
399   /* Subtract 1 */
400   new_link->SYM_time.tv_sec -= 1;
401
402   /* L_time = current time + validity time */
403   olsr_get_timestamp((olsr_u32_t) vtime*1000, &new_link->time);
404
405
406   /* HYSTERESIS */
407   if(use_hysteresis)
408     {
409       new_link->L_link_pending = 1;
410       olsr_get_timestamp((olsr_u32_t) vtime*1000, &new_link->L_LOST_LINK_time);
411       olsr_get_timestamp((olsr_u32_t) htime*1500, &new_link->hello_timeout);
412       new_link->last_htime = htime;
413       new_link->olsr_seqno = 0;
414       new_link->L_link_quality = 0;
415     }
416   /* Add to queue */
417   new_link->next = link_set;
418   link_set = new_link;
419
420
421   /*
422    * Create the neighbor entry
423    */
424
425   /* Neighbor MUST exist! */
426   if(NULL == (neighbor = olsr_lookup_neighbor_table(remote_main)))
427     {
428       neighbor = olsr_insert_neighbor_table(remote_main);
429       /* Copy the main address */
430       COPY_IP(&neighbor->neighbor_main_addr, remote_main);
431 #ifdef DEBUG
432       olsr_printf(3, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n", olsr_ip_to_string(remote_main));
433 #endif
434     }
435
436   neighbor->linkcount++;
437
438
439   new_link->neighbor = neighbor;
440
441   if(!COMP_IP(remote, remote_main))
442     {
443       /* Add MID alias if not already registered */
444       /* This is kind of sketchy... and not specified
445        * in the RFC. We can only guess a vtime.
446        * We'll go for one that is hopefully long
447        * enough in most cases. 20 seconds
448        */
449       olsr_printf(1, "Adding MID alias main %s ", olsr_ip_to_string(remote_main));
450       olsr_printf(1, "-> %s based on HELLO\n\n", olsr_ip_to_string(remote));
451       insert_mid_alias(remote_main, remote, 20.0);
452     }
453
454   /* Add to link-layer spy list */
455 #ifndef WIN32
456   if(llinfo)
457     {
458       local_if = if_ifwithaddr(local);
459       
460       olsr_printf(1, "Adding %s to spylist of interface %s\n", olsr_ip_to_string(remote), local_if->int_name);
461
462       if((local_if != NULL) && (add_spy_node(remote, local_if->int_name)))
463         new_link->spy_activated = 1;
464     }
465 #endif
466
467   return link_set;
468 }
469
470
471 /**
472  *Lookup the status of a link.
473  *
474  *@param int_addr address of the remote interface
475  *
476  *@return 1 of the link is symmertic 0 if not
477  */
478
479 int
480 check_neighbor_link(union olsr_ip_addr *int_addr)
481 {
482   struct link_entry *tmp_link_set;
483
484   tmp_link_set = link_set;
485
486   while(tmp_link_set)
487     {
488       if(COMP_IP(int_addr, &tmp_link_set->neighbor_iface_addr))
489         return lookup_link_status(tmp_link_set);
490       tmp_link_set = tmp_link_set->next;
491     }
492   return UNSPEC_LINK;
493 }
494
495
496 /**
497  *Lookup a link entry
498  *
499  *@param remote the remote interface address
500  *@param local the local interface address
501  *
502  *@return the link entry if found, NULL if not
503  */
504 struct link_entry *
505 lookup_link_entry(union olsr_ip_addr *remote, union olsr_ip_addr *local)
506 {
507   struct link_entry *tmp_link_set;
508
509   tmp_link_set = link_set;
510
511   while(tmp_link_set)
512     {
513       if(COMP_IP(remote, &tmp_link_set->neighbor_iface_addr) &&
514          COMP_IP(local, &tmp_link_set->local_iface_addr))
515         return tmp_link_set;
516       tmp_link_set = tmp_link_set->next;
517     }
518   return NULL;
519
520 }
521
522
523
524
525
526
527
528 /**
529  *Update a link entry. This is the "main entrypoint" in
530  *the link-sensing. This function is calles from the HELLO
531  *parser function.
532  *It makes sure a entry is updated or created.
533  *
534  *@param local the local IP address
535  *@param remote the remote IP address
536  *@param message the HELLO message
537  *@param in_if the interface on which this HELLO was received
538  *
539  *@return the link_entry struct describing this link entry
540  */
541 struct link_entry *
542 update_link_entry(union olsr_ip_addr *local, union olsr_ip_addr *remote, struct hello_message *message, struct interface *in_if)
543 {
544   int status;
545   struct link_entry *entry;
546 #ifndef WIN32
547   struct interface *local_if;
548 #endif
549
550   /* Time out entries */
551   //timeout_link_set();
552
553   /* Add if not registered */
554   entry = add_new_entry(local, remote, &message->source_addr, message->vtime, message->htime);
555
556   /* Update link layer info */
557   /* Add to link-layer spy list */
558 #ifndef WIN32
559   if(llinfo && !entry->spy_activated)
560     {
561       local_if = if_ifwithaddr(local);
562       
563       olsr_printf(1, "Adding %s to spylist of interface %s\n", olsr_ip_to_string(remote), local_if->int_name);
564
565       if((local_if != NULL) && (add_spy_node(remote, local_if->int_name)))
566         entry->spy_activated = 1;
567     }
568 #endif
569
570   /* Update ASYM_time */
571   //printf("Vtime is %f\n", message->vtime);
572   /* L_ASYM_time = current time + validity time */
573   olsr_get_timestamp((olsr_u32_t) (message->vtime*1000), &entry->ASYM_time);
574
575
576   status = check_link_status(message);
577
578   //printf("Status %d\n", status);
579
580   switch(status)
581     {
582     case(LOST_LINK):
583       /* L_SYM_time = current time - 1 (i.e., expired) */
584       entry->SYM_time = now;
585       entry->SYM_time.tv_sec -= 1;
586
587       break;
588     case(SYM_LINK):
589     case(ASYM_LINK):
590       /* L_SYM_time = current time + validity time */
591       //printf("updating SYM time for %s\n", olsr_ip_to_string(remote));
592       olsr_get_timestamp((olsr_u32_t) (message->vtime*1000), &entry->SYM_time);
593         //timeradd(&now, &tmp_timer, &entry->SYM_time);
594
595       /* L_time = L_SYM_time + NEIGHB_HOLD_TIME */
596       if(in_if->is_wireless)
597         timeradd(&entry->SYM_time, &hold_time_neighbor, &entry->time);
598       else
599         timeradd(&entry->SYM_time, &hold_time_neighbor_nw, &entry->time);
600
601       break;
602     default:;
603     }
604
605   /* L_time = max(L_time, L_ASYM_time) */
606   if(timercmp(&entry->time, &entry->ASYM_time, <))
607     entry->time = entry->ASYM_time;
608
609
610   /*
611   printf("Updating link LOCAL: %s ", olsr_ip_to_string(local));
612   printf("REMOTE: %s\n", olsr_ip_to_string(remote));
613   printf("VTIME: %f ", message->vtime);
614   printf("STATUS: %d\n", status);
615   */
616
617   /* Update hysteresis values */
618   if(use_hysteresis)
619     olsr_process_hysteresis(entry);
620
621   /* update neighbor status */
622   /* Return link status */
623   //status = lookup_link_status(entry);
624   /* UPDATED ! */
625   status = get_neighbor_status(remote);
626
627   /* Update neighbor */
628   update_neighbor_status(entry->neighbor, status);
629   //update_neighbor_status(entry->neighbor);
630
631   return entry;  
632 }
633
634
635 /**
636  * Fuction that updates all registered pointers to
637  * one neighbor entry with another pointer
638  * Used by MID updates.
639  *
640  *@old the pointer to replace
641  *@new the pointer to use instead of "old"
642  *
643  *@return the number of entries updated
644  */
645 int
646 replace_neighbor_link_set(struct neighbor_entry *old,
647                           struct neighbor_entry *new)
648 {
649   struct link_entry *tmp_link_set, *last_link_entry;
650   int retval;
651
652   retval = 0;
653
654   if(link_set == NULL)
655     return retval;
656       
657   tmp_link_set = link_set;
658   last_link_entry = NULL;
659
660   while(tmp_link_set)
661     {
662
663       if(tmp_link_set->neighbor == old)
664         {
665           tmp_link_set->neighbor = new;
666           retval++;
667         }
668       tmp_link_set = tmp_link_set->next;
669     }
670
671   return retval;
672
673 }
674
675
676 /**
677  *Checks the link status to a neighbor by
678  *looking in a received HELLO message.
679  *
680  *@param message the HELLO message to check
681  *
682  *@return the link status
683  */
684 static int
685 check_link_status(struct hello_message *message)
686 {
687
688   struct hello_neighbor  *neighbors;
689   struct interface *ifd;
690
691   neighbors = message->neighbors;
692   
693   while(neighbors!=NULL)
694     {  
695       //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
696       //printf("against %s\n",olsr_ip_to_string(&main_addr));
697
698       /* Check all interfaces */          
699       for (ifd = ifnet; ifd ; ifd = ifd->int_next) 
700         {
701           if(COMP_IP(&neighbors->address, &ifd->ip_addr))
702             {
703               //printf("ok");
704               return neighbors->link;
705             }
706         }
707
708       neighbors = neighbors->next; 
709     }
710
711
712   return UNSPEC_LINK;
713 }
714
715
716 /**
717  *Time out the link set. In other words, the link
718  *set is traversed and all non-valid entries are
719  *deleted.
720  *
721  */
722 static void
723 olsr_time_out_link_set()
724 {
725
726   struct link_entry *tmp_link_set, *last_link_entry;
727
728   if(link_set == NULL)
729     return;
730       
731   tmp_link_set = link_set;
732   last_link_entry = NULL;
733
734   while(tmp_link_set)
735     {
736
737       if(TIMED_OUT(&tmp_link_set->time))
738         {
739           if(last_link_entry != NULL)
740             {
741               last_link_entry->next = tmp_link_set->next;
742
743               /* Delete neighbor entry */
744               if(tmp_link_set->neighbor->linkcount == 1)
745                 olsr_delete_neighbor_table(&tmp_link_set->neighbor->neighbor_main_addr);
746               else
747                 tmp_link_set->neighbor->linkcount--;
748
749               //olsr_delete_neighbor_if_no_link(&tmp_link_set->neighbor->neighbor_main_addr);
750               changes_neighborhood = UP;
751
752               free(tmp_link_set);
753               tmp_link_set = last_link_entry;
754             }
755           else
756             {
757               link_set = tmp_link_set->next; /* CHANGED */
758
759               /* Delete neighbor entry */
760               if(tmp_link_set->neighbor->linkcount == 1)
761                 olsr_delete_neighbor_table(&tmp_link_set->neighbor->neighbor_main_addr);
762               else
763                 tmp_link_set->neighbor->linkcount--;
764               //olsr_delete_neighbor_if_no_link(&tmp_link_set->neighbor->neighbor_main_addr);
765
766               changes_neighborhood = UP;
767
768               free(tmp_link_set);
769               tmp_link_set = link_set;
770               continue;
771             }       
772         }
773       
774       last_link_entry = tmp_link_set;
775       tmp_link_set = tmp_link_set->next;
776     }
777
778   return;
779 }
780
781
782
783
784 /**
785  *Updates links that we have not received
786  *HELLO from in expected time according to 
787  *hysteresis.
788  *
789  *@return nada
790  */
791 static void
792 olsr_time_out_hysteresis()
793 {
794
795   struct link_entry *tmp_link_set;
796   int status;
797
798   if(link_set == NULL)
799     return;
800
801   tmp_link_set = link_set;
802
803   while(tmp_link_set)
804     {
805       if(TIMED_OUT(&tmp_link_set->hello_timeout))
806         {
807           tmp_link_set->L_link_quality = olsr_hyst_calc_instability(tmp_link_set->L_link_quality);
808           olsr_printf(1, "HYST[%s] HELLO timeout %0.3f\n", olsr_ip_to_string(&tmp_link_set->neighbor_iface_addr), tmp_link_set->L_link_quality);
809           /* Update hello_timeout - NO SLACK THIS TIME */
810           olsr_get_timestamp((olsr_u32_t) tmp_link_set->last_htime*1000, &tmp_link_set->hello_timeout);
811
812           /* Recalculate status */
813           /* Update hysteresis values */
814           olsr_process_hysteresis(tmp_link_set);
815           
816           /* update neighbor status */
817           //status = lookup_link_status(tmp_link_set);
818           /* UPDATED ! */
819           status = get_neighbor_status(&tmp_link_set->neighbor_iface_addr);
820
821
822           /* Update neighbor */
823           update_neighbor_status(tmp_link_set->neighbor, status);
824           //update_neighbor_status(tmp_link_set->neighbor);
825
826           /* Update seqno - not mentioned in the RFC... kind of a hack.. */
827           tmp_link_set->olsr_seqno++;
828         }
829       tmp_link_set = tmp_link_set->next;
830     }
831
832   return;
833 }
834