gateway: add interface to get the gateway costs
[olsrd.git] / src / link_set.c
index 63bcaf9..aa6a9ea 100644 (file)
 /*
  * Link sensing database for the OLSR routing daemon
  */
+#include <assert.h>
 
 #include "defs.h"
 #include "link_set.h"
+#include "hysteresis.h"
 #include "mid_set.h"
 #include "mpr.h"
 #include "neighbor_table.h"
 #include "olsr.h"
+#include "log.h"
 #include "scheduler.h"
 #include "olsr_spf.h"
 #include "net_olsr.h"
 #include "ipcalc.h"
 #include "lq_plugin.h"
-#include "common/string.h"
 
 /* head node for all link sets */
 struct list_node link_entry_head;
 
-static struct olsr_cookie_info *link_dead_timer_cookie = NULL;
-static struct olsr_cookie_info *link_loss_timer_cookie = NULL;
-static struct olsr_cookie_info *link_sym_timer_cookie = NULL;
-
-
-bool link_changes;                    /* is set if changes occur in MPRS set */
+bool link_changes;                     /* is set if changes occur in MPRS set */
 
 void
 signal_link_changes(bool val)
-{                              /* XXX ugly */
+{                               /* XXX ugly */
   link_changes = val;
 }
 
 /* Prototypes. */
-static int check_link_status(const struct lq_hello_message *message,
-                             const struct interface *in_if);
-static struct link_entry *add_link_entry(const union olsr_ip_addr *,
-                                        const union olsr_ip_addr *,
-                                        const union olsr_ip_addr *, olsr_reltime,
-                                        olsr_reltime, struct interface *);
+static int check_link_status(const struct hello_message *message, const struct interface *in_if);
+static struct link_entry *add_link_entry(const union olsr_ip_addr *, const union olsr_ip_addr *, const union olsr_ip_addr *,
+                                         olsr_reltime, olsr_reltime, const struct interface *);
 static int get_neighbor_status(const union olsr_ip_addr *);
+static void olsr_expire_link_sym_timer(void *context);
 
 void
 olsr_init_link_set(void)
@@ -87,22 +82,38 @@ olsr_init_link_set(void)
 
   /* Init list head */
   list_head_init(&link_entry_head);
+}
+
+/**
+ * This function resets all links to lost, so that
+ * a final "lost all links" hello can be generated to
+ * tell your neighbors that you are gone now.
+ */
+void olsr_reset_all_links(void) {
+  struct link_entry *link;
 
-  link_dead_timer_cookie =
-    olsr_alloc_cookie("Link dead", OLSR_COOKIE_TYPE_TIMER);
-  link_loss_timer_cookie =
-    olsr_alloc_cookie("Link loss", OLSR_COOKIE_TYPE_TIMER);
-  link_sym_timer_cookie =
-    olsr_alloc_cookie("Link SYM", OLSR_COOKIE_TYPE_TIMER);
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    link->ASYM_time = now_times-1;
 
-}
+    olsr_stop_timer(link->link_sym_timer);
+    link->link_sym_timer = NULL;
+
+    link->neighbor->is_mpr = false;
+    link->neighbor->status = NOT_SYM;
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
 
 
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    olsr_expire_link_sym_timer(link);
+    olsr_clear_hello_lq(link);
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
+}
+
 /**
  * Get the status of a link. The status is based upon different
  * timeouts in the link entry.
  *
- * @param remote address of the remote interface
+ * @param entry link entry
  * @return the link status of the link
  */
 int
@@ -116,6 +127,36 @@ lookup_link_status(const struct link_entry *entry)
   /*
    * Hysteresis
    */
