More fixes for TC production in MPR environments
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 15 Feb 2017 10:18:22 +0000 (11:18 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 15 Feb 2017 10:18:22 +0000 (11:18 +0100)
src-plugins/nhdp/nhdp/nhdp_db.c
src-plugins/nhdp/nhdp/nhdp_db.h
src-plugins/nhdp/nhdp/nhdp_domain.c
src-plugins/nhdp/nhdp/nhdp_domain.h
src-plugins/nhdp/nhdp/nhdp_reader.c
src-plugins/nhdp/nhdp/nhdp_writer.c
src-plugins/olsrv2/olsrv2/olsrv2.c
src-plugins/olsrv2/olsrv2/olsrv2_routing.c

index 8199189..2c099de 100644 (file)
@@ -275,13 +275,14 @@ nhdp_db_neighbor_remove(struct nhdp_neighbor *neigh) {
     }
   }
 
+  if (was_mpr) {
+    /* all domains might have changed */
+    nhdp_domain_recalculate_mpr(NULL, neigh);
+  }
+
   /* remove from global list and free memory */
   list_remove(&neigh->_global_node);
   oonf_class_free(&_neigh_info, neigh);
-
-  if (was_mpr) {
-    nhdp_domain_recalculate_mpr(true);
-  }
 }
 
 /**
@@ -854,7 +855,8 @@ nhdp_db_link_update_status(struct nhdp_link *lnk) {
   if (old_status != lnk->status) {
     /* link status was changed */
     lnk->last_status_change = oonf_clock_getNow();
-    nhdp_domain_recalculate_mpr(true);
+    nhdp_domain_recalculate_metrics(NULL, lnk->neigh);
+    nhdp_domain_recalculate_mpr(NULL, lnk->neigh);
 
     /* trigger change event */
     oonf_class_event(&_link_info, lnk, OONF_OBJECT_CHANGED);
@@ -1049,20 +1051,10 @@ _cb_link_heard(struct oonf_timer_instance *ptr) {
 static void
 _cb_link_symtime(struct oonf_timer_instance *ptr) {
   struct nhdp_link *lnk;
-  struct nhdp_neighbor_domaindata *data;
-  struct nhdp_domain *domain;
 
   lnk = container_of(ptr, struct nhdp_link, sym_time);
   OONF_DEBUG(LOG_NHDP, "Link Symtime fired: 0x%0zx", (size_t)lnk);
   nhdp_db_link_update_status(lnk);
-
-  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-    data = nhdp_domain_get_neighbordata(domain, lnk->neigh);
-    if (data->neigh_is_mpr) {
-      nhdp_domain_recalculate_mpr(false);
-      return;
-    }
-  }
 }
 
 /**
index e058316..7b95e86 100644 (file)
@@ -215,6 +215,9 @@ struct nhdp_link {
   /*! Willingness of neighbor for flooding data */
   uint8_t flooding_willingness;
 
+  /*! true if the neighbor has been selected as a MPR by this router */
+  bool _neigh_was_flooding_mpr;
+
   /*! internal field for NHDP processing */
   int _process_count;
 
index c35e7ab..0339620 100644 (file)
@@ -70,10 +70,11 @@ static void _remove_mpr(struct nhdp_domain *);
 static void _cb_update_everyone_routing_mpr(struct nhdp_domain *domain);
 static void _cb_update_everyone_flooding_mpr(struct nhdp_domain *domain);
 
-static bool _recalculate_neighbor_metrics(struct nhdp_domain *domain);
 static bool _recalculate_neighbor_metric(struct nhdp_domain *domain,
         struct nhdp_neighbor *neigh);
-static bool _recalculate_mpr_set(struct nhdp_domain *domain);
+static bool _recalculate_routing_mpr_set(struct nhdp_domain *domain,
+    struct nhdp_neighbor *neigh);
+static bool _recalculate_flooding_mpr_set(void);
 
 static const char *_link_to_string(struct nhdp_metric_str *, uint32_t);
 static const char *_path_to_string(struct nhdp_metric_str *, uint32_t, uint8_t);
@@ -487,49 +488,102 @@ nhdp_domain_process_metric_2hoptlv(struct nhdp_domain *domain,
 }
 
 /**
- * This will trigger a MPR set recalculation.
- * @param force_change force a MPR recalculation and dijkstra trigger
- *    even if the existing neighbor set didn't change
+ * This will trigger a metric recalculation
+ * @param domain NHDP domain of metric change, NULL for all domains
+ * return true if metric changed, false otherwise
  */
