Handle degenerated LQ routing cases gracefully: edges to one-hop
authorThomas Lopatic <thomas@lopatic.de>
Thu, 17 Feb 2005 02:06:22 +0000 (02:06 +0000)
committerThomas Lopatic <thomas@lopatic.de>
Thu, 17 Feb 2005 02:06:22 +0000 (02:06 +0000)
neighbours to which we do not have a link any longer and routes via
interfaces that don't exist any longer because they are down. Select and
store the LQ multiplier when a new link is added.

src/link_set.c
src/link_set.h
src/lq_route.c

index 0175e05..777c505 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: link_set.c,v 1.49 2005/02/15 17:17:42 tlopatic Exp $
+ * $Id: link_set.c,v 1.50 2005/02/17 02:06:22 tlopatic Exp $
  */
 
 
@@ -316,8 +316,50 @@ get_best_link_to_neighbor(union olsr_ip_addr *remote)
   return good_link ? good_link : backup_link;
 }
 
+static void set_loss_link_multiplier(struct link_entry *entry)
+{
+  struct interface *inter;
+  struct olsr_if *cfg_inter;
+  struct olsr_lq_mult *mult;
+  float val = -1.0;
+  union olsr_ip_addr null_addr;
 
+  // find the interface for the link
 
+  inter = if_ifwithaddr(&entry->local_iface_addr);
+
+  // find the interface configuration for the interface
+
+  for (cfg_inter = olsr_cnf->interfaces; cfg_inter != NULL;
+       cfg_inter = cfg_inter->next)
+    if (cfg_inter->interf == inter)
+      break;
+
+  // 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 ((COMP_IP(&mult->addr, &null_addr) && val < 0.0) ||
+        COMP_IP(&mult->addr, &entry->neighbor_iface_addr))
+      val = mult->val;
+  }
+
+  // if we have not found an entry, then use the default multiplier
+
+  if (val < 0)
+    val = 1.0;
+
+  // store the multiplier
+
+  entry->loss_link_multiplier = val;
+}
 
 /**
  *Nothing mysterious here.
@@ -409,6 +451,8 @@ add_new_entry(union olsr_ip_addr *local, union olsr_ip_addr *remote, union olsr_
       new_link->loss_index = 0;
 
       memset(new_link->loss_bitmap, 0, sizeof (new_link->loss_bitmap));
+
+      set_loss_link_multiplier(new_link);
     }
 
   new_link->loss_link_quality = 0.0;
@@ -852,47 +896,6 @@ void olsr_print_link_set(void)
   }
 }
 
-static void multiply_link_quality(struct link_entry *entry)
-{
-  struct interface *inter;
-  struct olsr_if *cfg_inter;
-  struct olsr_lq_mult *mult;
-  float val = -1.0;
-  union olsr_ip_addr null_addr;
-
-  // find the interface for the link
-
-  inter = if_ifwithaddr(&entry->local_iface_addr);
-
-  // find the interface configuration for the interface
-
-  for (cfg_inter = olsr_cnf->interfaces; cfg_inter != NULL;
-       cfg_inter = cfg_inter->next)
-    if (cfg_inter->interf == inter)
-      break;
-
-  // 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 ((COMP_IP(&mult->addr, &null_addr) && val < 0.0) ||
-        COMP_IP(&mult->addr, &entry->neighbor_iface_addr))
-      val = mult->val;
-  }
-
-  // if we have found an entry, then multiply
-
-  if (val >= 0)
-    entry->loss_link_quality *= val;
-}
-
 static void update_packet_loss_worker(struct link_entry *entry, int lost)
 {
   unsigned char mask = 1 << (entry->loss_index & 7);
@@ -959,7 +962,7 @@ static void update_packet_loss_worker(struct link_entry *entry, int lost)
 
   // multiply the calculated link quality with the user-specified multiplier
 
-  multiply_link_quality(entry);
+  entry->loss_link_quality *= entry->loss_link_multiplier;
 
   // if the link quality has changed by more than 10 percent,
   // print the new link quality table
index 95d0260..1e2ce3b 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: link_set.h,v 1.21 2005/02/14 15:54:30 tlopatic Exp $
+ * $Id: link_set.h,v 1.22 2005/02/17 02:06:22 tlopatic Exp $
  */
 
 
@@ -85,6 +85,7 @@ struct link_entry
   int total_packets;
 
   double loss_link_quality;