+  if (olsr_cnf->use_hysteresis) {
+
+    /*
+     * if L_LOST_LINK_time is not expired, the link is advertised
+     * with a link type of LOST_LINK.
+     */
+
+    if (!TIMED_OUT(entry->L_LOST_LINK_time)) {
+      return LOST_LINK;
+    }
+
+    /*
+     * otherwise, if L_LOST_LINK_time is expired and L_link_pending
+     * is set to "true", the link SHOULD NOT be advertised at all;
+     */
+    if (entry->L_link_pending == 1) {
+#ifndef NODEBUG
+      struct ipaddr_str buf;
+      OLSR_PRINTF(3, "HYST[%s]: Setting to HIDE\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
+#endif /* NODEBUG */
+      return HIDE_LINK;
+    }
+
+    /*
+     * otherwise, if L_LOST_LINK_time is expired and L_link_pending
+     * is set to "false", the link is advertised as described
+     * previously in section 6.
+     */
+  }
+
   if (entry->link_sym_timer) {
     return SYM_LINK;
   }
@@ -127,7 +168,6 @@ lookup_link_status(const struct link_entry *entry)
   return LOST_LINK;
 }
 
-
 /**
  * Find the "best" link status to a neighbor
  *
@@ -139,37 +179,30 @@ get_neighbor_status(const union olsr_ip_addr *address)
 {
   const union olsr_ip_addr *main_addr;
   struct interface *ifs;
-  struct tc_entry *tc;
 
   /* Find main address */
-  if (!(main_addr = olsr_lookup_main_addr_by_alias(address)))
+  if (!(main_addr = mid_lookup_main_addr(address)))
     main_addr = address;
 
-  /*
-   * Locate the hookup point.
-   */
-  tc = olsr_locate_tc_entry(main_addr);
-
   /* Loop trough local interfaces to check all possebilities */
-  OLSR_FOR_ALL_INTERFACES(ifs) {
-
-    struct mid_entry *aliases;
+  for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
+    struct mid_address *aliases;
     struct link_entry *lnk = lookup_link_entry(main_addr, NULL, ifs);
 
     if (lnk != NULL) {
       if (lookup_link_status(lnk) == SYM_LINK)
-       return SYM_LINK;
+        return SYM_LINK;
     }
 
-    /* Walk the aliases */
-    OLSR_FOR_ALL_TC_MID_ENTRIES(tc, aliases) {
+    /* Get aliases */
+    for (aliases = mid_lookup_aliases(main_addr); aliases != NULL; aliases = aliases->next_alias) {
 
-      lnk = lookup_link_entry(&aliases->mid_alias_addr, NULL, ifs);
+      lnk = lookup_link_entry(&aliases->alias, NULL, ifs);
       if (lnk && (lookup_link_status(lnk) == SYM_LINK)) {
-         return SYM_LINK;
+        return SYM_LINK;
       }
-    } OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, aliases);
-  } OLSR_FOR_ALL_INTERFACES_END(ifs);
+    }
+  }
 
   return 0;
 }
