Merge branch 'master' into mpr_rework
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 16 Feb 2017 07:54:09 +0000 (08:54 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 16 Feb 2017 07:54:09 +0000 (08:54 +0100)
22 files changed:
src-plugins/nhdp/constant_metric/constant_metric.c
src-plugins/nhdp/ff_dat_metric/ff_dat_metric.c
src-plugins/nhdp/mpr/mpr.c
src-plugins/nhdp/mpr/neighbor-graph-flooding.c
src-plugins/nhdp/mpr/neighbor-graph-routing.c
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/nhdp/nhdpinfo/nhdpinfo.c
src-plugins/olsrv2/netjsoninfo/netjsoninfo.c
src-plugins/olsrv2/olsrv2/olsrv2.c
src-plugins/olsrv2/olsrv2/olsrv2_internal.h
src-plugins/olsrv2/olsrv2/olsrv2_reader.c
src-plugins/olsrv2/olsrv2/olsrv2_routing.c
src-plugins/olsrv2/olsrv2/olsrv2_routing.h
src-plugins/olsrv2/olsrv2/olsrv2_tc.c
src-plugins/olsrv2/olsrv2/olsrv2_writer.c
src-plugins/subsystems/oonf_class.h
src/olsrd2/CMakeLists.txt

index c8bbc7c..393aace 100644 (file)
@@ -286,9 +286,6 @@ _cb_set_linkcost(struct oonf_timer_instance *ptr __attribute__((unused))) {
       nhdp_domain_set_incoming_metric(&_constant_metric_handler, lnk, RFC7181_METRIC_INFINITE);
     }
   }
-
-  /* update neighbor metrics */
-  nhdp_domain_neighborhood_changed();
 }
 
 /**
index d26c316..89def37 100644 (file)
@@ -638,16 +638,12 @@ _cb_dat_sampling(struct oonf_timer_instance *ptr) {
   uint32_t missing_intervals;
   size_t i;
   int rx_bitrate;
-  bool change_happened;
-
   struct netaddr_str nbuf;
 
   ifconfig = container_of(ptr, struct ff_dat_if_config, _sampling_timer);
 
   OONF_DEBUG(LOG_FF_DAT, "Calculate Metric from sampled data");
 
-  change_happened = false;
-
   list_for_each_element(nhdp_db_get_link_list(), lnk, _global_node) {
     if (oonf_class_get_extension(&_nhdpif_extenstion, lnk->local_if) != ifconfig) {
       continue;
@@ -735,7 +731,7 @@ _cb_dat_sampling(struct oonf_timer_instance *ptr) {
     }
 
     /* set metric for incoming link */
-    change_happened |= nhdp_domain_set_incoming_metric(
+    nhdp_domain_set_incoming_metric(
         &_datff_handler, lnk, metric_value);
 
     OONF_DEBUG(LOG_FF_DAT, "New sampling rate for link %s (%s):"
@@ -752,11 +748,6 @@ _cb_dat_sampling(struct oonf_timer_instance *ptr) {
     ldata->buckets[ldata->activePtr].received = 0;
     ldata->buckets[ldata->activePtr].total = 0;
   }
-
-  /* update neighbor metrics */
-  if (change_happened) {
-    nhdp_domain_neighborhood_changed();
-  }
 }
 
 /**
index fa35d28..6e49148 100644 (file)
@@ -74,7 +74,8 @@
 static void _early_cfg_init(void);
 static int _init(void);
 static void _cleanup(void);
-static void _cb_update_mpr(void);
+static void _cb_update_routing_mpr(struct nhdp_domain *);
+static void _cb_update_flooding_mpr(struct nhdp_domain *);
 
 #ifndef NDEBUG
 static void _validate_mpr_set(
@@ -101,7 +102,8 @@ DECLARE_OONF_PLUGIN(_nhdp_mpr_subsystem);
 
 static struct nhdp_domain_mpr _mpr_handler = {
   .name = OONF_MPR_SUBSYSTEM,
-  .update_mpr = _cb_update_mpr,
+  .update_routing_mpr = _cb_update_routing_mpr,
+  .update_flooding_mpr = _cb_update_flooding_mpr,
 };
 
 /* logging sources for NHDP subsystem */
@@ -168,7 +170,7 @@ _update_nhdp_flooding(struct neighbor_graph *graph) {
         &current_link->neigh->originator,
         current_mpr_node, _avl_node);
     if (current_mpr_node != NULL) {
-      current_link->neigh->neigh_is_flooding_mpr = true;
+      current_link->neigh_is_flooding_mpr = true;
     }
   }
 }
@@ -184,33 +186,26 @@ _clear_nhdp_flooding(void) {
 //  OONF_DEBUG(LOG_MPR, "Updating FLOODING MPRs");
 
   list_for_each_element(nhdp_db_get_link_list(), current_link, _global_node) {
-    current_link->neigh->neigh_is_flooding_mpr = false;
+    current_link->neigh_is_flooding_mpr = false;
   }
 }
 
 static void