+  double loss_link_multiplier;
 
   int loss_window_size;
   int loss_index;
index 0c8459a..efc90f5 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: lq_route.c,v 1.26 2005/02/16 14:44:44 tlopatic Exp $
+ * $Id: lq_route.c,v 1.27 2005/02/17 02:06:22 tlopatic Exp $
  */
 
 #include "defs.h"
@@ -328,6 +328,7 @@ void olsr_calculate_lq_routing_table(void)
   struct rt_entry *gw_rt, *hna_rt, *head_rt;
   struct neighbor_2_entry *neigh2;
   struct neighbor_list_entry *neigh_walker;
+  struct interface *inter;
 
   if (ipsize == 4)
     avl_comp = avl_comp_ipv4;
@@ -502,38 +503,39 @@ void olsr_calculate_lq_routing_table(void)
       continue;
     }
 
-#if defined linux && 0
-    /*
-     * on Linux we can add a new route for a destination before removing
-     * the old route, so frequent route updates are not a problem, as
-     * we never have a time window in which there isn't any route; hence
-     * we can use the more volatile ETX value instead of the hop count
-     */
+    // find the best link to the one-hop neighbour
 
-    hops = (int)vert->path_etx;
+    link = get_best_link_to_neighbor(&walker->addr);
 
-    if (hops > 100)
-      hops = 100;
-#endif
+    // we may see NULL here, if the one-hop neighbour is not in the
+    // link and neighbour sets any longer, but we have derived an edge
+    // between us and the one-hop neighbour from the TC set
 
-    // add a route to the main address of the destination node
+    if (link != NULL)
+    {
+      // find the interface for the found link
 
-    link = get_best_link_to_neighbor(&walker->addr);
+      inter = if_ifwithaddr(&link->local_iface_addr);
 
-    olsr_insert_routing_table(&vert->addr,
-                             &link->neighbor_iface_addr,
-                             if_ifwithaddr(&link->local_iface_addr),
-                              hops);
+      // we may see NULL here if the interface is down, but we have
+      // links that haven't timed out, yet
 
-    // add routes to the remaining interfaces of the destination node
+      if (inter != NULL)
+      {
+        // add a route to the main address of the destination node, if
+        // we haven't already added it above
 
-    for (mid_walker = mid_lookup_aliases(&vert->addr); mid_walker != NULL;
-         mid_walker = mid_walker->next_alias)
-    {
-      olsr_insert_routing_table(&mid_walker->alias,
-                                &link->neighbor_iface_addr,
-                                if_ifwithaddr(&link->local_iface_addr),
-                                hops);
+        olsr_insert_routing_table(&vert->addr, &link->neighbor_iface_addr,
+                                  inter, hops);
+
+        // add routes to the remaining interfaces of the destination node,
+        // if we haven't already added it above
+
+        for (mid_walker = mid_lookup_aliases(&vert->addr); mid_walker != NULL;
+             mid_walker = mid_walker->next_alias)
+          olsr_insert_routing_table(&mid_walker->alias,
+                                    &link->neighbor_iface_addr, inter, hops);
+      }
     }
   }
 
@@ -561,6 +563,16 @@ void olsr_calculate_lq_routing_table(void)
     if (hna_gw == NULL)
       continue;
 
+    // find route to the node
+
+    gw_rt = olsr_lookup_routing_table(&hna_gw->A_gateway_addr);
+
+    // maybe we haven't found a link or an interface for the gateway above
+    // and hence haven't added a route - skip the HNA in this case
+
+    if (gw_rt == NULL)
+      continue;
+
     // loop through the node's HNAs
 
     for (hna = hna_gw->networks.next; hna != &hna_gw->networks;
@@ -571,18 +583,6 @@ void olsr_calculate_lq_routing_table(void)
       if (olsr_lookup_routing_table(&hna->A_network_addr) != NULL)
         continue;
 
-      // find route to the node
-
-      gw_rt = olsr_lookup_routing_table(&hna_gw->A_gateway_addr);
-
-      // should never happen as we only process reachable nodes
-
-      if (gw_rt == NULL)
-      {
-        fprintf(stderr, "LQ HNA processing: Gateway without a route.");
-        continue;
-      }
-
       // create route for the HNA
 
       hna_rt = olsr_malloc(sizeof(struct rt_entry), "LQ HNA route entry");