@@ -182,11 +215,13 @@ get_best_link_to_neighbor(const union olsr_ip_addr *remote)
 {
   const union olsr_ip_addr *main_addr;
   struct link_entry *walker, *good_link, *backup_link;
+  struct interface *tmp_if;
+  int curr_metric = MAX_IF_METRIC;
   olsr_linkcost curr_lcost = LINK_COST_BROKEN;
   olsr_linkcost tmp_lc;
 
   /* main address lookup */
-  main_addr = olsr_lookup_main_addr_by_alias(remote);
+  main_addr = mid_lookup_main_addr(remote);
 
   /* "remote" *already is* the main address */
   if (!main_addr) {
@@ -204,28 +239,66 @@ get_best_link_to_neighbor(const union olsr_ip_addr *remote)
     if (!ipequal(&walker->neighbor->neighbor_main_addr, main_addr))
       continue;
 
-    /* get the link cost */
-    tmp_lc = walker->linkcost;
+    if (olsr_cnf->lq_level == 0) {
 
-    /*
-     * is this link better than anything we had before ?
-     * use the requested remote interface address as a tie-breaker.
-     */
-    if ((tmp_lc < curr_lcost) ||
-        ((tmp_lc == curr_lcost) &&
-         ipequal(&walker->local_iface_addr, remote))) {
-
-      /* memorize the link quality */
-      curr_lcost = tmp_lc;
-
-      /* prefer symmetric links over asymmetric links */
-      if (lookup_link_status(walker) == SYM_LINK) {
-        good_link = walker;
-      } else {
-        backup_link = walker;
+      /*
+       * handle the non-LQ, RFC-compliant case
+       */
+
+      /*
+       * find the interface for the link.
+       * we select the link with the best local interface metric.
+       */
+      tmp_if = walker->if_name ? if_ifwithname(walker->if_name) : if_ifwithaddr(&walker->local_iface_addr);
+
+      if (!tmp_if) {
+        continue;
+      }
+
+      /*
+       * is this interface better than anything we had before ?
+       * use the requested remote interface address as a tie-breaker
+       */
+      if ((tmp_if->int_metric < curr_metric) || ((tmp_if->int_metric == curr_metric) && ipequal(&walker->local_iface_addr, remote))) {
+
+        /* memorize the interface's metric */
+        curr_metric = tmp_if->int_metric;
+
+        /* prefer symmetric links over asymmetric links */
+        if (lookup_link_status(walker) == SYM_LINK) {
+          good_link = walker;
+        } else {
+          backup_link = walker;
+        }
+      }
+    } else {
+
+      /*
+       * handle the LQ, non-RFC compliant case.
+       */
+
+      /* get the link cost */
+      tmp_lc = walker->linkcost;
+
+      /*
+       * is this link better than anything we had before ?
+       * use the requested remote interface address as a tie-breaker.
+       */
+      if ((tmp_lc < curr_lcost) || ((tmp_lc == curr_lcost) && ipequal(&walker->local_iface_addr, remote))) {
+
+        /* memorize the link quality */
+        curr_lcost = tmp_lc;
+
+        /* prefer symmetric links over asymmetric links */
+        if (lookup_link_status(walker) == SYM_LINK) {
+          good_link = walker;
+        } else {
+          backup_link = walker;
+        }
       }
     }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+  }
+  OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
 
   /*
    * if we haven't found any symmetric links, try to return an asymmetric link.
@@ -240,26 +313,32 @@ set_loss_link_multiplier(struct link_entry *entry)
   struct olsr_if *cfg_inter;
   struct olsr_lq_mult *mult;
   uint32_t val = 0;
+  union olsr_ip_addr null_addr;
+  struct ipaddr_str buf;
 
   /* find the interface for the link */
-  inter = if_ifwithaddr(&entry->local_iface_addr);
+  assert(entry->if_name);
+  inter = if_ifwithname(entry->if_name);
 
   /* find the interface configuration for the interface */
-  for (cfg_inter = olsr_cnf->interfaces; cfg_inter;
-       cfg_inter = cfg_inter->next) {
+  for (cfg_inter = olsr_cnf->interfaces; cfg_inter; cfg_inter = cfg_inter->next) {
     if (cfg_inter->interf == inter) {
       break;
     }
   }
+  assert(cfg_inter);
+
+  /* create a null address for comparison */
+  memset(&null_addr, 0, sizeof(union olsr_ip_addr));
 
   /* loop through the multiplier entries */
   for (mult = cfg_inter->cnf->lq_mult; mult != NULL; mult = mult->next) {
+
     /*
      * use the default multiplier only if there isn't any entry that
      * has a matching IP address.
      */
-    if ((val == 0 && ipequal(&mult->addr, &all_zero)) ||
-       ipequal(&mult->addr, &entry->neighbor_iface_addr)) {
+    if ((ipequal(&mult->addr, &null_addr) && val == 0) || ipequal(&mult->addr, &entry->neighbor_iface_addr)) {
       val = mult->value;
     }
   }
@@ -271,6 +350,9 @@ set_loss_link_multiplier(struct link_entry *entry)
 
   /* store the multiplier */
   entry->loss_link_multiplier = val;
+
+  OLSR_PRINTF(1, "Set linkloss multiplier for %s on %s to %d\n",
+      olsr_ip_to_string(&buf, &entry->neighbor_iface_addr), cfg_inter->name, val);
 }
 
 /*
@@ -279,6 +361,14 @@ set_loss_link_multiplier(struct link_entry *entry)
 static void
 olsr_delete_link_entry(struct link_entry *link)
 {
+  struct tc_edge_entry *tc_edge;
+
+  /* delete tc edges we made for SPF */
+  tc_edge = olsr_lookup_tc_edge(tc_myself, &link->neighbor_iface_addr);
+  if (tc_edge != NULL) {
+    olsr_delete_tc_edge_entry(tc_edge);
+  }
+
 
   /* Delete neighbor entry */
   if (link->neighbor->linkcount == 1) {
@@ -292,15 +382,12 @@ olsr_delete_link_entry(struct link_entry *link)
   link->link_timer = NULL;
   olsr_stop_timer(link->link_sym_timer);
   link->link_sym_timer = NULL;
+  olsr_stop_timer(link->link_hello_timer);
+  link->link_hello_timer = NULL;
   olsr_stop_timer(link->link_loss_timer);
   link->link_loss_timer = NULL;
-
   list_remove(&link->link_list);
 
-  /* Unlink Interfaces */
-  unlock_interface(link->inter);
-  link->inter = NULL;
-
   free(link->if_name);
   free(link);
 
@@ -308,10 +395,10 @@ olsr_delete_link_entry(struct link_entry *link)
 }
 
 /**
- * Delete all link entries matching a given interface id
+ * Delete all link entries matching a given interface address.
  */
 void
-olsr_delete_link_entry_by_if(const int int_index)
+olsr_delete_link_entry_by_ip(const union olsr_ip_addr *int_addr)
 {
   struct link_entry *link;
 
@@ -320,12 +407,14 @@ olsr_delete_link_entry_by_if(const int int_index)
   }
 
   OLSR_FOR_ALL_LINK_ENTRIES(link) {
-    if (int_index == link->inter->if_index) {
+    if (ipequal(int_addr, &link->local_iface_addr)) {
       olsr_delete_link_entry(link);
     }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  }
+  OLSR_FOR_ALL_LINK_ENTRIES_END(link);
 }
 
+
 /**
  * Callback for the link loss timer.
  */
@@ -340,10 +429,10 @@ olsr_expire_link_loss_timer(void *context)
   olsr_update_packet_loss_worker(link, true);
 
   /* next timeout in 1.0 x htime */
-  olsr_change_timer(link->link_loss_timer, link->loss_helloint,
-                   OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC);
+  olsr_change_timer(link->link_loss_timer, link->loss_helloint, OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC);
 }
 
+
 /**
  * Callback for the link SYM timer.
  */
@@ -353,15 +442,14 @@ olsr_expire_link_sym_timer(void *context)
   struct link_entry *link;
 
   link = (struct link_entry *)context;
-  link->link_sym_timer = NULL; /* be pedandic */
+  link->link_sym_timer = NULL;  /* be pedandic */
 
   if (link->prev_status != SYM_LINK) {
     return;
   }
 
   link->prev_status = lookup_link_status(link);
-  update_neighbor_status(link->neighbor,
-                        get_neighbor_status(&link->neighbor_iface_addr));
+  update_neighbor_status(link->neighbor, get_neighbor_status(&link->neighbor_iface_addr));
   changes_neighborhood = true;
 }
 
@@ -371,13 +459,26 @@ olsr_expire_link_sym_timer(void *context)
 void
 olsr_expire_link_hello_timer(void *context)
 {
+  struct ipaddr_str buf;
   struct link_entry *link;
 
   link = (struct link_entry *)context;
 
+  link->L_link_quality = olsr_hyst_calc_instability(link->L_link_quality);
+
+  OLSR_PRINTF(1, "HYST[%s] HELLO timeout %f\n", olsr_ip_to_string(&buf, &link->neighbor_iface_addr), (double)link->L_link_quality);
+
+  /* Update hello_timeout - NO SLACK THIS TIME */
+  olsr_change_timer(link->link_hello_timer, link->last_htime, OLSR_LINK_JITTER, OLSR_TIMER_PERIODIC);
+
+  /* Update hysteresis values */
+  olsr_process_hysteresis(link);
+
   /* update neighbor status */
-  update_neighbor_status(link->neighbor,
-                        get_neighbor_status(&link->neighbor_iface_addr));
+  update_neighbor_status(link->neighbor, get_neighbor_status(&link->neighbor_iface_addr));
+
+  /* Update seqno - not mentioned in the RFC... kind of a hack.. */
+  link->olsr_seqno++;
 }
 
 /**
@@ -389,7 +490,7 @@ olsr_expire_link_entry(void *context)
   struct link_entry *link;
 
   link = (struct link_entry *)context;
-  link->link_timer = NULL;     /* be pedandic */
+  link->link_timer = NULL;      /* be pedandic */
 
   olsr_delete_link_entry(link);
 }
@@ -397,12 +498,15 @@ olsr_expire_link_entry(void *context)
 /**
  * Set the link expiration timer.
  */
-static void
+void
 olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
 {
-  olsr_set_timer(&link->link_timer, rel_timer, OLSR_LINK_JITTER,
-                OLSR_TIMER_ONESHOT, &olsr_expire_link_entry, link,
-                 link_dead_timer_cookie->ci_id);
+  struct ipaddr_str buf;
+
+  OLSR_PRINTF(3, "reset link timer: %s = %u\n",
+    olsr_ip_to_string(&buf, &link->neighbor_iface_addr),
+    (unsigned int)(now_times + rel_timer/1000));
+  olsr_set_timer(&link->link_timer, rel_timer, OLSR_LINK_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_link_entry, link, 0);
 }
 
 /**
@@ -418,11 +522,8 @@ olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
  * @return the new link_entry
  */
 static struct link_entry *
-add_link_entry(const union olsr_ip_addr *local,
-               const union olsr_ip_addr *remote,
-              const union olsr_ip_addr *remote_main,
-              olsr_reltime vtime, olsr_reltime htime,
-               struct interface *local_if)
+add_link_entry(const union olsr_ip_addr *local, const union olsr_ip_addr *remote, const union olsr_ip_addr *remote_main,
+               olsr_reltime vtime, olsr_reltime htime, const struct interface *local_if)
 {
   struct link_entry *new_link;
   struct neighbor_entry *neighbor;
@@ -441,11 +542,9 @@ add_link_entry(const union olsr_ip_addr *local,
 #ifdef DEBUG
   {
     struct ipaddr_str localbuf, rembuf;
-    OLSR_PRINTF(1, "Adding %s=>%s to link set\n",
-               olsr_ip_to_string(&localbuf, local), olsr_ip_to_string(&rembuf,
-                                                                      remote));
+    OLSR_PRINTF(1, "Adding %s=>%s to link set\n", olsr_ip_to_string(&localbuf, local), olsr_ip_to_string(&rembuf, remote));
   }
-#endif
+#endif /* DEBUG */
 
   /* a new tuple is created with... */
   new_link = olsr_malloc_link_entry("new link entry");
@@ -453,15 +552,13 @@ add_link_entry(const union olsr_ip_addr *local,
   /* copy if_name, if it is defined */
   if (local_if->int_name) {
     size_t name_size = strlen(local_if->int_name) + 1;
-    new_link->if_name =
-      olsr_malloc(name_size, "target of if_name in new link entry");
+    new_link->if_name = olsr_malloc(name_size, "target of if_name in new link entry");
     strscpy(new_link->if_name, local_if->int_name, name_size);
   } else
     new_link->if_name = NULL;
 
-  /* shortcut to interface. */
+  /* shortcut to interface. XXX refcount */
   new_link->inter = local_if;
-  lock_interface(local_if);
 
   /*
    * L_local_iface_addr = Address of the interface
@@ -477,14 +574,26 @@ add_link_entry(const union olsr_ip_addr *local,
 
   new_link->prev_status = ASYM_LINK;
 
-  new_link->loss_helloint = htime;
+  /* HYSTERESIS */
+  if (olsr_cnf->use_hysteresis) {
+    new_link->L_link_pending = 1;
+    new_link->L_LOST_LINK_time = GET_TIMESTAMP(vtime);
+    olsr_update_hysteresis_hello(new_link, htime);
+    new_link->last_htime = htime;
+    new_link->olsr_seqno = 0;
+    new_link->olsr_seqno_valid = false;
+  }
+
+  new_link->L_link_quality = 0.0;
+
+  if (olsr_cnf->lq_level > 0) {
+    new_link->loss_helloint = htime;
 
-  olsr_set_timer(&new_link->link_loss_timer, htime + htime/2,
-   OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
-   &olsr_expire_link_loss_timer, new_link,
-                 link_loss_timer_cookie->ci_id);
+    olsr_set_timer(&new_link->link_loss_timer, htime + htime / 2, OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
+                   &olsr_expire_link_loss_timer, new_link, 0);
 
-  set_loss_link_multiplier(new_link);
+    set_loss_link_multiplier(new_link);
+  }
 
   new_link->linkcost = LINK_COST_BROKEN;
 
@@ -500,9 +609,8 @@ add_link_entry(const union olsr_ip_addr *local,
   if (!neighbor) {
 #ifdef DEBUG
     struct ipaddr_str buf;
-    OLSR_PRINTF(3, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n",
-               olsr_ip_to_string(&buf, remote_main));
-#endif
+    OLSR_PRINTF(3, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n", olsr_ip_to_string(&buf, remote_main));
+#endif /* DEBUG */
     neighbor = olsr_insert_neighbor_table(remote_main);
   }
 
@@ -512,7 +620,6 @@ add_link_entry(const union olsr_ip_addr *local,
   return new_link;
 }
 
-
 /**
  * Lookup the status of a link.
  *
@@ -528,7 +635,8 @@ check_neighbor_link(const union olsr_ip_addr *int_addr)
     if (ipequal(int_addr, &link->neighbor_iface_addr)) {
       return lookup_link_status(link);
     }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  }
+  OLSR_FOR_ALL_LINK_ENTRIES_END(link);
 
   return UNSPEC_LINK;
 }
@@ -542,29 +650,26 @@ check_neighbor_link(const union olsr_ip_addr *int_addr)
  * @return the link entry if found, NULL if not
  */
 struct link_entry *
-lookup_link_entry(const union olsr_ip_addr *remote,
-                 const union olsr_ip_addr *remote_main,
-                 const struct interface *local)
+lookup_link_entry(const union olsr_ip_addr *remote, const union olsr_ip_addr *remote_main, const struct interface *local)
 {
   struct link_entry *link;
 
   OLSR_FOR_ALL_LINK_ENTRIES(link) {
-    if (ipequal(remote, &link->neighbor_iface_addr) &&
-       (link->if_name ? !strcmp(link->if_name, local->int_name)
-        : ipequal(&local->ip_addr, &link->local_iface_addr)))
-    {
+    if (ipequal(remote, &link->neighbor_iface_addr)
+        && (link->if_name ? !strcmp(link->if_name, local->int_name) : ipequal(&local->ip_addr, &link->local_iface_addr))) {
       /* check the remote-main address only if there is one given */
-      if (NULL != remote_main && !ipequal(remote_main, &link->neighbor->neighbor_main_addr))
-      {
+      if (NULL != remote_main && !ipequal(remote_main, &link->neighbor->neighbor_main_addr)) {
         /* Neighbor has changed it's main_addr, update */
         struct ipaddr_str oldbuf, newbuf;
+
         OLSR_PRINTF(1, "Neighbor changed main_ip, updating %s -> %s\n",
-          olsr_ip_to_string(&oldbuf, &link->neighbor->neighbor_main_addr), olsr_ip_to_string(&newbuf, remote_main));
-        link->neighbor->neighbor_main_addr = *remote_main;
+                    olsr_ip_to_string(&oldbuf, &link->neighbor->neighbor_main_addr), olsr_ip_to_string(&newbuf, remote_main));
+        olsr_update_neighbor_main_addr(link->neighbor, remote_main);
       }
       return link;
     }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  }
+  OLSR_FOR_ALL_LINK_ENTRIES_END(link);
 
   return NULL;
 }
@@ -581,21 +686,17 @@ lookup_link_entry(const union olsr_ip_addr *remote,
  * @return the link_entry struct describing this link entry
  */
 struct link_entry *
-update_link_entry(const union olsr_ip_addr *local,
-                 const union olsr_ip_addr *remote,
-                 const struct lq_hello_message *message,
-                 struct interface *in_if)
+update_link_entry(const union olsr_ip_addr *local, const union olsr_ip_addr *remote, const struct hello_message *message,
+                  const struct interface *in_if)
 {
   struct link_entry *entry;
 
   /* Add if not registered */
-  entry =
-    add_link_entry(local, remote, &message->comm.orig, message->comm.vtime,
-                  message->htime, in_if);
+  entry = add_link_entry(local, remote, &message->source_addr, message->vtime, message->htime, in_if);
 
   /* Update ASYM_time */
-  entry->vtime = message->comm.vtime;
-  entry->ASYM_time = GET_TIMESTAMP(message->comm.vtime);
+  entry->vtime = message->vtime;
+  entry->ASYM_time = GET_TIMESTAMP(message->vtime);
 
   entry->prev_status = check_link_status(message, in_if);
 
@@ -608,42 +709,42 @@ update_link_entry(const union olsr_ip_addr *local,
   case (ASYM_LINK):
 
     /* L_SYM_time = current time + validity time */
-    olsr_set_timer(&entry->link_sym_timer, message->comm.vtime,
-                  OLSR_LINK_SYM_JITTER, OLSR_TIMER_ONESHOT,
-                  &olsr_expire_link_sym_timer, entry,
-                   link_sym_timer_cookie->ci_id);
+    olsr_set_timer(&entry->link_sym_timer, message->vtime, OLSR_LINK_SYM_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_link_sym_timer,
+                   entry, 0);
 
     /* L_time = L_SYM_time + NEIGHB_HOLD_TIME */
-    olsr_set_link_timer(entry, message->comm.vtime + NEIGHB_HOLD_TIME *
-                       MSEC_PER_SEC);
+    olsr_set_link_timer(entry, message->vtime + NEIGHB_HOLD_TIME * MSEC_PER_SEC);
+    break;
+  default:
     break;
-  default:;
   }
 
   /* L_time = max(L_time, L_ASYM_time) */
-  if (entry->link_timer && (entry->link_timer->timer_clock < entry->ASYM_time)) {
+  if (entry->link_timer == NULL || (entry->link_timer->timer_clock < entry->ASYM_time)) {
     olsr_set_link_timer(entry, TIME_DUE(entry->ASYM_time));
   }
 
+  /* Update hysteresis values */
+  if (olsr_cnf->use_hysteresis)
+    olsr_process_hysteresis(entry);
+
   /* Update neighbor */
   update_neighbor_status(entry->neighbor, get_neighbor_status(remote));
 
   return entry;
 }
 
-
 /**
  * Function that updates all registered pointers to
  * one neighbor entry with another pointer
  * Used by MID updates.
  *
- * @old the pointer to replace
- * @new the pointer to use instead of "old"
+ * @param old the pointer to replace
+ * @param new the pointer to use instead of "old"
  * @return the number of entries updated
  */
 int
-replace_neighbor_link_set(const struct neighbor_entry *old,
-                         struct neighbor_entry *new)
+replace_neighbor_link_set(const struct neighbor_entry *old, struct neighbor_entry *new)
 {
   struct link_entry *link;
   int retval = 0;
@@ -658,38 +759,39 @@ replace_neighbor_link_set(const struct neighbor_entry *old,
       link->neighbor = new;
       retval++;
     }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  }
+  OLSR_FOR_ALL_LINK_ENTRIES_END(link);
 
   return retval;
 }
 
-
 /**
  *Checks the link status to a neighbor by
  *looking in a received HELLO message.
  *
  *@param message the HELLO message to check
+ *@param in_if the incoming interface
  *
  *@return the link status
  */
 static int
-check_link_status(const struct lq_hello_message *message,
-                 const struct interface *in_if)
+check_link_status(const struct hello_message *message, const struct interface *in_if)
 {
   int ret = UNSPEC_LINK;
-  struct lq_hello_neighbor *neighbors;
+  struct hello_neighbor *neighbors;
 
-  neighbors = message->neigh;
+  neighbors = message->neighbors;
   while (neighbors) {
 
     /*
      * Note: If a neigh has 2 cards we can reach, the neigh
      * will send a Hello with the same IP mentined twice
      */
-    if (ipequal(&neighbors->addr, &in_if->ip_addr)) {
-      ret = neighbors->link_type;
+    if (ipequal(&neighbors->address, &in_if->ip_addr) &&
+        neighbors->link != UNSPEC_LINK) {
+      ret = neighbors->link;
       if (SYM_LINK == ret) {
-       break;
+        break;
       }
     }
     neighbors = neighbors->next;
@@ -698,53 +800,46 @@ check_link_status(const struct lq_hello_message *message,
   return ret;
 }
 
+#ifndef NODEBUG
 void
 olsr_print_link_set(void)
 {
-#ifndef NODEBUG
   /* The whole function makes no sense without it. */
   struct link_entry *walker;
-  const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
+  const int addrsize = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
 
-  OLSR_PRINTF(0,
-             "\n--- %s ---------------------------------------------------- LINKS\n\n",
-             olsr_wallclock_string());
-  OLSR_PRINTF(1, "%-*s  %-6s %-14s %s\n", addrsize, "IP address", "hyst",
-             "      LQ      ", "ETX");
+  OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- LINKS\n\n", olsr_wallclock_string());
+  OLSR_PRINTF(1, "%-*s  %-6s %-14s %s\n", addrsize, "IP address", "hyst", "      LQ      ", "ETX");
 
   OLSR_FOR_ALL_LINK_ENTRIES(walker) {
 
     struct ipaddr_str buf;
     struct lqtextbuffer lqbuffer1, lqbuffer2;
-    OLSR_PRINTF(1, "%-*s %-14s %s\n",
-               addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
-               get_link_entry_text(walker, '/', &lqbuffer1),
-               get_linkcost_text(walker->linkcost, false, &lqbuffer2));
+    OLSR_PRINTF(1, "%-*s  %5.3f  %-14s %s\n", addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+               (double)walker->L_link_quality, get_link_entry_text(walker, '/', &lqbuffer1), get_linkcost_text(walker->linkcost,
+                                                                                                        false, &lqbuffer2));
   } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
-#endif
 }
+#endif /* NODEBUG */
 
 /*
  * called for every LQ HELLO message.
  * update the timeout with the htime value from the message
  */
 void
-olsr_update_packet_loss_hello_int(struct link_entry *entry,
-                                 olsr_reltime loss_hello_int)
+olsr_update_packet_loss_hello_int(struct link_entry *entry, olsr_reltime loss_hello_int)
 {
   entry->loss_helloint = loss_hello_int;
 }
 
 void
-olsr_update_packet_loss(struct link_entry *entry)
+olsr_received_hello_handler(struct link_entry *entry)
 {
   olsr_update_packet_loss_worker(entry, false);
 
   /* timeout for the first lost packet is 1.5 x htime */
-  olsr_set_timer(&entry->link_loss_timer, entry->loss_helloint + entry->loss_helloint/2,
-                OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
-                &olsr_expire_link_loss_timer, entry,
-                 link_loss_timer_cookie->ci_id);
+  olsr_set_timer(&entry->link_loss_timer, entry->loss_helloint + entry->loss_helloint / 2, OLSR_LINK_LOSS_JITTER,
+                 OLSR_TIMER_PERIODIC, &olsr_expire_link_loss_timer, entry, 0);
 }
 
 /*