-_update_flooding_mpr(void) {
+_cb_update_flooding_mpr(struct nhdp_domain *domain) {
   struct mpr_flooding_data flooding_data;
 
   memset(&flooding_data, 0, sizeof(flooding_data));
   
-  if (nhdp_domain_get_flooding()->mpr != &_mpr_handler) {
-    /* we are not the flooding mpr */
-    return;
-  }
-
   _clear_nhdp_flooding();
   avl_for_each_element(nhdp_interface_get_tree(), flooding_data.current_interface, _node) {
     OONF_DEBUG(LOG_MPR, "*** Calculate flooding MPRs for interface %s ***",
         nhdp_interface_get_name(flooding_data.current_interface));
     
-    mpr_calculate_neighbor_graph_flooding(
-        nhdp_domain_get_flooding(), &flooding_data);
-    mpr_calculate_mpr_rfc7181(nhdp_domain_get_flooding(),
-        &flooding_data.neigh_graph);
+    mpr_calculate_neighbor_graph_flooding(domain, &flooding_data);
+    mpr_calculate_mpr_rfc7181(domain, &flooding_data.neigh_graph);
     mpr_print_sets(&flooding_data.neigh_graph);
 #ifndef NDEBUG
-    _validate_mpr_set(nhdp_domain_get_flooding(), &flooding_data.neigh_graph);
+    _validate_mpr_set(domain, &flooding_data.neigh_graph);
 #endif
     _update_nhdp_flooding(&flooding_data.neigh_graph);
     mpr_clear_neighbor_graph(&flooding_data.neigh_graph);
@@ -219,44 +214,24 @@ _update_flooding_mpr(void) {
 }
 
 static void
-_update_routing_mpr(void) {
+_cb_update_routing_mpr(struct nhdp_domain *domain) {
   struct neighbor_graph routing_graph;
-  struct nhdp_domain *domain;
 
-  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-    if (domain->mpr != &_mpr_handler) {
-      /* we are not the routing MPR for this domain */
-      continue;
-    }
-    OONF_DEBUG(LOG_MPR, "*** Calculate routing MPRs for domain %u ***", domain->index);
+  if (domain->mpr != &_mpr_handler) {
+    /* we are not the routing MPR for this domain */
+    return;
+  }
+  OONF_DEBUG(LOG_MPR, "*** Calculate routing MPRs for domain %u ***", domain->index);
     
-    memset(&routing_graph, 0, sizeof(routing_graph));
-    mpr_calculate_neighbor_graph_routing(domain, &routing_graph);
-    mpr_calculate_mpr_rfc7181(domain, &routing_graph);
-    mpr_print_sets(&routing_graph);
+  memset(&routing_graph, 0, sizeof(routing_graph));
+  mpr_calculate_neighbor_graph_routing(domain, &routing_graph);
+  mpr_calculate_mpr_rfc7181(domain, &routing_graph);
+  mpr_print_sets(&routing_graph);
 #ifndef NDEBUG
-    _validate_mpr_set(domain, &routing_graph);
+  _validate_mpr_set(domain, &routing_graph);
 #endif
-    _update_nhdp_routing(&routing_graph);
-    mpr_clear_neighbor_graph(&routing_graph);
-  } 
-  
-}
-
-/**
- * Callback triggered when an MPR update is required
- */
-static void
-_cb_update_mpr(void) {
-  OONF_DEBUG(LOG_MPR, "Recalculating MPRs");
-
-  /* calculate flooding MPRs */
-  _update_flooding_mpr();
-  
-  /* calculate routing MPRs */
-  _update_routing_mpr();
-
-  OONF_DEBUG(LOG_MPR, "Finished recalculating MPRs");
+  _update_nhdp_routing(&routing_graph);
+  mpr_clear_neighbor_graph(&routing_graph);
 }
 
 #ifndef NDEBUG
@@ -279,17 +254,24 @@ _validate_mpr_set(const struct nhdp_domain *domain, struct neighbor_graph *graph
   /* 
    * First property: If x in N1 has W(x) = WILL_ALWAYS then x is in M. 
    */
-  avl_for_each_element(&graph->set_n1, node_n1,
-                       _avl_node)
-  {
-    if (node_n1->neigh->flooding_willingness
+  avl_for_each_element(&graph->set_n1, node_n1, _avl_node) {
+    if (domain == nhdp_domain_get_flooding_domain()) {
+      if (node_n1->link->flooding_willingness
             == RFC7181_WILLINGNESS_ALWAYS) {
-      assert(mpr_is_mpr(graph, &node_n1->addr));
+        assert(mpr_is_mpr(graph, &node_n1->addr));
+      }
+    }
+    else {
+      struct nhdp_neighbor_domaindata *neighdata;
+
+      neighdata = nhdp_domain_get_neighbordata(domain, node_n1->neigh);
+      if (neighdata->willingness == RFC7181_WILLINGNESS_ALWAYS) {
+        assert(mpr_is_mpr(graph, &node_n1->addr));
+      }
     }
   }
 
-  avl_for_each_element(&graph->set_n2, n2_addr, _avl_node)
-  {
+  avl_for_each_element(&graph->set_n2, n2_addr, _avl_node) {
     d_y_n1 = mpr_calculate_d_of_y_s(domain, graph, n2_addr, &graph->set_n1);
     d_y_mpr = mpr_calculate_d_of_y_s(domain, graph, n2_addr, &graph->set_mpr);
     
index c6b9fb6..c31e581 100644 (file)
@@ -120,7 +120,7 @@ static bool
 _is_allowed_link_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface, struct nhdp_link *lnk) {
   if (_is_reachable_link_tuple(domain, current_interface, lnk)
-      && lnk->neigh->flooding_willingness > RFC7181_WILLINGNESS_NEVER) {
+      && lnk->flooding_willingness > RFC7181_WILLINGNESS_NEVER) {
     return true;
   }
   return false;
@@ -289,7 +289,7 @@ _calculate_n2(const struct nhdp_domain *domain, struct mpr_flooding_data *data)
 static uint32_t
 _get_willingness_n1(const struct nhdp_domain *domain __attribute__((unused)),
     struct n1_node *node) {
-  return node->neigh->flooding_willingness;
+  return node->link->flooding_willingness;
 }
 
 void
index 6cc6a85..44e4628 100644 (file)
@@ -267,6 +267,7 @@ _calculate_n1(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   
   list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
     // Reset temporary selection state 
+
     neigh->selection_is_mpr = false;
     if (_is_allowed_neighbor_tuple(domain, neigh)) {
       OONF_DEBUG(LOG_MPR, "Add neighbor %s in: %u", netaddr_to_string(&buf1, &neigh->originator),
index c444dee..55d48d8 100644 (file)
@@ -232,11 +232,14 @@ nhdp_db_neighbor_add(void) {
  */
 void
 nhdp_db_neighbor_remove(struct nhdp_neighbor *neigh) {
+  struct nhdp_neighbor_domaindata *neighdata;
   struct nhdp_naddr *naddr, *na_it;
   struct nhdp_link *lnk, *l_it;
+  struct nhdp_domain *domain;
 #ifdef OONF_LOG_DEBUG_INFO
   struct netaddr_str nbuf;
 #endif
+  bool was_mpr;
 
   OONF_DEBUG(LOG_NHDP, "Remove Neighbor: 0x%0zx (%s)",
       (size_t)neigh, netaddr_to_string(&nbuf, &neigh->originator));
@@ -262,6 +265,21 @@ nhdp_db_neighbor_remove(struct nhdp_neighbor *neigh) {
     avl_remove(&_neigh_originator_tree, &neigh->_originator_node);
   }
 
+  /* check if neighbor was a MPR */
+  was_mpr = false;
+  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+    neighdata = nhdp_domain_get_neighbordata(domain, neigh);
+    if (neighdata->neigh_is_mpr) {
+      was_mpr = true;
+      break;
+    }
+  }
+
+  if (was_mpr) {
+    /* all domains might have changed */
+    nhdp_domain_delayed_mpr_recalculation(NULL, neigh);
+  }
+
   /* remove from global list and free memory */
   list_remove(&neigh->_global_node);
   oonf_class_free(&_neigh_info, neigh);
@@ -818,6 +836,7 @@ nhdp_db_link_update_status(struct nhdp_link *lnk) {
   was_symmetric = lnk->status == NHDP_LINK_SYMMETRIC;
 
   /* update link status */
+  lnk->last_status = lnk->status;
   lnk->status = _nhdp_db_link_calculate_status(lnk);
 
   /* handle database changes */
@@ -836,6 +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_metrics(NULL, lnk->neigh);
+    nhdp_domain_delayed_mpr_recalculation(NULL, lnk->neigh);
 
     /* trigger change event */
     oonf_class_event(&_link_info, lnk, OONF_OBJECT_CHANGED);
@@ -1007,10 +1028,6 @@ _cb_link_vtime(struct oonf_timer_instance *ptr) {
   /* check if neighbor still has links */
   if (list_is_empty(&neigh->_links)) {
     nhdp_db_neighbor_remove(neigh);
-    nhdp_domain_neighborhood_changed();
-  }
-  else {
-    nhdp_domain_neighbor_changed(neigh);
   }
 }
 
@@ -1038,7 +1055,6 @@ _cb_link_symtime(struct oonf_timer_instance *ptr) {
   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);
-  nhdp_domain_neighbor_changed(lnk->neigh);
 }
 
 /**
@@ -1062,12 +1078,9 @@ _cb_naddr_vtime(struct oonf_timer_instance *ptr) {
 static void
 _cb_l2hop_vtime(struct oonf_timer_instance *ptr) {
   struct nhdp_l2hop *l2hop;
-  struct nhdp_neighbor *neigh;
 
   l2hop = container_of(ptr, struct nhdp_l2hop, _vtime);
-  neigh = l2hop->link->neigh;
 
   OONF_DEBUG(LOG_NHDP, "2Hop vtime fired: 0x%0zx", (size_t)ptr);
   nhdp_db_link_2hop_remove(l2hop);
-  nhdp_domain_neighbor_changed(neigh);
 }
index 5235570..7b95e86 100644 (file)
@@ -130,7 +130,10 @@ struct nhdp_neighbor_domaindata {
   struct nhdp_metric metric;
 
   /*! pointer to the best link available to the neighbor */
-  struct nhdp_link *best_link;
+  struct nhdp_link *best_out_link;
+
+  /*! outgoing link metric of the best link */
+  uint32_t best_out_link_metric;
 
   /*! interface index for the best link available to the neighbor */
   unsigned best_link_ifindex;
@@ -141,6 +144,9 @@ struct nhdp_neighbor_domaindata {
   /*! true if the neighbor has been selected as a MPR by this router */
   bool neigh_is_mpr;
 
+  /*! true if the neighbor was a MPR of this router before the MPR recalculation */
+  bool _neigh_was_mpr;
+
   /*! Routing willingness of neighbor */
   uint8_t willingness;
 };
@@ -151,6 +157,9 @@ struct nhdp_neighbor_domaindata {
 struct nhdp_l2hop_domaindata {
   /*! incoming and outgoing metric */
   struct nhdp_metric metric;
+
+  /*! metric used for last MPR calculation */
+  uint32_t _last_used_outgoing_metric;
 };
 
 /**
@@ -173,6 +182,9 @@ struct nhdp_link {
   /*! timer that fires when the link has to be removed from the database */
   struct oonf_timer_instance vtime;
 
+  /*! last status of the linked, used to detect status changes */
+  enum nhdp_link_status last_status;
+
   /*! cached status of the linked */
   enum nhdp_link_status status;
 
@@ -194,6 +206,18 @@ struct nhdp_link {
   /*! timestamp when the current link status was set */
   uint64_t last_status_change;
 
+  /*! true if the local router has been selected as a MPR by the neighbor */
+  bool local_is_flooding_mpr;
+
+  /*! true if the neighbor has been selected as a MPR by this router */
+  bool neigh_is_flooding_mpr;
+
+  /*! 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;
 
@@ -281,21 +305,12 @@ struct nhdp_neighbor {
   /*! pointer to other (dualstack) representation of this neighbor */
   struct nhdp_neighbor *dualstack_partner;
 
-  /*! true if the local router has been selected as a MPR by the neighbor */
-  bool local_is_flooding_mpr;
-
-  /*! true if the neighbor has been selected as a MPR by this router */
-  bool neigh_is_flooding_mpr;
-  
-  /* ! true if the neighbor has been selected as an MPR during selection algorithm */
-  bool selection_is_mpr;
-
-  /*! Willingness of neighbor for flooding data */
-  uint8_t flooding_willingness;
-
   /*! internal field for NHDP processing */
   int _process_count;
 
+  /*! true if the neighbor has been selected as an MPR during selection algorithm */
+  bool selection_is_mpr;
+
   /*!
    * originator address of this node before it was changed.
    * Mostly used in CHANGE events
index 74ada5c..c0247e2 100644 (file)
@@ -67,10 +67,14 @@ static void _apply_mpr(struct nhdp_domain *domain,
     const char *mpr_name, uint8_t willingness);
 static void _remove_mpr(struct nhdp_domain *);
 
-static void _cb_update_everyone_mpr(void);
+static void _cb_update_everyone_routing_mpr(struct nhdp_domain *domain);
+static void _cb_update_everyone_flooding_mpr(struct nhdp_domain *domain);
 
-static void _recalculate_neighbor_metric(struct nhdp_domain *domain,
+static bool _recalculate_neighbor_metric(struct nhdp_domain *domain,
         struct nhdp_neighbor *neigh);
+static bool _recalculate_routing_mpr_set(struct nhdp_domain *domain);
+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);
 static const char *_int_to_string(struct nhdp_metric_str *, struct nhdp_link *);
@@ -101,7 +105,8 @@ static struct nhdp_domain_metric _no_metric = {
 static struct nhdp_domain_mpr _everyone_mprs = {
   .name = "Everyone MPR",
 
-  .update_mpr = _cb_update_everyone_mpr,
+  .update_flooding_mpr = _cb_update_everyone_flooding_mpr,
+  .update_routing_mpr = _cb_update_everyone_routing_mpr,
 };
 
 /* non-default routing domains registered to NHDP */
@@ -351,6 +356,11 @@ nhdp_domain_init_link(struct nhdp_link *lnk) {
   struct nhdp_link_domaindata *data;
   int i;
 
+  /* initialize flooding MPR settings */
+  lnk->flooding_willingness = RFC7181_WILLINGNESS_NEVER;
+  lnk->local_is_flooding_mpr = false;
+  lnk->neigh_is_flooding_mpr = false;
+
   /* initialize metrics */
   for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
     lnk->_domaindata[i].metric.in = RFC7181_METRIC_INFINITE;
@@ -403,17 +413,12 @@ nhdp_domain_init_neighbor(struct nhdp_neighbor *neigh) {
   struct nhdp_neighbor_domaindata *data;
   int i;
 
-  /* initialize flooding MPR settings */
-  neigh->flooding_willingness = RFC7181_WILLINGNESS_NEVER;
-  neigh->local_is_flooding_mpr = false;
-  neigh->neigh_is_flooding_mpr = false;
-  neigh->selection_is_mpr = false;
-
   for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
     neigh->_domaindata[i].metric.in = RFC7181_METRIC_INFINITE;
     neigh->_domaindata[i].metric.out = RFC7181_METRIC_INFINITE;
 
-    neigh->_domaindata[i].best_link = NULL;
+    neigh->_domaindata[i].best_out_link = NULL;
+    neigh->_domaindata[i].best_out_link_metric = RFC7181_METRIC_INFINITE;
     neigh->_domaindata[i].willingness = RFC7181_WILLINGNESS_NEVER;
 
 
@@ -481,76 +486,110 @@ nhdp_domain_process_metric_2hoptlv(struct nhdp_domain *domain,
   }
 }
 
-static bool _recalculate_mpr = false;
-
-void
-nhdp_domain_recalculate_mpr(void) {
+/**
+ * This will trigger a metric recalculation
+ * @param domain NHDP domain of metric change, NULL for all domains
+ * return true if metric changed, false otherwise
+ */
+static bool
+_recalculate_metrics(struct nhdp_domain *domain, struct nhdp_neighbor *neigh, bool trigger) {
   struct nhdp_domain_listener *listener;
-  struct nhdp_domain *domain;
-  struct nhdp_neighbor *neigh;
-  
-  if (!_recalculate_mpr) {
-    return;
+  bool changed_metric;
+
+  changed_metric = false;
+
+  if (trigger) {
+    OONF_DEBUG(LOG_NHDP, "Recalculating metrics set for domain %d",
+        domain ? domain->index : -1);
   }
 
-  list_for_each_element(&_domain_list, domain, _node) {
-    if (domain->mpr->update_mpr != NULL) {
-      domain->mpr->update_mpr();
+  if (!domain) {
+    list_for_each_element(&_domain_list, domain, _node) {
+      changed_metric |= _recalculate_metrics(domain, neigh, false);
     }
   }
-
-  // TODO: flooding mpr ?
-  // (Why do we need to consider flooding MPRs here?)
-
-  list_for_each_element(&_domain_listener_list, listener, _node) {
-    if (listener->update) {
-      listener->update(NULL);
+  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);
+  }
 
-  /* check if we still have routing MPR selectors */
-  OONF_DEBUG(LOG_NHDP, "Checking if we still have routing MPR selectors");
-  _node_is_selected_as_mpr = false;
-
-  list_for_each_element(&_domain_list, domain, _node) {
-    list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
-      if (nhdp_domain_get_neighbordata(domain, neigh)->local_is_mpr) {
-        _node_is_selected_as_mpr = true;
-        return;
+  if (trigger && changed_metric) {
+    list_for_each_element(&_domain_listener_list, listener, _node) {
+      /* trigger domain listeners */
+      if (listener->metric_update) {
+        listener->metric_update(domain);
       }
     }
   }
 
-  _recalculate_mpr = false;
+  if (trigger) {
+    OONF_INFO(LOG_NHDP, "Metrics changed for domain %d: %s",
+        domain ? domain->index : -1, changed_metric ? "true" : "false");
+  }
+  return changed_metric;
 }
-/**
- * Neighborhood changed in terms of metrics or connectivity.
- * This will trigger a MPR set recalculation.
- */
+
+bool
+nhdp_domain_recalculate_metrics(struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
+  return _recalculate_metrics(domain, neigh, true);
+}
+
+static void
+_fire_mpr_changed(struct nhdp_domain *domain) {
+  struct nhdp_domain_listener *listener;
+  list_for_each_element(&_domain_listener_list, listener, _node) {
+    /* trigger domain listeners */
+    if (listener->mpr_update) {
+      listener->mpr_update(domain);
+    }
+  }
+}
+
 void
-nhdp_domain_neighborhood_changed(void) {
+nhdp_domain_recalculate_mpr(void) {
   struct nhdp_domain *domain;
-  struct nhdp_neighbor *neigh;
 
   list_for_each_element(&_domain_list, domain, _node) {
-    list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
-      _recalculate_neighbor_metric(domain, neigh);
+    if (domain->_mpr_outdated) {
+      if (_recalculate_routing_mpr_set(domain)) {
+        domain->mpr->update_routing_mpr(domain);
+        _fire_mpr_changed(domain);
+      }
+      domain->_mpr_outdated = false;
+    }
+  }
+  if (_flooding_domain._mpr_outdated) {
+    if (_recalculate_flooding_mpr_set()) {
+      _flooding_domain.mpr->update_flooding_mpr(&_flooding_domain);
+      _fire_mpr_changed(&_flooding_domain);
     }
+    _flooding_domain._mpr_outdated = false;
   }
 }
 
 /**
- * One neighbor changed in terms of metrics or connectivity.
- * This will trigger a MPR set recalculation.
- * @param neigh neighbor where the changed happened
+ * This marks a MPR domain as 'to be recalculated' as soon as a Hello is sent
+ * @param domain NHDP domain
+ * @param neigh neighbor that triggered the recalculation,
+ *   NULL for unspecified neighbor
+ * @return
  */
 void
-nhdp_domain_neighbor_changed(struct nhdp_neighbor *neigh) {
-  struct nhdp_domain *domain;
-  
-  list_for_each_element(&_domain_list, domain, _node) {
-    _recalculate_neighbor_metric(domain, neigh);
+nhdp_domain_delayed_mpr_recalculation(struct nhdp_domain *domain,
+    struct nhdp_neighbor *neigh __attribute__((unused))) {
+  if (!domain) {
+    list_for_each_element(&_domain_list, domain, _node) {
+      nhdp_domain_delayed_mpr_recalculation(domain, neigh);
+    }
+    nhdp_domain_delayed_mpr_recalculation(&_flooding_domain, neigh);
+    return;
   }
+
+  domain->_mpr_outdated = true;
 }
 
 /**
@@ -596,21 +635,22 @@ nhdp_domain_process_mprtypes_tlv(
 
 /**
  * Process an in MPR tlv for a NHDP link
- * @param mprtypes list of extenstions for MPR
+ * @param mprtypes list of extensions for MPR
  * @param mprtypes_size length of mprtypes array
  * @param neigh NHDP neighbor
  * @param tlv MPR tlv context
  */
 void
 nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
-    struct nhdp_neighbor *neigh, struct rfc5444_reader_tlvblock_entry *tlv) {
+    struct nhdp_link *lnk, struct rfc5444_reader_tlvblock_entry *tlv) {
   struct nhdp_domain *domain;
+  struct nhdp_neighbor *neigh;
   size_t bit_idx, byte_idx;
   size_t i;
 
-  neigh->local_is_flooding_mpr = false;
+  lnk->local_is_flooding_mpr = false;
   list_for_each_element(&_domain_list, domain, _node) {
-    nhdp_domain_get_neighbordata(domain, neigh)->local_is_mpr = false;
+    nhdp_domain_get_neighbordata(domain, lnk->neigh)->local_is_mpr = false;
   }
 
   if (!tlv) {
@@ -618,10 +658,10 @@ nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
   }
 
   /* set flooding MPR flag */
-  neigh->local_is_flooding_mpr =
+  lnk->local_is_flooding_mpr =
       (tlv->single_value[0] & RFC7181_MPR_FLOODING) != 0;
   OONF_DEBUG(LOG_NHDP_R, "Flooding MPR for neighbor: %s",
-      neigh->local_is_flooding_mpr ? "true" : "false");
+      lnk->local_is_flooding_mpr ? "true" : "false");
 
   /* set routing MPR flags */
   for (i=0; i<mprtypes_size; i++) {
@@ -636,11 +676,21 @@ nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
       continue;
     }
 
-    nhdp_domain_get_neighbordata(domain, neigh)->local_is_mpr =
+    nhdp_domain_get_neighbordata(domain, lnk->neigh)->local_is_mpr =
         (tlv->single_value[byte_idx] & (1 << bit_idx)) != 0;
 
     OONF_DEBUG(LOG_NHDP_R, "Routing MPR for neighbor in domain %u: %s",
-        domain->ext, nhdp_domain_get_neighbordata(domain, neigh)->local_is_mpr ? "true" : "false");
+        domain->ext, nhdp_domain_get_neighbordata(domain, lnk->neigh)->local_is_mpr ? "true" : "false");
+  }
+
+  _node_is_selected_as_mpr = false;
+  list_for_each_element(&_domain_list, domain, _node) {
+    list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
+      if (nhdp_domain_get_neighbordata(domain, neigh)->local_is_mpr) {
+        _node_is_selected_as_mpr = true;
+        return;
+      }
+    }
   }
 }
 
@@ -648,7 +698,7 @@ nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
  * Process an in Willingness tlv and put values into
  * temporary storage in MPR handler object. Call
  * nhdp_domain_store_willingness to permanently store them later.
- * @param mprtypes list of extenstions for MPR
+ * @param mprtypes list of extensions for MPR
  * @param mprtypes_size length of mprtypes array
  * @param tlv Willingness tlv context
  */
@@ -707,16 +757,16 @@ nhdp_domain_process_willingness_tlv(
  * @param neigh NHDP neighbor
  */
 void
-nhdp_domain_store_willingness(struct nhdp_neighbor *neigh) {
+nhdp_domain_store_willingness(struct nhdp_link *lnk) {
   struct nhdp_neighbor_domaindata *neighdata;
   struct nhdp_domain *domain;
 
-  neigh->flooding_willingness = _flooding_domain._tmp_willingness;
+  lnk->flooding_willingness = _flooding_domain._tmp_willingness;
   OONF_DEBUG(LOG_NHDP_R, "Set flooding willingness: %u",
-      neigh->flooding_willingness);
+      lnk->flooding_willingness);
 
   list_for_each_element(&_domain_list, domain, _node) {
-    neighdata = nhdp_domain_get_neighbordata(domain, neigh);
+    neighdata = nhdp_domain_get_neighbordata(domain, lnk->neigh);
     neighdata->willingness = domain->_tmp_willingness;
     OONF_DEBUG(LOG_NHDP_R, "Set routing willingness for domain %u: %u",
         domain->ext, neighdata->willingness);
@@ -757,19 +807,19 @@ nhdp_domain_encode_mprtypes_tlvvalue(
  */
 size_t
 nhdp_domain_encode_mpr_tlvvalue(
-    uint8_t *tlvvalue, size_t tlvsize, struct nhdp_neighbor *neigh) {
+    uint8_t *tlvvalue, size_t tlvsize, struct nhdp_link *lnk) {
   struct nhdp_domain *domain;
   size_t bit_idx, byte_idx, len;
 
   memset(tlvvalue, 0, tlvsize);
   len = 0;
   /* set flooding MPR flag */
-  if (neigh->neigh_is_flooding_mpr) {
+  if (lnk->neigh_is_flooding_mpr) {
     tlvvalue[0] |= RFC7181_MPR_FLOODING;
   }
 
   OONF_DEBUG(LOG_NHDP_W, "Set flooding MPR: %s",
-      neigh->neigh_is_flooding_mpr ? "true" : "false");
+      lnk->neigh_is_flooding_mpr ? "true" : "false");
 
   list_for_each_element(&_domain_list, domain, _node) {
     bit_idx = (domain->index + 1) & 7;
@@ -782,12 +832,12 @@ nhdp_domain_encode_mpr_tlvvalue(
       len = byte_idx + 1;
     }
 
-    if (nhdp_domain_get_neighbordata(domain, neigh)->neigh_is_mpr) {
+    if (nhdp_domain_get_neighbordata(domain, lnk->neigh)->neigh_is_mpr) {
       tlvvalue[byte_idx] |= (1 << bit_idx);
     }
 
     OONF_DEBUG(LOG_NHDP_W, "Set routing MPR for domain %u: %s",
-        domain->ext, nhdp_domain_get_neighbordata(domain, neigh)->neigh_is_mpr ? "true" : "false");
+        domain->ext, nhdp_domain_get_neighbordata(domain, lnk->neigh)->neigh_is_mpr ? "true" : "false");
   }
   return len;
 }
@@ -848,6 +898,13 @@ nhdp_domain_set_flooding_mpr(const char *mpr_name, uint8_t willingness) {
   _apply_mpr(&_flooding_domain, mpr_name, willingness);
 }
 
+/**
+ * @return the virtual flooding domain
+ */
+const struct nhdp_domain *
+nhdp_domain_get_flooding_domain(void) {
+  return &_flooding_domain;
+}
 /**
  * Sets the incoming metric of a link. This is the only function external
  * code should use to commit the calculated metric values to the nhdp db.
@@ -887,8 +944,7 @@ nhdp_domain_set_incoming_metric(struct nhdp_domain_metric *metric,
 }
 
 /**
- * get list of nhdp domains
- * @return domain list
+ * @return list of domains
  */
 struct list_entity *
 nhdp_domain_get_list(void) {
@@ -896,58 +952,109 @@ nhdp_domain_get_list(void) {
 }
 
 /**
- * get list of nhdp domain listeners for metric/mpr changes
- * @return listener list
+ * @return list of event listeners for domain metric/mpr triggers
  */
 struct list_entity *
 nhdp_domain_get_listener_list(void) {
   return &_domain_listener_list;
 }
 
+static bool
+_recalculate_flooding_mpr_set(void) {
+  struct nhdp_link *lnk;
+
+  list_for_each_element(nhdp_db_get_link_list(), lnk, _global_node) {
+    lnk->_neigh_was_flooding_mpr = lnk->neigh_is_flooding_mpr;
+  }
+
+  _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 false;
+}
+
 /**
- * get current NHDP flooding domain
- * @return flooding domain
+ * Recalculate the MPR set of a NHDP domain
+ * @param domain nhdp domain
+ * @return true if the MPR set changed
  */
-const struct nhdp_domain *
-nhdp_domain_get_flooding(void) {
-  return &_flooding_domain;
+static bool
+_recalculate_routing_mpr_set(struct nhdp_domain *domain) {
+  struct nhdp_neighbor_domaindata *neighdata;
+  struct nhdp_neighbor *neigh;
+
+  if (!domain->mpr->update_routing_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);
+    neighdata->_neigh_was_mpr = neighdata->neigh_is_mpr;
+  }
+
+  /* update MPR set */
+  domain->mpr->update_routing_mpr(domain);
+
+  /* check for changes */
+  list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
+    neighdata = nhdp_domain_get_neighbordata(domain, neigh);
+    if (neighdata->_neigh_was_mpr != neighdata->neigh_is_mpr) {
+      OONF_DEBUG(LOG_NHDP, "Domain ext %u MPR set changed", domain->ext);
+      return true;
+    }
+  }
+  return false;
 }
 
 /**
  * Recalculate the 'best link/metric' values of a neighbor
+ * and check for two-hop outgoing link metric changes
  * @param domain NHDP domain
  * @param neigh NHDP neighbor
+ * @param neighdata NHDP neighbor domaindata
+ * @return true neighbor metric or the two-hop link metrics changed
  */
-static void
+static bool
 _recalculate_neighbor_metric(
     struct nhdp_domain *domain,
     struct nhdp_neighbor *neigh) {
   struct nhdp_link *lnk;
   struct nhdp_link_domaindata *linkdata;
+  struct nhdp_l2hop *l2hop;
+  struct nhdp_l2hop_domaindata *l2hopdata;
   struct nhdp_neighbor_domaindata *neighdata;
-  struct nhdp_metric oldmetric;
+  bool changed;
 #ifdef OONF_LOG_DEBUG_INFO
   struct netaddr_str nbuf;
 #endif
 
   neighdata = nhdp_domain_get_neighbordata(domain, neigh);
-
-  /* copy old metric value */
-  memcpy(&oldmetric, &neighdata->metric, sizeof(oldmetric));
+  changed = false;
 
   /* reset metric */
   neighdata->metric.in = RFC7181_METRIC_INFINITE;
   neighdata->metric.out = RFC7181_METRIC_INFINITE;
 
   /* reset best link */
-  neighdata->best_link = NULL;
+  neighdata->best_out_link = NULL;
   neighdata->best_link_ifindex = 0;
 
-  OONF_DEBUG(LOG_NHDP, "Recalculate neighbor %s metrics (ext %u):",
-      netaddr_to_string(&nbuf, &neigh->originator), domain->ext);
+  OONF_INFO(LOG_NHDP, "Recalculate neighbor %s metrics (ext %u): old_outgoing=%u",
+      netaddr_to_string(&nbuf, &neigh->originator), domain->ext,
+      neighdata->best_out_link_metric);
 
   /* get best metric */
   list_for_each_element(&neigh->_links, lnk, _neigh_node) {
+    if (lnk->status != NHDP_LINK_SYMMETRIC) {
+      continue;
+    }
+
     linkdata = nhdp_domain_get_linkdata(domain, lnk);
     if (linkdata->metric.out < neighdata->metric.out) {
       OONF_DEBUG(LOG_NHDP, "Link on if %s has better outgoing metric: %u",
@@ -955,7 +1062,7 @@ _recalculate_neighbor_metric(
               linkdata->metric.out);
 
       neighdata->metric.out = linkdata->metric.out;
-      neighdata->best_link = lnk;
+      neighdata->best_out_link = lnk;
     }
     if (linkdata->metric.in < neighdata->metric.in) {
       OONF_DEBUG(LOG_NHDP, "Link on if %s has better incoming metric: %u",
@@ -963,20 +1070,31 @@ _recalculate_neighbor_metric(
               linkdata->metric.in);
       neighdata->metric.in = linkdata->metric.in;
     }
+
+    /* check for changes in outgoing 2-hop metrics */
+    avl_for_each_element(&lnk->_2hop, l2hop, _link_node) {
+      l2hopdata = nhdp_domain_get_l2hopdata(domain, l2hop);
+
+      changed |= l2hopdata->metric.out != l2hopdata->_last_used_outgoing_metric;
+      l2hopdata->_last_used_outgoing_metric = l2hopdata->metric.out;
+    }
   }
 
-  if (neighdata->best_link != NULL) {
-    OONF_DEBUG(LOG_NHDP, "Best link if: %s",
-        nhdp_interface_get_if_listener(neighdata->best_link->local_if)->data->name);
+  if (neighdata->best_out_link != NULL) {
+    linkdata = nhdp_domain_get_linkdata(domain, neighdata->best_out_link);
+
+    OONF_INFO(LOG_NHDP, "Best link: if=%s, link=%s, in=%u, out=%u",
+        nhdp_interface_get_if_listener(neighdata->best_out_link->local_if)->data->name,
+        netaddr_to_string(&nbuf, &neighdata->best_out_link->if_addr),
+        linkdata->metric.in, linkdata->metric.out);
     neighdata->best_link_ifindex =
-        nhdp_interface_get_if_listener(neighdata->best_link->local_if)->data->index;
-  }
+        nhdp_interface_get_if_listener(neighdata->best_out_link->local_if)->data->index;
 
-  if (memcmp(&oldmetric, &neighdata->metric, sizeof(oldmetric)) != 0) {
-    /* mark metric as updated */
-    domain->neighbor_metric_changed = true;
-    _recalculate_mpr = true;
+    changed |= neighdata->best_out_link_metric != linkdata->metric.out;
+    neighdata->best_out_link_metric = linkdata->metric.out;
   }
+
+  return changed;
 }
 
 /**
@@ -1199,24 +1317,27 @@ _remove_mpr(struct nhdp_domain *domain) {
 }
 
 static void
-_cb_update_everyone_mpr(void) {
+_cb_update_everyone_routing_mpr(struct nhdp_domain *domain) {
   struct nhdp_neighbor *neigh;
-  struct nhdp_domain *domain;
   struct nhdp_neighbor_domaindata *domaindata;
 
   list_for_each_element(nhdp_db_get_neigh_list(), neigh, _global_node) {
-    if (_flooding_domain.mpr == &_everyone_mprs) {
-      neigh->neigh_is_flooding_mpr =
-          neigh->flooding_willingness > RFC7181_WILLINGNESS_NEVER;
+    if (domain->mpr == &_everyone_mprs) {
+      domaindata = nhdp_domain_get_neighbordata(domain, neigh);
+      domaindata->neigh_is_mpr =
+          domaindata->willingness > RFC7181_WILLINGNESS_NEVER;
     }
+  }
+}
 
-    list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-      if (domain->mpr == &_everyone_mprs) {
-        domaindata = nhdp_domain_get_neighbordata(domain, neigh);
-        domaindata->neigh_is_mpr =
-            domaindata->willingness > RFC7181_WILLINGNESS_NEVER;
-      }
-    }
+static void
+_cb_update_everyone_flooding_mpr(
+    struct nhdp_domain *domain __attribute__((unused))) {
+  struct nhdp_link *lnk;
+
+  list_for_each_element(nhdp_db_get_link_list(), lnk, _global_node) {
+    lnk->neigh_is_flooding_mpr =
+        lnk->flooding_willingness > RFC7181_WILLINGNESS_NEVER;
   }
 }
 
index 2439137..5d06d70 100644 (file)
@@ -148,6 +148,8 @@ struct nhdp_domain_metric {
   struct avl_node _node;
 };
 
+struct nhdp_domain;
+
 /**
  * MPR handler for a NHDP domain
  */
@@ -156,9 +158,16 @@ struct nhdp_domain_mpr {
   const char *name;
 
   /**
-   * callback to calculate MPR set
+   * callback to calculate routing MPR set
+   * @param domain NHDP domain to update MPR set
+   */
+  void (*update_routing_mpr)(struct nhdp_domain *domain);
+
+  /**
+   * callback to calculate flooding MPR set
+   * @param domain NHDP domain used to update flooding MPR set
    */
-  void (*update_mpr)(void);
+  void (*update_flooding_mpr)(struct nhdp_domain *domain);
 
   /**
    * callback to enable mpr
@@ -200,18 +209,15 @@ struct nhdp_domain {
   /*! flooding willingness */
   uint8_t local_willingness;
 
-  /**
-   * true if a neighbor metric of this domain has changed
-   * since the last reset of this variable
-   */
-  bool neighbor_metric_changed;
-
   /*! metric tlv extension */
   uint8_t ext;
 
   /*! index in the domain array */
   int index;
 
+  /*! true if MPR should be recalculated */
+  bool _mpr_outdated;
+
   /*! temporary storage for willingness processing */
   uint8_t _tmp_willingness;
 
@@ -226,11 +232,17 @@ struct nhdp_domain {
  * listener for NHDP domain updates
  */
 struct nhdp_domain_listener {
-  /**
-   * Callback to inform about a NHDP neighbor update
-   * @param neigh neighbor that changed, NULL if multiple neighbors changed
-   */
-  void (*update)(struct nhdp_neighbor *neigh);
+    /**
+     * Callback to inform about a NHDP neighbor MPR update
+     * @param domain NHDP domain of which the MPR set changed
+     */
+    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
+     */
+    void (*metric_update)(struct nhdp_domain *domain);
 
   /*! hook into global domain updater list */
   struct list_entity _node;
@@ -286,34 +298,37 @@ 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(void);
-EXPORT void nhdp_domain_neighborhood_changed(void);
-EXPORT void nhdp_domain_neighbor_changed(struct nhdp_neighbor *neigh);
-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);
 EXPORT void nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
-    struct nhdp_neighbor *, struct rfc5444_reader_tlvblock_entry *tlv);
+    struct nhdp_link *, struct rfc5444_reader_tlvblock_entry *tlv);
 EXPORT void nhdp_domain_process_willingness_tlv(
     uint8_t *mpr_types, size_t mprtypes_size,
     struct rfc5444_reader_tlvblock_entry *tlv);
-EXPORT void nhdp_domain_store_willingness(struct nhdp_neighbor *);
+EXPORT void nhdp_domain_store_willingness(struct nhdp_link *);
 EXPORT size_t nhdp_domain_encode_mprtypes_tlvvalue(
     uint8_t *mprtypes, size_t mprtypes_size);
 EXPORT size_t nhdp_domain_encode_mpr_tlvvalue(
-    uint8_t *tlvvalue, size_t tlvsize, struct nhdp_neighbor *);
+    uint8_t *tlvvalue, size_t tlvsize, struct nhdp_link *);
 EXPORT size_t nhdp_domain_encode_willingness_tlvvalue(
     uint8_t *tlvvalue, size_t tlvsize);
 
 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 void nhdp_domain_delayed_mpr_recalculation(
+    struct nhdp_domain *domain, struct nhdp_neighbor *neigh);
+EXPORT void nhdp_domain_recalculate_mpr(void);
 
 EXPORT struct list_entity *nhdp_domain_get_list(void);
 EXPORT struct list_entity *nhdp_domain_get_listener_list(void);
-EXPORT const struct nhdp_domain *nhdp_domain_get_flooding(void);
+EXPORT const struct nhdp_domain *nhdp_domain_get_flooding_domain(void);
 EXPORT void nhdp_domain_set_flooding_mpr(const char *mpr_name, uint8_t willingness);
+EXPORT const struct nhdp_domain *nhdp_domain_get_flooding_domain(void);
 
 /**
  * @param domain NHDP domain
index 589dd82..5158d0b 100644 (file)
@@ -728,7 +728,7 @@ _process_domainspecific_linkdata(struct netaddr *addr __attribute__((unused))) {
 
   /* process MPR settings of link */
   nhdp_domain_process_mpr_tlv(_current.mprtypes, _current.mprtypes_size,
-      _current.neighbor, _nhdp_address_pass2_tlvs[IDX_ADDRTLV2_MPR].tlv);
+      _current.link, _nhdp_address_pass2_tlvs[IDX_ADDRTLV2_MPR].tlv);
 
   /* update out metric with other sides in metric */
   tlv = _nhdp_address_pass2_tlvs[IDX_ADDRTLV2_LINKMETRIC].tlv;
@@ -968,10 +968,7 @@ _cb_msg_pass2_end(struct rfc5444_reader_tlvblock_context *context, bool dropped)
   nhdp_db_neighbor_set_originator(_current.neighbor, &context->orig_addr);
 
   /* copy willingness to permanent storage */
-  nhdp_domain_store_willingness(_current.neighbor);
-
-  /* update MPR sets and link metrics */
-  nhdp_domain_neighbor_changed(_current.neighbor);
+  nhdp_domain_store_willingness(_current.link);
 
   /* update ip flooding settings */
   nhdp_interface_update_status(_current.localif);
@@ -979,5 +976,9 @@ _cb_msg_pass2_end(struct rfc5444_reader_tlvblock_context *context, bool dropped)
   /* update link status */
   nhdp_db_link_update_status(_current.link);
 
+  /* update link metrics and MPR */
+  nhdp_domain_recalculate_metrics(NULL, _current.neighbor);
+  nhdp_domain_delayed_mpr_recalculation(NULL, _current.neighbor);
+
   return RFC5444_OKAY;
 }
index 31c25ea..40e7f06 100644 (file)
@@ -420,7 +420,7 @@ _add_link_address(struct rfc5444_writer *writer, struct rfc5444_writer_content_p
 
   /* add MPR tlvs */
   if (laddr != NULL) {
-    len = nhdp_domain_encode_mpr_tlvvalue(mprvalue, sizeof(mprvalue), naddr->neigh);
+    len = nhdp_domain_encode_mpr_tlvvalue(mprvalue, sizeof(mprvalue), laddr->link);
 
     if (len) {
       rfc5444_writer_add_addrtlv(writer, address,
index f36a050..b7d5b74 100644 (file)
@@ -154,6 +154,15 @@ static int _cb_create_text_neighbor_address(struct oonf_viewer_template *);
 /*! template key for links remote mac address */
 #define KEY_LINK_MAC                "link_mac"
 
+/*! template key signaling link has selected node as flooding MPR */
+#define KEY_LINK_FLOOD_LOCAL        "link_flood_local"
+
+/*! template key signaling route has selected link as flooding MPR */
+#define KEY_LINK_FLOOD_REMOTE       "link_flood_remote"
+
+/*! template key for link flooding willingness */
+#define KEY_LINK_FLOOD_WILL         "link_flood_willingness"
+
 /*! template key for a link IP address */
 #define KEY_LINK_ADDRESS            "link_address"
 
@@ -172,21 +181,12 @@ static int _cb_create_text_neighbor_address(struct oonf_viewer_template *);
 /*! template key for neighbors dualstack originator IP */
 #define KEY_NEIGHBOR_DUALSTACK      "neighbor_dualstack"
 
-/*! template key signaling neighbor has selected node as flooding MPR */
-#define KEY_NEIGHBOR_FLOOD_LOCAL    "neighbor_flood_local"
-
-/*! template key signaling route has selected neighbor as flooding MPR */
-#define KEY_NEIGHBOR_FLOOD_REMOTE   "neighbor_flood_remote"
-
 /*! template key for number of symmetric links of neighbor */
 #define KEY_NEIGHBOR_SYMMETRIC      "neighbor_symmetric"
 
 /*! template key for number of links of neighbor */
 #define KEY_NEIGHBOR_LINKCOUNT      "neighbor_linkcount"
 
-/*! template key for neighbor flooding willingness */
-#define KEY_NEIGHBOR_FLOOD_WILL     "neighbor_flood_willingness"
-
 /*! template key for neighbor address */
 #define KEY_NEIGHBOR_ADDRESS        "neighbor_address"
 
@@ -253,6 +253,9 @@ static struct isonumber_str       _value_link_vtime;
 static char                       _value_link_status[NHDP_LINK_STATUS_TXTLENGTH];
 static struct netaddr_str         _value_link_dualstack;
 static struct netaddr_str         _value_link_mac;
+static char                       _value_link_flood_local[TEMPLATE_JSON_BOOL_LENGTH];
+static char                       _value_link_flood_remote[TEMPLATE_JSON_BOOL_LENGTH];
+static char                       _value_link_willingness[3];
 
 static struct netaddr_str         _value_link_address;
 
@@ -262,11 +265,8 @@ static struct isonumber_str       _value_twohop_vtime;
 
 static struct netaddr_str         _value_neighbor_originator;
 static struct netaddr_str         _value_neighbor_dualstack;
-static char                       _value_neighbor_flood_local[TEMPLATE_JSON_BOOL_LENGTH];
-static char                       _value_neighbor_flood_remote[TEMPLATE_JSON_BOOL_LENGTH];
 static char                       _value_neighbor_symmetric[TEMPLATE_JSON_BOOL_LENGTH];
 static char                       _value_neighbor_linkcount[10];
-static char                       _value_neighbor_willingness[3];
 static struct netaddr_str         _value_neighbor_address;
 static char                       _value_neighbor_address_lost[TEMPLATE_JSON_BOOL_LENGTH];
 static struct isonumber_str       _value_neighbor_address_lost_vtime;
@@ -320,6 +320,9 @@ static struct abuf_template_data_entry _tde_link[] = {
     { KEY_LINK_STATUS, _value_link_status, true },
     { KEY_LINK_DUALSTACK, _value_link_dualstack.buf, true },
     { KEY_LINK_MAC, _value_link_mac.buf, true },
+    { KEY_LINK_FLOOD_LOCAL, _value_link_flood_local, true },
+    { KEY_LINK_FLOOD_REMOTE, _value_link_flood_remote, true },
+    { KEY_LINK_FLOOD_WILL, _value_link_willingness, false },
     { KEY_NEIGHBOR_ORIGINATOR, _value_neighbor_originator.buf, true },
     { KEY_NEIGHBOR_DUALSTACK, _value_neighbor_dualstack.buf, true },
 };
@@ -362,9 +365,6 @@ static struct abuf_template_data_entry _tde_neigh_key[] = {
 
 static struct abuf_template_data_entry _tde_neigh[] = {
     { KEY_NEIGHBOR_DUALSTACK, _value_neighbor_dualstack.buf, true },
-    { KEY_NEIGHBOR_FLOOD_LOCAL, _value_neighbor_flood_local, true },
-    { KEY_NEIGHBOR_FLOOD_REMOTE, _value_neighbor_flood_remote, true },
-    { KEY_NEIGHBOR_FLOOD_WILL, _value_neighbor_willingness, false },
     { KEY_NEIGHBOR_SYMMETRIC, _value_neighbor_symmetric, true },
     { KEY_NEIGHBOR_LINKCOUNT, _value_neighbor_linkcount, false },
 };
@@ -617,6 +617,16 @@ _initialize_nhdp_link_values(struct nhdp_link *lnk) {
   }
 
   netaddr_to_string(&_value_link_mac, &lnk->remote_mac);
+
+  strscpy(_value_link_flood_local,
+      json_getbool(lnk->local_is_flooding_mpr),
+      sizeof(_value_link_flood_local));
+  strscpy(_value_link_flood_remote,
+      json_getbool(lnk->neigh_is_flooding_mpr),
+      sizeof(_value_link_flood_remote));
+  snprintf(_value_link_willingness, sizeof(_value_link_willingness),
+      "%d", lnk->flooding_willingness);
+
 }
 
 /**
@@ -709,15 +719,6 @@ _initialize_nhdp_neighbor_values(struct nhdp_neighbor *neigh) {
     strscpy(_value_neighbor_dualstack.buf, "-", sizeof(_value_neighbor_dualstack));
   }
 
-  strscpy(_value_neighbor_flood_local,
-      json_getbool(neigh->local_is_flooding_mpr),
-      sizeof(_value_neighbor_flood_local));
-  strscpy(_value_neighbor_flood_remote,
-      json_getbool(neigh->neigh_is_flooding_mpr),
-      sizeof(_value_neighbor_flood_remote));
-  snprintf(_value_neighbor_willingness, sizeof(_value_neighbor_willingness),
-      "%d", neigh->flooding_willingness);
-
   strscpy(_value_neighbor_symmetric,
       json_getbool(neigh->symmetric > 0),
       sizeof(_value_neighbor_symmetric));
index 80685cc..e8fbc1c 100644 (file)
@@ -487,7 +487,7 @@ _print_edge_links(struct json_session *session,
 
   af_type = netaddr_get_address_family(&neigh->originator);
 
-  best_link = nhdp_domain_get_neighbordata(domain, neigh)->best_link;
+  best_link = nhdp_domain_get_neighbordata(domain, neigh)->best_out_link;
 
   json_start_array(session, "links");
 
index 7530340..d79a2cd 100644 (file)
@@ -53,7 +53,6 @@
 #include "config/cfg_schema.h"
 #include "core/oonf_logging.h"
 #include "core/oonf_subsystem.h"
-#include "core/os_core.h"
 #include "subsystems/oonf_rfc5444.h"
 #include "subsystems/oonf_telnet.h"
 #include "subsystems/oonf_timer.h"
@@ -110,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;
 
@@ -186,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"
@@ -236,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 */
@@ -258,16 +265,13 @@ static struct os_interface_listener _if_listener = {
 /* global variables */
 static struct oonf_rfc5444_protocol *_protocol;
 
-static uint16_t _ansn;
-static uint32_t _sym_neighbor_id = 0;
-
 static bool _generate_tcs = true;
 
 /* Additional logging sources */
-static enum oonf_log_source LOG_OLSRV2;
-static enum oonf_log_source LOG_OLSRV2_R;
-static enum oonf_log_source LOG_OLSRV2_ROUTING;
-static enum oonf_log_source LOG_OLSRV2_W;
+enum oonf_log_source LOG_OLSRV2;
+enum oonf_log_source LOG_OLSRV2_R;
+enum oonf_log_source LOG_OLSRV2_ROUTING;
+enum oonf_log_source LOG_OLSRV2_W;
 
 /**
  * Initialize additional logging sources for NHDP
@@ -286,12 +290,15 @@ _early_cfg_init(void) {
  */
 static int
 _init(void) {
-  if (os_core_get_random(&_ansn, sizeof(_ansn))) {
+  _protocol = oonf_rfc5444_get_default_protocol();
+
+  if (olsrv2_writer_init(_protocol)) {
     return -1;
   }
 
-  _protocol = oonf_rfc5444_get_default_protocol();
-  if (olsrv2_writer_init(_protocol)) {
+  if (olsrv2_routing_init()) {
+    olsrv2_writer_cleanup();
+    oonf_rfc5444_remove_protocol(_protocol);
     return -1;
   }
 
@@ -303,7 +310,6 @@ _init(void) {
   olsrv2_originator_init();
   olsrv2_reader_init(_protocol);
   olsrv2_tc_init();
-  olsrv2_routing_init();
 
   /* initialize timer */
   oonf_timer_add(&_tc_timer_class);
@@ -511,51 +517,17 @@ olsrv2_mpr_shall_forwarding(struct rfc5444_reader_tlvblock_context *context,
   }
 
   /* forward if this neighbor has selected us as a flooding MPR */
-  forward = neigh->local_is_flooding_mpr && neigh->symmetric > 0;
+  forward = laddr->link->local_is_flooding_mpr && neigh->symmetric > 0;
   OONF_DEBUG(LOG_OLSRV2, "Do %sforward message type %u from %s"
       " with seqno %u (%s/%u)",
       forward ? "" : "not ",
       context->msg_type,
       netaddr_to_string(&buf, &context->orig_addr),
       context->seqno,
-      neigh->local_is_flooding_mpr ? "true" : "false", neigh->symmetric);
+      laddr->link->local_is_flooding_mpr ? "true" : "false", neigh->symmetric);
   return forward;
 }
 
-/**
- * @return current answer set number for local topology database
- */
-uint16_t
-olsrv2_get_ansn(void) {
-  return _ansn;
-}
-
-/**
- * Update answer set number if metric of a neighbor changed since last update.
- * @param force true to force an answerset number change
- * @return new answer set number, might be the same if no metric changed.
- */
-uint16_t
-olsrv2_update_ansn(bool force) {
-  struct nhdp_domain *domain;
-  bool changed;
-
-  changed = false;
-  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-    if (domain->neighbor_metric_changed) {
-      changed = true;
-      domain->neighbor_metric_changed = false;
-    }
-  }
-
-  if (changed || force
-      || _sym_neighbor_id != nhdp_db_neighbor_get_set_id()) {
-    _ansn++;
-    _sym_neighbor_id = nhdp_db_neighbor_get_set_id();
-  }
-  return _ansn;
-}
-
 /**
  * Switches the automatic generation of TCs on and off
  * @param generate true if TCs should be generated every OLSRv2 TC interval,
@@ -782,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 e6b76b5..82403cc 100644 (file)
 #ifndef OLSRV2_INTERNAL_H_
 #define OLSRV2_INTERNAL_H_
 
+#include "common/common_types.h"
 #include "core/oonf_logging.h"
 
-/* headers only for use inside the NHDP subsystem */
-enum oonf_log_source LOG_OLSRV2;
-enum oonf_log_source LOG_OLSRV2_R;
-enum oonf_log_source LOG_OLSRV2_ROUTING;
-enum oonf_log_source LOG_OLSRV2_W;
+/* headers only for use inside the OLSRv2 subsystem */
+EXPORT enum oonf_log_source LOG_OLSRV2;
+EXPORT enum oonf_log_source LOG_OLSRV2_R;
+EXPORT enum oonf_log_source LOG_OLSRV2_ROUTING;
+EXPORT enum oonf_log_source LOG_OLSRV2_W;
 
 #endif /* OLSRV2_INTERNAL_H_ */
index 13ec129..917a67a 100644 (file)
@@ -97,6 +97,9 @@ struct _olsrv2_data {
 
   /*! number of entries in MPR type value */
   size_t mprtypes_size;
+
+  /*! true if a change happened for this domain */
+  bool changed[NHDP_MAXIMUM_DOMAINS];
 };
 
 /* Prototypes */
@@ -397,15 +400,19 @@ _cb_addresstlvs(struct rfc5444_reader_tlvblock_context *context __attribute__((u
 
         for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
           if (cost_out[i] <= RFC7181_METRIC_MAX) {
+            _current.changed[i] |= (edge->cost[i] != cost_out[i]);
             edge->cost[i] = cost_out[i];
           }
           else if (_current.complete_tc) {
+            _current.changed[i] |= (edge->cost[i] != RFC7181_METRIC_INFINITE);
             edge->cost[i] = RFC7181_METRIC_INFINITE;
           }
           if (edge->inverse->virtual && cost_in[i] <= RFC7181_METRIC_MAX) {
+            _current.changed[i] |= (edge->inverse->cost[i] != cost_in[i]);
             edge->inverse->cost[i] = cost_in[i];
           }
           else if (edge->inverse->virtual && _current.complete_tc) {
+            _current.changed[i] |= (edge->inverse->cost[i] != RFC7181_METRIC_INFINITE);
             edge->inverse->cost[i] = RFC7181_METRIC_INFINITE;
           }
         }
@@ -419,9 +426,11 @@ _cb_addresstlvs(struct rfc5444_reader_tlvblock_context *context __attribute__((u
         end->ansn = _current.node->ansn;
         for (i=0; i< NHDP_MAXIMUM_DOMAINS; i++) {
           if (cost_out[i] <= RFC7181_METRIC_MAX) {
+            _current.changed[i] |= (end->cost[i] != cost_out[i]);
             end->cost[i] = cost_out[i];
           }
           else if (_current.complete_tc) {
+            _current.changed[i] |= (end->cost[i] != RFC7181_METRIC_INFINITE);
             end->cost[i] = RFC7181_METRIC_INFINITE;
           }
         }
@@ -566,8 +575,11 @@ _cb_messagetlvs_end(struct rfc5444_reader_tlvblock_context *context __attribute_
   olsrv2_tc_trigger_change(_current.node);
   _current.node = NULL;
 
-  /* recalculate routing table */
-  olsrv2_routing_trigger_update();
+  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+    if (_current.changed[domain->index]) {
+      olsrv2_routing_domain_changed(domain);
+    }
+  }
 
   return RFC5444_OKAY;
 }
index d4adf1f..f834d8c 100644 (file)
@@ -51,6 +51,7 @@
 #include "common/list.h"
 #include "common/netaddr.h"
 #include "core/oonf_logging.h"
+#include "core/os_core.h"
 #include "subsystems/oonf_class.h"
 #include "subsystems/oonf_rfc5444.h"
 #include "subsystems/oonf_timer.h"
@@ -87,8 +88,11 @@ static void _handle_nhdp_routes(struct nhdp_domain *);
 static void _add_route_to_kernel_queue(struct olsrv2_routing_entry *rtentry);
 static void _process_dijkstra_result(struct nhdp_domain *);
 static void _process_kernel_queue(void);
+
+static void _cb_mpr_update(struct nhdp_domain *);
+static void _cb_metric_update(struct nhdp_domain *);
 static void _cb_trigger_dijkstra(struct oonf_timer_instance *);
-static void _cb_nhdp_update(struct nhdp_neighbor *);
+
 static void _cb_route_finished(struct os_route *route, int error);
 
 /* Domain parameter of dijkstra algorithm */
@@ -110,12 +114,19 @@ static struct oonf_timer_instance _rate_limit_timer = {
   .class = &_dijkstra_timer_info
 };
 
+static bool _trigger_dijkstra = false;
+
 /* callback for NHDP domain events */
 static struct nhdp_domain_listener _nhdp_listener = {
-  .update = _cb_nhdp_update,
+  .mpr_update = _cb_mpr_update,
+  .metric_update = _cb_metric_update,
 };
 
-static bool _trigger_dijkstra = false;
+/* status variables for domain changes */
+static uint16_t _ansn;
+static bool _domain_changed[NHDP_MAXIMUM_DOMAINS];
+static bool _update_ansn;
+
 
 /* global datastructures for routing */
 static struct avl_tree _routing_tree[NHDP_MAXIMUM_DOMAINS];
@@ -130,10 +141,20 @@ static bool _freeze_routes = false;
 /**
  * Initialize olsrv2 dijkstra and routing code
  */
-void
+int
 olsrv2_routing_init(void) {
   int i;
 
+  /* initialize domain change tracker */
+  if (os_core_get_random(&_ansn, sizeof(_ansn))) {
+    return -1;
+  }
+
+  nhdp_domain_listener_add(&_nhdp_listener);
+  memset(_domain_changed, 0, sizeof(_domain_changed));
+  _update_ansn = false;
+
+
   oonf_class_add(&_rtset_entry);
   oonf_timer_add(&_dijkstra_timer_info);
 
@@ -144,7 +165,7 @@ olsrv2_routing_init(void) {
   avl_init(&_dijkstra_working_tree, avl_comp_uint32, true);
   list_init_head(&_kernel_queue);
 
-  nhdp_domain_listener_add(&_nhdp_listener);
+  return 0;
 }
 
 /**
@@ -187,7 +208,6 @@ olsrv2_routing_cleanup(void) {
   int i;
 
   nhdp_domain_listener_remove(&_nhdp_listener);
-
   oonf_timer_stop(&_rate_limit_timer);
 
   for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
@@ -205,6 +225,14 @@ olsrv2_routing_cleanup(void) {
   oonf_class_remove(&_rtset_entry);
 }
 
+/**
+ * @return current answer set number for local topology database
+ */
+uint16_t
+olsrv2_routing_get_ansn(void) {
+  return _ansn;
+}
+
 /**
  * Trigger a new dijkstra as soon as we are back in the mainloop
  * (unless the rate limitation timer is active, then we will wait for it)
@@ -247,6 +275,24 @@ olsrv2_routing_get_parameters(struct nhdp_domain *domain) {
   return &_domain_parameter[domain->index];
 }
 
+/**
+ * Mark a domain as changed to trigger a dijkstra run
+ * @param domain NHDP domain, NULL for all domains
+ */
+void
+olsrv2_routing_domain_changed(struct nhdp_domain *domain) {
+  if (domain) {
+    _domain_changed[domain->index] = true;
+
+    olsrv2_routing_trigger_update();
+    return;
+  }
+
+  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+    olsrv2_routing_domain_changed(domain);
+  }
+}
+
 /**
  * Trigger dijkstra and routing update now
  * @param skip_wait true to ignore rate limitation timer
@@ -273,9 +319,22 @@ olsrv2_routing_force_update(bool skip_wait) {
     oonf_timer_stop(&_rate_limit_timer);
   }
 
+  if (_update_ansn) {
+    _ansn++;
+    _update_ansn = false;
+    OONF_DEBUG(LOG_OLSRV2_ROUTING, "Update ANSN to %u", _ansn);
+  }
+
   OONF_DEBUG(LOG_OLSRV2_ROUTING, "Run Dijkstra");
 
   list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+    /* check if dijkstra is necessary */
+    if (!_domain_changed[domain->index]) {
+      /* nothing to do for this domain */
+      continue;
+    }
+    _domain_changed[domain->index] = false;
+
     /* initialize dijkstra specific fields */
     _prepare_routes(domain);
     _prepare_nodes();
@@ -390,6 +449,32 @@ olsrv2_routing_get_filter_list(void) {
   return &_routing_filter_list;
 }
 
+/**
+ * Callback triggered when an MPR-set changed
+ * @param domain NHDP domain that changed
+ */
+static void
+_cb_mpr_update(struct nhdp_domain *domain) {
+  OONF_INFO(LOG_OLSRV2, "MPR update for domain %u", domain->index);
+
+  _update_ansn = true;
+  _domain_changed[domain->index] = true;
+  olsrv2_routing_trigger_update();
+}
+
+/**
+ * Callback triggered when an outgoing metric changed
+ * @param domain NHDP domain that changed
+ */
+static void
+_cb_metric_update(struct nhdp_domain *domain) {
+  OONF_INFO(LOG_OLSRV2, "Metric update for domain %u", domain->index);
+
+  _update_ansn = true;
+  _domain_changed[domain->index] = true;
+  olsrv2_routing_trigger_update();
+}
+
 /**
  * Run Dijkstra for a set domain, address family and
  * (non-)source-specific nodes
@@ -617,7 +702,7 @@ _update_routing_entry(struct nhdp_domain *domain,
       netaddr_to_string(&nbuf1, &rtentry->route.p.key.dst),
       netaddr_to_string(&nbuf2, &rtentry->route.p.key.src),
       netaddr_to_string(&nbuf3, &first_hop->originator),
-      domain->ext, pathcost, neighdata->best_link->local_if->os_if_listener.data->name);
+      domain->ext, pathcost, neighdata->best_out_link->local_if->os_if_listener.data->name);
 
   /* remember originator */
   memcpy(&rtentry->originator, dst_originator, sizeof(struct netaddr));
@@ -633,12 +718,12 @@ _update_routing_entry(struct nhdp_domain *domain,
 
   /* copy gateway if necessary */
   if (single_hop
-      && netaddr_cmp(&neighdata->best_link->if_addr,
+      && netaddr_cmp(&neighdata->best_out_link->if_addr,
           &rtentry->route.p.key.dst) == 0) {
     netaddr_invalidate(&rtentry->route.p.gw);
   }
   else {
-    memcpy(&rtentry->route.p.gw, &neighdata->best_link->if_addr,
+    memcpy(&rtentry->route.p.gw, &neighdata->best_out_link->if_addr,
         sizeof(struct netaddr));
   }
 }
@@ -1098,15 +1183,6 @@ _cb_trigger_dijkstra(struct oonf_timer_instance *ptr __attribute__((unused))) {
   }
 }
 
-/**
- * Callback triggered when neighbor metrics are updates
- * @param neigh
- */
-static void
-_cb_nhdp_update(struct nhdp_neighbor *neigh __attribute__((unused))) {
-  olsrv2_routing_trigger_update();
-}
-
 /**
  * Callback for kernel route processing results
  * @param route pointer to kernel route
index 3b3eac5..225a5ac 100644 (file)
@@ -179,16 +179,18 @@ struct olsrv2_routing_filter {
   struct list_entity _node;
 };
 
-void olsrv2_routing_init(void);
+int olsrv2_routing_init(void);
 void olsrv2_routing_initiate_shutdown(void);
 void olsrv2_routing_cleanup(void);
 
 void olsrv2_routing_dijkstra_node_init(
     struct olsrv2_dijkstra_node *, const struct netaddr *originator);
 
+EXPORT uint16_t olsrv2_routing_get_ansn(void);
 EXPORT void olsrv2_routing_set_domain_parameter(struct nhdp_domain *domain,
     struct olsrv2_routing_domain *parameter);
 
+EXPORT void olsrv2_routing_domain_changed(struct nhdp_domain *domain);
 EXPORT void olsrv2_routing_force_update(bool skip_wait);
 EXPORT void olsrv2_routing_trigger_update(void);
 
index 6b0f6d4..69c5703 100644 (file)
@@ -236,6 +236,9 @@ olsrv2_tc_node_remove(struct olsrv2_tc_node *node) {
     avl_remove(&_tc_tree, &node->_originator_node);
     oonf_class_free(&_tc_node_class, node);
   }
+
+  /* all domains might have changed */
+  olsrv2_routing_domain_changed(NULL);
 }
 
 /**
@@ -326,6 +329,9 @@ olsrv2_tc_edge_add(struct olsrv2_tc_node *src, struct netaddr *addr) {
  */
 bool
 olsrv2_tc_edge_remove(struct olsrv2_tc_edge *edge) {
+  /* all domains might have changed */
+  olsrv2_routing_domain_changed(NULL);
+
   return _remove_edge(edge, true);
 }
 
@@ -423,6 +429,9 @@ olsrv2_tc_endpoint_remove(
 
   /* free attached network */
   oonf_class_free(&_tc_attached_class, net);
+
+  /* all domains might have changed */
+  olsrv2_routing_domain_changed(NULL);
 }
 
 /**
index 52e11bd..9612846 100644 (file)
@@ -59,6 +59,7 @@
 #include "olsrv2/olsrv2_internal.h"
 #include "olsrv2/olsrv2_lan.h"
 #include "olsrv2/olsrv2_originator.h"
+#include "olsrv2/olsrv2_routing.h"
 #include "olsrv2/olsrv2_writer.h"
 
 /* constants */
@@ -565,7 +566,7 @@ _cb_finishMessageTLVs(struct rfc5444_writer *writer,
   uint16_t ansn;
 
   /* get ANSN */
-  ansn = htons(olsrv2_update_ansn(false));
+  ansn = htons(olsrv2_routing_get_ansn());
 
   rfc5444_writer_set_messagetlv(writer, RFC7181_MSGTLV_CONT_SEQ_NUM,
       complete ? RFC7181_CONT_SEQ_NUM_COMPLETE : RFC7181_CONT_SEQ_NUM_INCOMPLETE,
index 666cb01..97fe8ba 100644 (file)
@@ -230,6 +230,16 @@ oonf_class_get_extension(struct oonf_class_extension *ext, void *ptr) {
   return ((char *)ptr) + ext->_offset;
 }
 
+/**
+ * @param ext extension data structure
+ * @param ptr pointer to extension block
+ * @return pointer to extensions base block
+ */
+static INLINE void *
+oonf_class_get_base(struct oonf_class_extension *ext, void *ptr) {
+  return ((char *)ptr) - ext->_offset;
+}
+
 /**
  * @param ext pointer to class extension
  * @return true if extension is registered
index ca9d73e..4e6a060 100644 (file)
@@ -57,6 +57,8 @@ IF (NOT OONF_STATIC_PLUGINS)
                              lan_import
                              auto_ll4
                              http
+                             mpr
+                             remotecontrol
                              )
 ENDIF (NOT OONF_STATIC_PLUGINS)