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