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