Removed superfluous maxplen config var
[olsrd.git] / src / link_set.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /*
43  * Link sensing database for the OLSR routing daemon
44  */
45
46 #include "defs.h"
47 #include "link_set.h"
48 #include "mid_set.h"
49 #include "mpr.h"
50 #include "neighbor_table.h"
51 #include "olsr.h"
52 #include "scheduler.h"
53 #include "olsr_spf.h"
54 #include "net_olsr.h"
55 #include "ipcalc.h"
56 #include "lq_plugin.h"
57 #include "common/string.h"
58
59 /* head node for all link sets */
60 struct list_node link_entry_head;
61
62 static struct olsr_cookie_info *link_dead_timer_cookie = NULL;
63 static struct olsr_cookie_info *link_loss_timer_cookie = NULL;
64 static struct olsr_cookie_info *link_sym_timer_cookie = NULL;
65
66
67 bool link_changes;                     /* is set if changes occur in MPRS set */
68
69 void
70 signal_link_changes(bool val)
71 {                               /* XXX ugly */
72   link_changes = val;
73 }
74
75 /* Prototypes. */
76 static int check_link_status(const struct lq_hello_message *message,
77                              const struct interface *in_if);
78 static struct link_entry *add_link_entry(const union olsr_ip_addr *,
79                                          const union olsr_ip_addr *,
80                                          union olsr_ip_addr *, olsr_reltime,
81                                          olsr_reltime, struct interface *);
82 static int get_neighbor_status(const union olsr_ip_addr *);
83
84 void
85 olsr_init_link_set(void)
86 {
87
88   /* Init list head */
89   list_head_init(&link_entry_head);
90
91   link_dead_timer_cookie =
92     olsr_alloc_cookie("Link dead", OLSR_COOKIE_TYPE_TIMER);
93   link_loss_timer_cookie =
94     olsr_alloc_cookie("Link loss", OLSR_COOKIE_TYPE_TIMER);
95   link_sym_timer_cookie =
96     olsr_alloc_cookie("Link SYM", OLSR_COOKIE_TYPE_TIMER);
97
98 }
99
100
101 /**
102  * Get the status of a link. The status is based upon different
103  * timeouts in the link entry.
104  *
105  * @param remote address of the remote interface
106  * @return the link status of the link
107  */
108 int
109 lookup_link_status(const struct link_entry *entry)
110 {
111
112   if (entry == NULL || list_is_empty(&link_entry_head)) {
113     return UNSPEC_LINK;
114   }
115
116   /*
117    * Hysteresis
118    */
119   if (entry->link_sym_timer) {
120     return SYM_LINK;
121   }
122
123   if (!TIMED_OUT(entry->ASYM_time)) {
124     return ASYM_LINK;
125   }
126
127   return LOST_LINK;
128 }
129
130
131 /**
132  * Find the "best" link status to a neighbor
133  *
134  * @param address the address to check for
135  * @return SYM_LINK if a symmetric link exists 0 if not
136  */
137 static int
138 get_neighbor_status(const union olsr_ip_addr *address)
139 {
140   const union olsr_ip_addr *main_addr;
141   struct interface *ifs;
142   struct tc_entry *tc;
143
144   /* Find main address */
145   if (!(main_addr = olsr_lookup_main_addr_by_alias(address)))
146     main_addr = address;
147
148   /*
149    * Locate the hookup point.
150    */
151   tc = olsr_locate_tc_entry(main_addr);
152
153   /* Loop trough local interfaces to check all possebilities */
154   OLSR_FOR_ALL_INTERFACES(ifs) {
155
156     struct mid_entry *aliases;
157     struct link_entry *lnk = lookup_link_entry(main_addr, NULL, ifs);
158
159     if (lnk != NULL) {
160       if (lookup_link_status(lnk) == SYM_LINK)
161         return SYM_LINK;
162     }
163
164     /* Walk the aliases */
165     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, aliases) {
166
167       lnk = lookup_link_entry(&aliases->mid_alias_addr, NULL, ifs);
168       if (lnk && (lookup_link_status(lnk) == SYM_LINK)) {
169           return SYM_LINK;
170       }
171     } OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, aliases);
172   } OLSR_FOR_ALL_INTERFACES_END(ifs);
173
174   return 0;
175 }
176
177 /**
178  * Find best link to a neighbor
179  */
180 struct link_entry *
181 get_best_link_to_neighbor(const union olsr_ip_addr *remote)
182 {
183   const union olsr_ip_addr *main_addr;
184   struct link_entry *walker, *good_link, *backup_link;
185   olsr_linkcost curr_lcost = LINK_COST_BROKEN;
186   olsr_linkcost tmp_lc;
187
188   /* main address lookup */
189   main_addr = olsr_lookup_main_addr_by_alias(remote);
190
191   /* "remote" *already is* the main address */
192   if (!main_addr) {
193     main_addr = remote;
194   }
195
196   /* we haven't selected any links, yet */
197   good_link = NULL;
198   backup_link = NULL;
199
200   /* loop through all links that we have */
201   OLSR_FOR_ALL_LINK_ENTRIES(walker) {
202
203     /* if this is not a link to the neighour in question, skip */
204     if (!ipequal(&walker->neighbor->neighbor_main_addr, main_addr))
205       continue;
206
207     /* get the link cost */
208     tmp_lc = walker->linkcost;
209
210     /*
211      * is this link better than anything we had before ?
212      * use the requested remote interface address as a tie-breaker.
213      */
214     if ((tmp_lc < curr_lcost) ||
215         ((tmp_lc == curr_lcost) &&
216          ipequal(&walker->local_iface_addr, remote))) {
217
218       /* memorize the link quality */
219       curr_lcost = tmp_lc;
220
221       /* prefer symmetric links over asymmetric links */
222       if (lookup_link_status(walker) == SYM_LINK) {
223         good_link = walker;
224       } else {
225         backup_link = walker;
226       }
227     }
228   } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
229
230   /*
231    * if we haven't found any symmetric links, try to return an asymmetric link.
232    */
233   return good_link ? good_link : backup_link;
234 }
235
236 static void
237 set_loss_link_multiplier(struct link_entry *entry)
238 {
239   struct interface *inter;
240   struct olsr_if_config *cfg_inter;
241   struct olsr_lq_mult *mult;
242   uint32_t val = 0;
243
244   /* find the interface for the link */
245   inter = if_ifwithaddr(&entry->local_iface_addr);
246
247   /* find the interface configuration for the interface */
248   for (cfg_inter = olsr_cnf->if_configs; cfg_inter;
249        cfg_inter = cfg_inter->next) {
250     if (cfg_inter->interf == inter) {
251       break;
252     }
253   }
254
255   /* loop through the multiplier entries */
256   for (mult = cfg_inter->cnf->lq_mult; mult != NULL; mult = mult->next) {
257     /*
258      * use the default multiplier only if there isn't any entry that
259      * has a matching IP address.
260      */
261     if ((val == 0 && ipequal(&mult->addr, &all_zero)) ||
262         ipequal(&mult->addr, &entry->neighbor_iface_addr)) {
263       val = mult->value;
264     }
265   }
266
267   /* if we have not found an entry, then use the default multiplier */
268   if (val == 0) {
269     val = LINK_LOSS_MULTIPLIER;
270   }
271
272   /* store the multiplier */
273   entry->loss_link_multiplier = val;
274 }
275
276 /*
277  * Delete, unlink and free a link entry.
278  */
279 static void
280 olsr_delete_link_entry(struct link_entry *link)
281 {
282
283   /*
284    * Delete the corresponding tc-edge for that link.
285    */
286   if (link->link_tc_edge) {
287     olsr_delete_tc_edge_entry(link->link_tc_edge);
288     link->link_tc_edge = NULL;
289   }
290
291   /*
292    * Delete the rt_path for the link-end.
293    */
294   olsr_delete_routing_table(&link->neighbor_iface_addr, 8 * olsr_cnf->ipsize,
295                             &link->neighbor->neighbor_main_addr,
296                             OLSR_RT_ORIGIN_LINK);
297
298   /* Delete neighbor entry */
299   if (link->neighbor->linkcount == 1) {
300     olsr_delete_neighbor_table(&link->neighbor->neighbor_main_addr);
301   } else {
302     link->neighbor->linkcount--;
303   }
304
305   /* Kill running timers */
306   olsr_stop_timer(link->link_timer);
307   link->link_timer = NULL;
308   olsr_stop_timer(link->link_sym_timer);
309   link->link_sym_timer = NULL;
310   olsr_stop_timer(link->link_loss_timer);
311   link->link_loss_timer = NULL;
312
313   list_remove(&link->link_list);
314
315   /* Unlink Interfaces */
316   unlock_interface(link->inter);
317   link->inter = NULL;
318
319   free(link->if_name);
320   olsr_free_link_entry(link);
321
322   changes_neighborhood = true;
323 }
324
325 /**
326  * Delete all link entries matching a given interface id
327  */
328 void
329 olsr_delete_link_entry_by_if(const struct interface *ifp)
330 {
331   struct link_entry *link;
332
333   if (list_is_empty(&link_entry_head)) {
334     return;
335   }
336
337   OLSR_FOR_ALL_LINK_ENTRIES(link) {
338     if (ifp == link->inter) {
339       olsr_delete_link_entry(link);
340     }
341   } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
342 }
343
344 /**
345  * Callback for the link loss timer.
346  */
347 static void
348 olsr_expire_link_loss_timer(void *context)
349 {
350   struct link_entry *link;
351
352   link = (struct link_entry *)context;
353
354   /* count the lost packet */
355   olsr_update_packet_loss_worker(link, true);
356
357   /* next timeout in 1.0 x htime */
358   olsr_change_timer(link->link_loss_timer, link->loss_helloint,
359                     OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC);
360 }
361
362 /**
363  * Callback for the link SYM timer.
364  */
365 static void
366 olsr_expire_link_sym_timer(void *context)
367 {
368   struct link_entry *link;
369
370   link = (struct link_entry *)context;
371   link->link_sym_timer = NULL;  /* be pedandic */
372
373   if (link->prev_status != SYM_LINK) {
374     return;
375   }
376
377   link->prev_status = lookup_link_status(link);
378   update_neighbor_status(link->neighbor,
379                          get_neighbor_status(&link->neighbor_iface_addr));
380   changes_neighborhood = true;
381 }
382
383 /**
384  * Callback for the link_hello timer.
385  */
386 void
387 olsr_expire_link_hello_timer(void *context)
388 {
389   struct link_entry *link;
390
391   link = (struct link_entry *)context;
392
393   /* update neighbor status */
394   update_neighbor_status(link->neighbor,
395                          get_neighbor_status(&link->neighbor_iface_addr));
396 }
397
398 /**
399  * Callback for the link timer.
400  */
401 static void
402 olsr_expire_link_entry(void *context)
403 {
404   struct link_entry *link;
405
406   link = (struct link_entry *)context;
407   link->link_timer = NULL;      /* be pedandic */
408
409   olsr_delete_link_entry(link);
410 }
411
412 /**
413  * Set the link expiration timer.
414  */
415 static void
416 olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
417 {
418   olsr_set_timer(&link->link_timer, rel_timer, OLSR_LINK_JITTER,
419                  OLSR_TIMER_ONESHOT, &olsr_expire_link_entry, link,
420                  link_dead_timer_cookie->ci_id);
421 }
422
423 /**
424  * Nothing mysterious here.
425  * Adding a new link entry to the link set.
426  *
427  * @param local the local IP address
428  * @param remote the remote IP address
429  * @param remote_main the remote nodes main address
430  * @param vtime the validity time of the entry
431  * @param htime the HELLO interval of the remote node
432  * @param local_if the local interface
433  * @return the new (or already existing) link_entry
434  */
435 static struct link_entry *
436 add_link_entry(const union olsr_ip_addr *local,
437                const union olsr_ip_addr *remote,
438                union olsr_ip_addr *remote_main,
439                olsr_reltime vtime, olsr_reltime htime,
440                struct interface *local_if)
441 {
442   struct link_entry *link;
443   struct neighbor_entry *neighbor;
444
445   link = lookup_link_entry(remote, remote_main, local_if);
446   if (link) {
447
448     /*
449      * Link exists. Update tc_edge LQ and exit.
450      */
451     olsr_copylq_link_entry_2_tc_edge_entry(link->link_tc_edge, link);
452     changes_neighborhood = olsr_calc_tc_edge_entry_etx(link->link_tc_edge);
453     return link;
454   }
455
456   /*
457    * if there exists no link tuple with
458    * L_neighbor_iface_addr == Source Address
459    */
460
461 #ifdef DEBUG
462   {
463     struct ipaddr_str localbuf, rembuf;
464     OLSR_PRINTF(1, "Adding %s=>%s to link set\n",
465                 olsr_ip_to_string(&localbuf, local), olsr_ip_to_string(&rembuf,
466                                                                        remote));
467   }
468 #endif
469
470   /* a new tuple is created with... */
471   link = olsr_malloc_link_entry();
472
473   /* copy if_name, if it is defined */
474   if (local_if->int_name) {
475     size_t name_size = strlen(local_if->int_name) + 1;
476     link->if_name =
477       olsr_malloc(name_size, "target of if_name in new link entry");
478     strscpy(link->if_name, local_if->int_name, name_size);
479   } else
480     link->if_name = NULL;
481
482   /* shortcut to interface. */
483   link->inter = local_if;
484   lock_interface(local_if);
485
486   /*
487    * L_local_iface_addr = Address of the interface
488    * which received the HELLO message
489    */
490   link->local_iface_addr = *local;
491
492   /* L_neighbor_iface_addr = Source Address */
493   link->neighbor_iface_addr = *remote;
494
495   /* L_time = current time + validity time */
496   olsr_set_link_timer(link, vtime);
497
498   link->prev_status = ASYM_LINK;
499
500   link->loss_helloint = htime;
501
502   olsr_set_timer(&link->link_loss_timer, htime + htime/2,
503                  OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
504                  &olsr_expire_link_loss_timer, link,
505                  link_loss_timer_cookie->ci_id);
506
507   set_loss_link_multiplier(link);
508
509   link->linkcost = LINK_COST_BROKEN;
510
511   /* Add to queue */
512   list_add_before(&link_entry_head, &link->link_list);
513
514   /*
515    * Create the neighbor entry
516    */
517
518   /* Neighbor MUST exist! */
519   neighbor = olsr_lookup_neighbor_table(remote_main);
520   if (!neighbor) {
521 #ifdef DEBUG
522     struct ipaddr_str buf;
523     OLSR_PRINTF(3, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n",
524                 olsr_ip_to_string(&buf, remote_main));
525 #endif
526     neighbor = olsr_insert_neighbor_table(remote_main);
527   }
528
529   neighbor->linkcount++;
530   link->neighbor = neighbor;
531
532   /*
533    * Add the rt_path for the link-end. This is an optimization
534    * that lets us install > 1 hop routes prior to receiving
535    * the MID entry for the 1 hop neighbor.
536    */
537   olsr_insert_routing_table(remote, 8 * olsr_cnf->ipsize, remote_main,
538                             OLSR_RT_ORIGIN_LINK);
539
540   /*
541    * Now create a tc-edge for that link.
542    */
543   olsr_change_myself_tc();
544   link->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, remote_main, 0);
545
546   /*
547    * Mark the edge local such that it does not get deleted
548    * during cleanup functions.
549    */
550   link->link_tc_edge->flags |= TC_EDGE_FLAG_LOCAL;
551
552   changes_neighborhood = true;
553   return link;
554 }
555
556
557 /**
558  * Lookup the status of a link.
559  *
560  * @param int_addr address of the remote interface
561  * @return 1 of the link is symmertic 0 if not
562  */
563 int
564 check_neighbor_link(const union olsr_ip_addr *int_addr)
565 {
566   struct link_entry *link;
567
568   OLSR_FOR_ALL_LINK_ENTRIES(link) {
569     if (ipequal(int_addr, &link->neighbor_iface_addr)) {
570       return lookup_link_status(link);
571     }
572   } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
573
574   return UNSPEC_LINK;
575 }
576
577 /**
578  * Lookup a link entry
579  *
580  * @param remote the remote interface address
581  * @param remote_main the remote nodes main address
582  * @param local the local interface address
583  * @return the link entry if found, NULL if not
584  */
585 struct link_entry *
586 lookup_link_entry(const union olsr_ip_addr *remote,
587                   const union olsr_ip_addr *remote_main,
588                   const struct interface *local)
589 {
590   struct link_entry *link;
591
592   OLSR_FOR_ALL_LINK_ENTRIES(link) {
593     if (ipequal(remote, &link->neighbor_iface_addr) &&
594         (link->if_name ? !strcmp(link->if_name, local->int_name)
595          : ipequal(&local->ip_addr, &link->local_iface_addr)))
596     {
597       /* check the remote-main address only if there is one given */
598       if (NULL != remote_main && !ipequal(remote_main, &link->neighbor->neighbor_main_addr))
599       {
600         /* Neighbor has changed it's main_addr, update */
601         struct ipaddr_str oldbuf, newbuf;
602         OLSR_PRINTF(1, "Neighbor changed main_ip, updating %s -> %s\n",
603           olsr_ip_to_string(&oldbuf, &link->neighbor->neighbor_main_addr), olsr_ip_to_string(&newbuf, remote_main));
604         link->neighbor->neighbor_main_addr = *remote_main;
605       }
606       return link;
607     }
608   } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
609
610   return NULL;
611 }
612
613 /**
614  * Update a link entry. This is the "main entrypoint" in
615  * the link-sensing. This function is called from the HELLO
616  * parser function. It makes sure a entry is updated or created.
617  *
618  * @param local the local IP address
619  * @param remote the remote IP address
620  * @param message the HELLO message
621  * @param in_if the interface on which this HELLO was received
622  * @return the link_entry struct describing this link entry
623  */
624 struct link_entry *
625 update_link_entry(const union olsr_ip_addr *local,
626                   const union olsr_ip_addr *remote,
627                   struct lq_hello_message *message,
628                   struct interface *in_if)
629 {
630   struct link_entry *entry;
631
632   /* Add if not registered */
633   entry =
634     add_link_entry(local, remote, &message->comm.orig, message->comm.vtime,
635                    message->htime, in_if);
636
637   /* Update ASYM_time */
638   entry->vtime = message->comm.vtime;
639   entry->ASYM_time = GET_TIMESTAMP(message->comm.vtime);
640
641   entry->prev_status = check_link_status(message, in_if);
642
643   switch (entry->prev_status) {
644   case (LOST_LINK):
645     olsr_stop_timer(entry->link_sym_timer);
646     entry->link_sym_timer = NULL;
647     break;
648   case (SYM_LINK):
649   case (ASYM_LINK):
650
651     /* L_SYM_time = current time + validity time */
652     olsr_set_timer(&entry->link_sym_timer, message->comm.vtime,
653                    OLSR_LINK_SYM_JITTER, OLSR_TIMER_ONESHOT,
654                    &olsr_expire_link_sym_timer, entry,
655                    link_sym_timer_cookie->ci_id);
656
657     /* L_time = L_SYM_time + NEIGHB_HOLD_TIME */
658     olsr_set_link_timer(entry, message->comm.vtime + NEIGHB_HOLD_TIME *
659                         MSEC_PER_SEC);
660     break;
661   default:;
662   }
663
664   /* L_time = max(L_time, L_ASYM_time) */
665   if (entry->link_timer && (entry->link_timer->timer_clock < entry->ASYM_time)) {
666     olsr_set_link_timer(entry, TIME_DUE(entry->ASYM_time));
667   }
668
669   /* Update neighbor */
670   update_neighbor_status(entry->neighbor, get_neighbor_status(remote));
671
672   return entry;
673 }
674
675
676 /**
677  * Function that updates all registered pointers to
678  * one neighbor entry with another pointer
679  * Used by MID updates.
680  *
681  * @old the pointer to replace
682  * @new the pointer to use instead of "old"
683  * @return the number of entries updated
684  */
685 int
686 replace_neighbor_link_set(const struct neighbor_entry *old,
687                           struct neighbor_entry *new)
688 {
689   struct link_entry *link;
690   int retval = 0;
691
692   if (list_is_empty(&link_entry_head)) {
693     return retval;
694   }
695
696   OLSR_FOR_ALL_LINK_ENTRIES(link) {
697
698     if (link->neighbor == old) {
699       link->neighbor = new;
700       retval++;
701     }
702   } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
703
704   return retval;
705 }
706
707
708 /**
709  *Checks the link status to a neighbor by
710  *looking in a received HELLO message.
711  *
712  *@param message the HELLO message to check
713  *
714  *@return the link status
715  */
716 static int
717 check_link_status(const struct lq_hello_message *message,
718                   const struct interface *in_if)
719 {
720   int ret = UNSPEC_LINK;
721   struct lq_hello_neighbor *neighbors;
722
723   neighbors = message->neigh;
724   while (neighbors) {
725
726     /*
727      * Note: If a neigh has 2 cards we can reach, the neigh
728      * will send a Hello with the same IP mentined twice
729      */
730     if (ipequal(&neighbors->addr, &in_if->ip_addr)) {
731       ret = neighbors->link_type;
732       if (SYM_LINK == ret) {
733         break;
734       }
735     }
736     neighbors = neighbors->next;
737   }
738
739   return ret;
740 }
741
742 void
743 olsr_print_link_set(void)
744 {
745 #ifndef NODEBUG
746   /* The whole function makes no sense without it. */
747   struct link_entry *walker;
748   const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
749
750   OLSR_PRINTF(0,
751               "\n--- %s ---------------------------------------------------- LINKS\n\n",
752               olsr_wallclock_string());
753   OLSR_PRINTF(1, "%-*s  %-6s %-14s %s\n", addrsize, "IP address", "hyst",
754               "      LQ      ", "ETX");
755
756   OLSR_FOR_ALL_LINK_ENTRIES(walker) {
757
758     struct ipaddr_str buf;
759     struct lqtextbuffer lqbuffer1, lqbuffer2;
760     OLSR_PRINTF(1, "%-*s %-14s %s\n",
761                 addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
762                 get_link_entry_text(walker, '/', &lqbuffer1),
763                 get_linkcost_text(walker->linkcost, false, &lqbuffer2));
764   } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
765 #endif
766 }
767
768 /*
769  * called for every LQ HELLO message.
770  * update the timeout with the htime value from the message
771  */
772 void
773 olsr_update_packet_loss_hello_int(struct link_entry *entry,
774                                   olsr_reltime loss_hello_int)
775 {
776   entry->loss_helloint = loss_hello_int;
777 }
778
779 void
780 olsr_update_packet_loss(struct link_entry *entry)
781 {
782   olsr_update_packet_loss_worker(entry, false);
783
784   /* timeout for the first lost packet is 1.5 x htime */
785   olsr_set_timer(&entry->link_loss_timer, entry->loss_helloint + entry->loss_helloint/2,
786                  OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
787                  &olsr_expire_link_loss_timer, entry,
788                  link_loss_timer_cookie->ci_id);
789 }
790
791 /*
792  * Local Variables:
793  * c-basic-offset: 2
794  * indent-tabs-mode: nil
795  * End:
796  */