-void
-nhdp_domain_recalculate_mpr(bool force_change) {
+static bool
+_recalculate_metrics(struct nhdp_domain *domain, struct nhdp_neighbor *neigh, bool trigger) {
   struct nhdp_domain_listener *listener;
-  struct nhdp_domain *domain;
-
   bool changed_metric;
-  bool changed_mpr;
-
-  list_for_each_element(&_domain_list, domain, _node) {
-    OONF_INFO(LOG_NHDP, "Recalculating MPR set for domain %u", domain->index);
-    changed_metric = false;
-    changed_mpr = false;
 
-    /* recalculate the neighbor metrics and see if they changed */
-    changed_metric = _recalculate_neighbor_metrics(domain);
+  changed_metric = false;
 
-    if (changed_metric) {
-      /* recalculate routing MPRs */
-      changed_mpr = _recalculate_mpr_set(domain);
+  if (trigger) {
+    OONF_DEBUG(LOG_NHDP, "Recalculating metrics set for domain %d",
+        domain ? domain->index : -1);
+  }
 
-      if (domain->ext == _flooding_domain.ext && domain->mpr->update_flooding_mpr) {
-        /* recalculating flooding MPR */
-        domain->mpr->update_flooding_mpr(&_flooding_domain);
-      }
+  if (!domain) {
+    list_for_each_element(&_domain_list, domain, _node) {
+      changed_metric |= _recalculate_metrics(domain, neigh, false);
+    }
+  }
+  else if (!neigh) {
+    list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
+      changed_metric |= _recalculate_neighbor_metric(domain, neigh);
     }
+  }
+  else {
+    changed_metric |= _recalculate_neighbor_metric(domain, neigh);
+  }
 
+  if (trigger && changed_metric) {
     list_for_each_element(&_domain_listener_list, listener, _node) {
       /* trigger domain listeners */
-      if ((force_change || changed_metric) && listener->metric_update) {
+      if (listener->metric_update) {
         listener->metric_update(domain);
       }
-      if ((force_change || changed_mpr) && listener->mpr_update) {
+    }
+  }
+
+  if (trigger) {
+    OONF_INFO(LOG_NHDP, "Metrics changed for domain %d: %s",
+        domain ? domain->index : -1, changed_metric ? "true" : "false");
+  }
+  return changed_metric;
+}
+
+bool
+nhdp_domain_recalculate_metrics(struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
+  return _recalculate_metrics(domain, neigh, true);
+}
+
+static bool
+_recalculate_mpr(struct nhdp_domain *domain, struct nhdp_neighbor *neigh, bool trigger) {
+  struct nhdp_domain_listener *listener;
+  bool changed_mpr;
+
+  if (trigger) {
+    OONF_DEBUG(LOG_NHDP, "Recalculating MPR set for domain %d",
+        domain ? domain->index : -1);
+  }
+
+  changed_mpr = false;
+  if (!domain) {
+    list_for_each_element(&_domain_list, domain, _node) {
+      changed_mpr |= _recalculate_mpr(domain, neigh, false);
+    }
+    changed_mpr |= _recalculate_mpr(&_flooding_domain, neigh, false);
+  }
+  else {
+    if (&_flooding_domain == domain) {
+      changed_mpr = _recalculate_flooding_mpr_set();
+    }
+    else {
+      changed_mpr = _recalculate_routing_mpr_set(domain, neigh);
+    }
+  }
+
+  if (trigger && changed_mpr) {
+    list_for_each_element(&_domain_listener_list, listener, _node) {
+      /* trigger domain listeners */
+      if (listener->mpr_update) {
         listener->mpr_update(domain);
       }
     }
+  }
 
-    OONF_INFO(LOG_NHDP, "domain %u: metric_change=%s, mpr_changed=%s",
-        domain->index, changed_metric ? "true" : "false", changed_mpr ? "true" : "false");
+  if (trigger) {
+    OONF_INFO(LOG_NHDP, "MPR changed for domain %d: %s",
+        domain ? domain->index : -1, changed_mpr ? "true" : "false");
   }
+  return changed_mpr;
+}
+
+bool
+nhdp_domain_recalculate_mpr(struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
+  return _recalculate_mpr(domain, neigh, true);
 }
 
 /**
@@ -899,42 +953,46 @@ nhdp_domain_get_listener_list(void) {
   return &_domain_listener_list;
 }
 
-/**
- * Recalculate the neighbor metrics of a NHDP domain
- * @param domain NHDP domain
- * @return if neighbor metric or two-hop link metric changed
- */
 static bool
-_recalculate_neighbor_metrics(struct nhdp_domain *domain) {
-  struct nhdp_neighbor *neigh;
-  bool changed;
+_recalculate_flooding_mpr_set(void) {
+  struct nhdp_link *lnk;
 
-  /* recalculate the neighbor metrics and see if they changed */
-  changed = false;
-  list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
-    changed |= _recalculate_neighbor_metric(domain, neigh);
+  list_for_each_element(nhdp_db_get_link_list(), lnk, _global_node) {
+    lnk->_neigh_was_flooding_mpr = lnk->neigh_is_flooding_mpr;
   }
 
-  if (changed) {
-    OONF_DEBUG(LOG_NHDP, "Domain ext %u metric changed", domain->ext);
+  _flooding_domain.mpr->update_flooding_mpr(&_flooding_domain);
+
+  list_for_each_element(nhdp_db_get_link_list(), lnk, _global_node) {
+    if (lnk->_neigh_was_flooding_mpr != lnk->neigh_is_flooding_mpr) {
+      OONF_DEBUG(LOG_NHDP, "Flooding domain MPR set changed");
+      return true;
+    }
   }
-  return changed;
+  return false;
 }
 
 /**
  * Recalculate the MPR set of a NHDP domain
  * @param domain nhdp domain
+ * @param neigh only recalculate if this neighbor is MPR
  * @return true if the MPR set changed
  */
 static bool
-_recalculate_mpr_set(struct nhdp_domain *domain) {
-  struct nhdp_neighbor *neigh;
+_recalculate_routing_mpr_set(struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
   struct nhdp_neighbor_domaindata *neighdata;
 
   if (!domain->mpr->update_routing_mpr) {
     return false;
   }
 
+  if (neigh) {
+    neighdata = nhdp_domain_get_neighbordata(domain, neigh);
+    if (!neighdata->neigh_is_mpr) {
+      return false;
+    }
+  }
+
   /* remember old MPR set */
   list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
     neighdata = nhdp_domain_get_neighbordata(domain, neigh);
index 5497acf..0c4012f 100644 (file)
@@ -231,13 +231,15 @@ struct nhdp_domain {
 struct nhdp_domain_listener {
     /**
      * Callback to inform about a NHDP neighbor MPR update
-     * @param domain NHDP domain of which the MPR set changed
+     * @param domain NHDP domain of which the MPR set changed,
+     *   NULL for all domains
      */
     void (*mpr_update)(struct nhdp_domain *domain);
 
     /**
      * Callback to inform about a NHDP neighbor metric update
-     * @param domain NHDP domain of which the metric changed
+     * @param domain NHDP domain of which the metric changed,
+     *   NULL for all domains
      */
     void (*metric_update)(struct nhdp_domain *domain);
 
@@ -295,9 +297,6 @@ EXPORT void nhdp_domain_process_metric_linktlv(struct nhdp_domain *,
 EXPORT void nhdp_domain_process_metric_2hoptlv(struct nhdp_domain *d,
     struct nhdp_l2hop *l2hop, const uint8_t *value);
 
-EXPORT void nhdp_domain_recalculate_mpr(bool force_change);
-EXPORT bool nhdp_domain_node_is_mpr(void);
-
 EXPORT size_t nhdp_domain_process_mprtypes_tlv(
     uint8_t *mprtypes, size_t mprtypes_size,
     struct rfc5444_reader_tlvblock_entry *tlv);
@@ -316,6 +315,12 @@ EXPORT size_t nhdp_domain_encode_willingness_tlvvalue(
 
 EXPORT bool nhdp_domain_set_incoming_metric(
     struct nhdp_domain_metric *metric, struct nhdp_link *lnk, uint32_t metric_in);
+EXPORT bool nhdp_domain_recalculate_metrics(
+    struct nhdp_domain *domain, struct nhdp_neighbor *neigh);
+
+EXPORT bool nhdp_domain_node_is_mpr(void);
+EXPORT bool nhdp_domain_recalculate_mpr(
+    struct nhdp_domain *domain, struct nhdp_neighbor *neigh);
 
 EXPORT struct list_entity *nhdp_domain_get_list(void);
 EXPORT struct list_entity *nhdp_domain_get_listener_list(void);
index c11f6fa..f9b119c 100644 (file)
@@ -976,8 +976,8 @@ _cb_msg_pass2_end(struct rfc5444_reader_tlvblock_context *context, bool dropped)
   /* update link status */
   nhdp_db_link_update_status(_current.link);
 
-  /* update MPR sets and link metrics */
-  nhdp_domain_recalculate_mpr(false);
+  /* update link metrics */
+  nhdp_domain_recalculate_metrics(NULL, _current.neighbor);
 
   return RFC5444_OKAY;
 }
index 6c32c75..8b0a17e 100644 (file)
@@ -172,7 +172,7 @@ nhdp_writer_send_hello(struct nhdp_interface *ninterf) {
   OONF_DEBUG(LOG_NHDP_W, "Sending Hello to interface %s",
       nhdp_interface_get_name(ninterf));
 
-  nhdp_domain_recalculate_mpr(false);
+  nhdp_domain_recalculate_mpr(NULL, NULL);
 
   /* store NHDP interface */
   _nhdp_if = ninterf;
index b229f48..d79a2cd 100644 (file)
@@ -109,6 +109,9 @@ struct _config {
   /*! olsrv2 p_hold_time */
   uint64_t p_hold_time;
 
+  /*! olsrv2 factor of a_hold_time in terms of tc_intervals */
+  uint64_t a_hold_time_factor;
+
   /*! decides NHDP routable status */
   bool nhdp_routable;
 
@@ -185,6 +188,8 @@ static struct cfg_schema_entry _olsrv2_entries[] = {
     "Holdtime for forwarding set information", 100),
   CFG_MAP_CLOCK_MIN(_config, p_hold_time, "processing_hold_time", "300.0",
     "Holdtime for processing set information", 100),
+  CFG_MAP_INT64_MINMAX(_config, a_hold_time_factor, "advertisement_hold_time_factor", "3",
+    "Holdtime for TC advertisements as a factor of TC interval time", false, false, 1, 255),
   CFG_MAP_BOOL(_config, nhdp_routable, "nhdp_routable", "no",
     "Decides if NHDP interface addresses"
     " are routed to other nodes. 'true' means the 'routable_acl' parameter"
@@ -235,6 +240,9 @@ static struct oonf_subsystem _olsrv2_subsystem = {
 };
 DECLARE_OONF_PLUGIN(_olsrv2_subsystem);
 
+/*! last time a TC was advertised because of MPR or LANs */
+static uint64_t _unadvertised_tc_count;
+
 static struct _config _olsrv2_config;
 
 /* timer for TC generation */
@@ -746,6 +754,13 @@ _parse_lan_array(struct cfg_named_section *section, bool add) {
 static void
 _cb_generate_tc(struct oonf_timer_instance *ptr __attribute__((unused))) {
   if (nhdp_domain_node_is_mpr() || !avl_is_empty(olsrv2_lan_get_tree())) {
+    _unadvertised_tc_count = 0;
+  }
+  else {
+    _unadvertised_tc_count++;
+  }
+
+  if (_unadvertised_tc_count <= _olsrv2_config.a_hold_time_factor) {
     olsrv2_writer_send_tc();
   }
 }
index cc99999..f834d8c 100644 (file)
@@ -455,8 +455,9 @@ olsrv2_routing_get_filter_list(void) {
  */
 static void
 _cb_mpr_update(struct nhdp_domain *domain) {
-  OONF_INFO(LOG_OLSRV2_ROUTING, "MPR update for domain %u", domain->index);
+  OONF_INFO(LOG_OLSRV2, "MPR update for domain %u", domain->index);
 
+  _update_ansn = true;
   _domain_changed[domain->index] = true;
   olsrv2_routing_trigger_update();
 }
@@ -467,7 +468,7 @@ _cb_mpr_update(struct nhdp_domain *domain) {
  */
 static void
 _cb_metric_update(struct nhdp_domain *domain) {
-  OONF_INFO(LOG_OLSRV2_ROUTING, "Metric update for domain %u", domain->index);
+  OONF_INFO(LOG_OLSRV2, "Metric update for domain %u", domain->index);
 
   _update_ansn = true;
   _domain_changed[domain->index] = true;