Several bugfixes for MPR and willingness handling
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 12 Aug 2015 12:40:02 +0000 (14:40 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 12 Aug 2015 12:40:02 +0000 (14:40 +0200)
14 files changed:
src-plugins/nhdp/mpr/mpr.c
src-plugins/nhdp/mpr/neighbor-graph-flooding.c
src-plugins/nhdp/mpr/neighbor-graph-flooding.h
src-plugins/nhdp/mpr/neighbor-graph-routing.c
src-plugins/nhdp/mpr/neighbor-graph-routing.h
src-plugins/nhdp/mpr/neighbor-graph.c
src-plugins/nhdp/mpr/neighbor-graph.h
src-plugins/nhdp/mpr/selection-rfc7181.c
src-plugins/nhdp/mpr/selection-rfc7181.h
src-plugins/nhdp/nhdp/nhdp.c
src-plugins/nhdp/nhdp/nhdp_domain.c
src-plugins/nhdp/nhdp/nhdp_domain.h
src-plugins/nhdp/nhdp/nhdp_reader.c
src-plugins/nhdp/nhdpinfo/nhdpinfo.c

index f32bbb3..59e188f 100644 (file)
 
 /* FIXME remove unneeded includes */
 
+/* definitions */
+#define LOG_MPR _nhdp_mpr_subsystem.logging
+
 /* prototypes */
-static void _early_cfg_init(void);
 static int _init(void);
 static void _cleanup(void);
 static void _cb_update_mpr(void);
-static void _cb_cfg_changed(void);
-
-/* plugin declaration */
-static struct cfg_schema_entry _mpr_rfc_entries[] = {
-  /* FIXME Shouldn't this be configurable per domain? What about flooding 
-   * willingness? */
-  CFG_MAP_INT32_MINMAX(nhdp_domain_mpr, willingness, "willingness",
-      RFC7181_WILLINGNESS_DEFAULT_STRING, "Routing willingness", 0, false,
-      RFC7181_WILLINGNESS_MIN, RFC7181_WILLINGNESS_MAX),
-//  CFG_MAP_BOOL(nhdp_domain_mpr, mpr_start, "mpr_start",
-//    "false", "Default value for neighbor MPR setting"),
-//  CFG_MAP_BOOL(nhdp_domain_mpr, mprs_start, "mprs_start",
-//      "false", "Default value for local MPR (selector) setting"),
-};
-
-static struct cfg_schema_section _mpr_rfc_section = {
-  .type = OONF_MPR_SUBSYSTEM,
-  .cb_delta_handler = _cb_cfg_changed,
-  .entries = _mpr_rfc_entries,
-  .entry_count = ARRAYSIZE(_mpr_rfc_entries),
-};
 
 static const char *_dependencies[] = {
   OONF_CLASS_SUBSYSTEM,
   OONF_TIMER_SUBSYSTEM,
   OONF_NHDP_SUBSYSTEM,
 };
-static struct oonf_subsystem _olsrv2_mpr_subsystem = {
+static struct oonf_subsystem _nhdp_mpr_subsystem = {
   .name = OONF_MPR_SUBSYSTEM,
   .dependencies = _dependencies,
   .dependencies_count = ARRAYSIZE(_dependencies),
-  .descr = "OLSRv2 MPR Plugin",
+  .descr = "RFC7181 Appendix B MPR Plugin",
   .author = "Jonathan Kirchhoff",
 
-  .cfg_section = &_mpr_rfc_section,
-
-  .early_cfg_init = _early_cfg_init,
   .init = _init,
   .cleanup = _cleanup,
 };
-DECLARE_OONF_PLUGIN(_olsrv2_mpr_subsystem);
-
-enum oonf_log_source LOG_MPR;
+DECLARE_OONF_PLUGIN(_nhdp_mpr_subsystem);
 
 static struct nhdp_domain_mpr _mpr_handler = {
   .name = OONF_MPR_SUBSYSTEM,
   .update_mpr = _cb_update_mpr,
-  .willingness = RFC7181_WILLINGNESS_DEFAULT,
   .mpr_start = false,
   .mprs_start = false,
 };
 
-static void
-_early_cfg_init(void) {
-  LOG_MPR = _olsrv2_mpr_subsystem.logging;
-}
-
 /**
  * Initialize plugin
  * @return -1 if an error happened, 0 otherwise
@@ -138,10 +108,6 @@ _init(void) {
   if (nhdp_domain_mpr_add(&_mpr_handler)) {
     return -1;
   }
-
-  nhdp_domain_set_flooding_mpr(&_mpr_handler, 0);
-
-  OONF_DEBUG(LOG_MPR, "Initializing");
   return 0;
 }
 
@@ -226,6 +192,11 @@ _update_flooding_mpr(void) {
 
   memset(&flooding_data, 0, sizeof(flooding_data));
   
+  if (nhdp_domain_get_flooding()->mpr != &_mpr_handler) {
+    /* we are not the flooding mpr */
+    return;
+  }
+
   /* FIXME Currently, the flooding set is calculated incrementally (i.e. 
    in a coordinated way as suggested by RFC 7181; however, this should
    be configurable (and other selection algorithms might not be compatible
@@ -240,8 +211,8 @@ _update_flooding_mpr(void) {
         nhdp_interface_get_name(flooding_data.current_interface));
     
     mpr_calculate_neighbor_graph_flooding(
-        nhdp_domain_get_flooding_mpr()->domain, &flooding_data);
-    mpr_calculate_mpr_rfc7181(nhdp_domain_get_flooding_mpr()->domain,
+        nhdp_domain_get_flooding(), &flooding_data);
+    mpr_calculate_mpr_rfc7181(nhdp_domain_get_flooding(),
         &flooding_data.neigh_graph);
     mpr_print_sets(&flooding_data.neigh_graph);
     _update_nhdp_flooding(&flooding_data.neigh_graph);
@@ -257,6 +228,10 @@ _update_routing_mpr(void) {
   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;
+    }
     memset(&routing_graph, 0, sizeof(routing_graph));
 
     mpr_calculate_neighbor_graph_routing(domain, &routing_graph);
@@ -282,23 +257,6 @@ _cb_update_mpr(void) {
   OONF_DEBUG(LOG_MPR, "Finished recalculating MPRs");
 }
 
-/**
- * Callback triggered when configuration changes
- * 
- * FIXME Currently a stub
- */
-static void
-_cb_cfg_changed(void) {
-  OONF_DEBUG(LOG_MPR, "Config changed");
-
-  if (cfg_schema_tobin(&_mpr_handler, _mpr_rfc_section.post,
-      _mpr_rfc_entries, ARRAYSIZE(_mpr_rfc_entries))) {
-    OONF_WARN(LOG_MPR, "Cannot convert configuration for "
-        OONF_MPR_SUBSYSTEM);
-    return;
-  }
-}
-
 #if 0
 
 /**
index 0d8f214..4703c03 100644 (file)
 
 /* FIXME remove unneeded includes */
 
-static uint32_t _calculate_d1_x(struct nhdp_domain *domain, struct n1_node *x);
-static uint32_t _calculate_d2_x_y(struct nhdp_domain *domain,
+static uint32_t _calculate_d1_x(const struct nhdp_domain *domain, struct n1_node *x);
+static uint32_t _calculate_d2_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y);
-static uint32_t _calculate_d_x_y(struct nhdp_domain *domain,
+static uint32_t _calculate_d_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y);
 #if 0
 static uint32_t _calculate_d1_of_y(struct mpr_flooding_data *data, struct addr_node *y);
 #endif
-static uint32_t _calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
+static uint32_t _calculate_d1_x_of_n2_addr(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct netaddr *addr);
-static void _calculate_n1(struct nhdp_domain *domain, struct mpr_flooding_data *data);
-static void _calculate_n2(struct nhdp_domain *domain, struct mpr_flooding_data *data);
+static void _calculate_n1(const struct nhdp_domain *domain, struct mpr_flooding_data *data);
+static void _calculate_n2(const struct nhdp_domain *domain, struct mpr_flooding_data *data);
 
-static bool _is_allowed_link_tuple(struct nhdp_domain *domain,
+static bool _is_allowed_link_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface, struct nhdp_link *lnk);
-static uint32_t _get_willingness_n1(struct nhdp_domain *, struct n1_node *node);
+static uint32_t _get_willingness_n1(const struct nhdp_domain *, struct n1_node *node);
 
 static struct neighbor_graph_interface _api_interface = {
   .is_allowed_link_tuple     = _is_allowed_link_tuple,
@@ -94,7 +94,7 @@ static struct neighbor_graph_interface _api_interface = {
  * @return 
  */
 static bool
-_is_reachable_link_tuple(struct nhdp_domain *domain,
+_is_reachable_link_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface, struct nhdp_link *lnk) {
   struct nhdp_link_domaindata *linkdata;
 
@@ -114,7 +114,7 @@ _is_reachable_link_tuple(struct nhdp_domain *domain,
  * @return 
  */
 static bool
-_is_allowed_link_tuple(struct nhdp_domain *domain,
+_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) {
@@ -124,7 +124,7 @@ _is_allowed_link_tuple(struct nhdp_domain *domain,
 }
 
 static bool
-_is_allowed_2hop_tuple(struct nhdp_domain *domain,
+_is_allowed_2hop_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface, struct nhdp_l2hop *two_hop) {
   struct nhdp_l2hop_domaindata *twohopdata;
 
@@ -137,7 +137,7 @@ _is_allowed_2hop_tuple(struct nhdp_domain *domain,
 }
 
 static uint32_t
-_calculate_d1_x(struct nhdp_domain *domain, struct n1_node *x) {
+_calculate_d1_x(const struct nhdp_domain *domain, struct n1_node *x) {
   struct nhdp_link_domaindata *linkdata;
 
   linkdata = nhdp_domain_get_linkdata(domain, x->link);
@@ -145,7 +145,7 @@ _calculate_d1_x(struct nhdp_domain *domain, struct n1_node *x) {
 }
 
 static uint32_t
-_calculate_d2_x_y(struct nhdp_domain *domain,
+_calculate_d2_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y) {
   struct nhdp_l2hop *tmp_l2hop;
   struct nhdp_l2hop_domaindata *twohopdata;
@@ -161,7 +161,7 @@ _calculate_d2_x_y(struct nhdp_domain *domain,
 }
 
 static uint32_t
-_calculate_d_x_y(struct nhdp_domain *domain,
+_calculate_d_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y) {
   return _calculate_d1_x(domain, x) + _calculate_d2_x_y(domain, x, y);
 }
@@ -196,7 +196,7 @@ _calculate_d1_of_y(struct mpr_flooding_data *data, struct addr_node *y) {
  * @return 
  */
 uint32_t
-_calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
+_calculate_d1_x_of_n2_addr(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct netaddr *addr) {
   struct n1_node *node_n1;
   struct nhdp_naddr *naddr;
@@ -222,7 +222,7 @@ _calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
  * @param interf
  */
 static void
-_calculate_n1(struct nhdp_domain *domain, struct mpr_flooding_data *data) {
+_calculate_n1(const struct nhdp_domain *domain, struct mpr_flooding_data *data) {
   struct nhdp_link *lnk;
 
   OONF_DEBUG(LOG_MPR, "Calculate N1 for interface %s",
@@ -249,7 +249,7 @@ _calculate_n1(struct nhdp_domain *domain, struct mpr_flooding_data *data) {
  * @return 
  */
 static void
-_calculate_n2(struct nhdp_domain *domain, struct mpr_flooding_data *data) {
+_calculate_n2(const struct nhdp_domain *domain, struct mpr_flooding_data *data) {
   struct n1_node *n1_neigh;
   struct nhdp_l2hop *twohop;
 
@@ -274,13 +274,13 @@ _calculate_n2(struct nhdp_domain *domain, struct mpr_flooding_data *data) {
  * @return 
  */
 static uint32_t
-_get_willingness_n1(struct nhdp_domain *domain __attribute__((unused)),
+_get_willingness_n1(const struct nhdp_domain *domain __attribute__((unused)),
     struct n1_node *node) {
   return node->neigh->flooding_willingness;
 }
 
 void
-mpr_calculate_neighbor_graph_flooding(struct nhdp_domain *domain, struct mpr_flooding_data *data) {
+mpr_calculate_neighbor_graph_flooding(const struct nhdp_domain *domain, struct mpr_flooding_data *data) {
   OONF_DEBUG(LOG_MPR, "Calculate neighbor graph for flooding MPRs");
 
   mpr_init_neighbor_graph(&data->neigh_graph, &_api_interface);
index 0aaca70..e977d52 100644 (file)
@@ -54,6 +54,6 @@ struct mpr_flooding_data {
 };
 
 void mpr_calculate_neighbor_graph_flooding(
-    struct nhdp_domain *domain, struct mpr_flooding_data *data);
+    const struct nhdp_domain *domain, struct mpr_flooding_data *data);
 
 #endif
index 2afd20e..5f81a3c 100644 (file)
 
 /* FIXME remove unneeded includes */
 
-static bool _is_allowed_link_tuple(struct nhdp_domain *domain,
+static bool _is_allowed_link_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface, struct nhdp_link *lnk);
-static uint32_t _calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
+static uint32_t _calculate_d1_x_of_n2_addr(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct netaddr *addr);
-static uint32_t _calculate_d_x_y(struct nhdp_domain *domain,
+static uint32_t _calculate_d_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y);
-static uint32_t _calculate_d2_x_y(struct nhdp_domain *domain,
+static uint32_t _calculate_d2_x_y(const struct nhdp_domain *domain,
     struct n1_node *x, struct addr_node *y);
-static uint32_t _get_willingness_n1(struct nhdp_domain *domain,
+static uint32_t _get_willingness_n1(const struct nhdp_domain *domain,
     struct n1_node *node);
 
-static uint32_t _calculate_d1_of_y(struct nhdp_domain *domain,
+static uint32_t _calculate_d1_of_y(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct addr_node *y);
 
 static struct neighbor_graph_interface _rt_api_interface = {
@@ -106,7 +106,7 @@ _is_reachable_neighbor_tuple(struct nhdp_neighbor *neigh) {
  * @return 
  */
 static bool
-_is_allowed_neighbor_tuple(struct nhdp_domain *domain __attribute__((unused)),
+_is_allowed_neighbor_tuple(const struct nhdp_domain *domain __attribute__((unused)),
     struct nhdp_neighbor *neigh) {
   if (_is_reachable_neighbor_tuple(neigh)) {
     // FIXME Willingness handling appears to be broken; routing willingness is always 0
@@ -117,7 +117,7 @@ _is_allowed_neighbor_tuple(struct nhdp_domain *domain __attribute__((unused)),
 }
 
 static bool
-_is_allowed_link_tuple(struct nhdp_domain *domain,
+_is_allowed_link_tuple(const struct nhdp_domain *domain,
     struct nhdp_interface *current_interface __attribute__((unused)),
     struct nhdp_link *lnk) {
   return _is_allowed_neighbor_tuple(domain, lnk->neigh);
@@ -138,7 +138,7 @@ _is_allowed_2hop_tuple(struct nhdp_l2hop *two_hop) {
  * @return 
  */
 static uint32_t
-_calculate_d1_x(struct nhdp_domain *domain, struct n1_node *x) {
+_calculate_d1_x(const struct nhdp_domain *domain, struct n1_node *x) {
   struct nhdp_neighbor_domaindata *neighdata;
 
   neighdata = nhdp_domain_get_neighbordata(domain, x->neigh);
@@ -152,7 +152,7 @@ _calculate_d1_x(struct nhdp_domain *domain, struct n1_node *x) {
  * @return 
  */
 static uint32_t
-_calculate_d2_x_y(struct nhdp_domain *domain, struct n1_node *x, struct addr_node *y) {
+_calculate_d2_x_y(const struct nhdp_domain *domain, struct n1_node *x, struct addr_node *y) {
   struct nhdp_l2hop *l2hop;
   struct nhdp_link *lnk;
   struct nhdp_l2hop_domaindata *twohopdata;
@@ -170,7 +170,7 @@ _calculate_d2_x_y(struct nhdp_domain *domain, struct n1_node *x, struct addr_nod
 }
 
 static uint32_t
-_calculate_d_x_y(struct nhdp_domain *domain, struct n1_node *x, struct addr_node *y) {
+_calculate_d_x_y(const struct nhdp_domain *domain, struct n1_node *x, struct addr_node *y) {
   return _calculate_d1_x(domain, x) + _calculate_d2_x_y(domain, x, y);
 }
 
@@ -180,7 +180,7 @@ _calculate_d_x_y(struct nhdp_domain *domain, struct n1_node *x, struct addr_node
  * @return 
  */
 static uint32_t
-_calculate_d1_of_y(struct nhdp_domain *domain,
+_calculate_d1_of_y(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct addr_node *y) {
   struct n1_node *node_n1;
   struct nhdp_laddr *laddr;
@@ -205,7 +205,7 @@ _calculate_d1_of_y(struct nhdp_domain *domain,
  * @return 
  */
 static uint32_t
-_calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
+_calculate_d1_x_of_n2_addr(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct netaddr *addr) {
   struct addr_node *node;
   uint32_t d1_x;
@@ -224,7 +224,7 @@ _calculate_d1_x_of_n2_addr(struct nhdp_domain *domain,
  * @param interf
  */
 static void
-_calculate_n1(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+_calculate_n1(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   struct nhdp_neighbor *neigh;
 
   OONF_DEBUG(LOG_MPR, "Calculate N1 for routing MPRs");
@@ -271,7 +271,7 @@ _calculate_n2(struct neighbor_graph *graph) {
  * @return 
  */
 static uint32_t
-_get_willingness_n1(struct nhdp_domain *domain, struct n1_node *node) {
+_get_willingness_n1(const struct nhdp_domain *domain, struct n1_node *node) {
   struct nhdp_neighbor_domaindata *neighdata;
 
   neighdata = nhdp_domain_get_neighbordata(domain, node->neigh);
@@ -284,7 +284,7 @@ neighbor_graph_interface *_get_neighbor_graph_interface_routing(void) {
 }
 
 void
-mpr_calculate_neighbor_graph_routing(struct nhdp_domain *domain,
+mpr_calculate_neighbor_graph_routing(const struct nhdp_domain *domain,
     struct neighbor_graph *graph) {
   struct neighbor_graph_interface *methods;
 
index 80a9760..22b4617 100644 (file)
@@ -46,7 +46,7 @@
 
 #include "nhdp/nhdp_domain.h"
 
-void mpr_calculate_neighbor_graph_routing(struct nhdp_domain *domain,
+void mpr_calculate_neighbor_graph_routing(const struct nhdp_domain *domain,
     struct neighbor_graph *graph);
 
 #endif
index 8ef249e..0f6210e 100644 (file)
@@ -164,7 +164,7 @@ mpr_is_mpr(struct neighbor_graph *graph, struct netaddr *addr) {
 }
 
 uint32_t
-mpr_calculate_minimal_d_z_y(struct nhdp_domain *domain,
+mpr_calculate_minimal_d_z_y(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct addr_node *y) {
   struct n1_node *z_node;
   uint32_t d_z_y, min_d_z_y;
index b40ea42..ea26331 100644 (file)
@@ -52,15 +52,15 @@ struct addr_node;
 struct n1_node;
 
 struct neighbor_graph_interface {    
-    bool (*is_allowed_link_tuple)(struct nhdp_domain *,
+    bool (*is_allowed_link_tuple)(const struct nhdp_domain *,
         struct nhdp_interface *current_interface, struct nhdp_link *link);
-    uint32_t (*calculate_d1_x_of_n2_addr)(struct nhdp_domain *,
+    uint32_t (*calculate_d1_x_of_n2_addr)(const struct nhdp_domain *,
         struct neighbor_graph*, struct netaddr*);
-    uint32_t (*calculate_d_x_y)(struct nhdp_domain *,
+    uint32_t (*calculate_d_x_y)(const struct nhdp_domain *,
         struct n1_node*, struct addr_node*);
-    uint32_t (*calculate_d2_x_y)(struct nhdp_domain *,
+    uint32_t (*calculate_d2_x_y)(const struct nhdp_domain *,
         struct n1_node*, struct addr_node*);
-    uint32_t (*get_willingness_n1)(struct nhdp_domain *, struct n1_node*);
+    uint32_t (*get_willingness_n1)(const struct nhdp_domain *, struct n1_node*);
 };
 
 struct neighbor_graph {
@@ -101,7 +101,7 @@ void mpr_clear_neighbor_graph(struct neighbor_graph *graph);
 
 bool mpr_is_mpr(struct neighbor_graph *graph, struct netaddr *addr);
 
-uint32_t mpr_calculate_minimal_d_z_y(struct nhdp_domain *,
+uint32_t mpr_calculate_minimal_d_z_y(const struct nhdp_domain *,
     struct neighbor_graph *graph, struct addr_node *y);
 
 void mpr_print_addr_set(struct avl_tree *set);
index 2947fc0..0065da7 100644 (file)
@@ -63,8 +63,8 @@
 
 /* FIXME remove unneeded includes */
 
-static void _calculate_n(struct nhdp_domain *domain, struct neighbor_graph *graph);
-static unsigned int _calculate_r(struct nhdp_domain *domain,
+static void _calculate_n(const struct nhdp_domain *domain, struct neighbor_graph *graph);
+static unsigned int _calculate_r(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct n1_node *x_node);
 
 /**
@@ -79,7 +79,7 @@ static unsigned int _calculate_r(struct nhdp_domain *domain,
  * @return 
  */
 static void
-_calculate_n(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+_calculate_n(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   struct addr_node *y_node;
   uint32_t d1_y;
   struct n1_node *x_node;
@@ -126,7 +126,7 @@ _calculate_n(struct nhdp_domain *domain, struct neighbor_graph *graph) {
  * @return 
  */
 static unsigned int
-_calculate_r(struct nhdp_domain *domain, struct neighbor_graph *graph,
+_calculate_r(const struct nhdp_domain *domain, struct neighbor_graph *graph,
     struct n1_node *x_node) {
   struct addr_node *y_node;
   struct n1_node *z_node;
@@ -185,7 +185,7 @@ _calculate_r(struct nhdp_domain *domain, struct neighbor_graph *graph,
  * @param current_mpr_data
  */
 static void
-_process_will_always(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+_process_will_always(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   struct n1_node *current_n1_node;
 #ifdef OONF_LOG_DEBUG_INFO
   struct netaddr_str buf1;
@@ -209,7 +209,7 @@ _process_will_always(struct nhdp_domain *domain, struct neighbor_graph *graph) {
  * @param current_mpr_data
  */
 static void
-_process_unique_mprs(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+_process_unique_mprs(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   struct n1_node *node_n1, *possible_mpr_node;
   struct addr_node *node_n;
   uint32_t possible_mprs;
@@ -256,9 +256,9 @@ _process_unique_mprs(struct nhdp_domain *domain, struct neighbor_graph *graph) {
  * @return 
  */
 static void
-_select_greatest_by_property(struct nhdp_domain *domain,
+_select_greatest_by_property(const struct nhdp_domain *domain,
     struct neighbor_graph *graph,
-    uint32_t(*get_property)(struct nhdp_domain *, struct neighbor_graph*, struct n1_node*)) {
+    uint32_t(*get_property)(const struct nhdp_domain *, struct neighbor_graph*, struct n1_node*)) {
   struct avl_tree *n1_subset, tmp_candidate_subset;
   struct n1_node *node_n1,
       *greatest_prop_node;
@@ -323,7 +323,7 @@ _select_greatest_by_property(struct nhdp_domain *domain,
 // FIXME Wrapper required for having the correct signature...
 
 static uint32_t
-_get_willingness_n1(struct nhdp_domain *domain,
+_get_willingness_n1(const struct nhdp_domain *domain,
     struct neighbor_graph *graph, struct n1_node *node) {
   return graph->methods->get_willingness_n1(domain, node);
 }
@@ -333,7 +333,7 @@ _get_willingness_n1(struct nhdp_domain *domain,
  * @param current_mpr_data
  */
 static void
-_process_remaining(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+_process_remaining(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   struct n1_node *node_n1;
   bool done;
 
@@ -381,7 +381,7 @@ _process_remaining(struct nhdp_domain *domain, struct neighbor_graph *graph) {
  * Calculate MPR
  */
 void
-mpr_calculate_mpr_rfc7181(struct nhdp_domain *domain, struct neighbor_graph *graph) {
+mpr_calculate_mpr_rfc7181(const struct nhdp_domain *domain, struct neighbor_graph *graph) {
   OONF_DEBUG(LOG_MPR, "Calculate MPR set");
 
   _calculate_n(domain, graph);
index a54e33a..d92a885 100644 (file)
@@ -46,6 +46,6 @@
 
 #include "nhdp/nhdp_domain.h"
 
-void mpr_calculate_mpr_rfc7181(struct nhdp_domain *, struct neighbor_graph *graph);
+void mpr_calculate_mpr_rfc7181(const struct nhdp_domain *, struct neighbor_graph *graph);
 
 #endif
index cf4cfac..79f0e8d 100644 (file)
 struct _domain_parameters {
   char metric_name[NHDP_DOMAIN_METRIC_MAXLEN];
   char mpr_name[NHDP_DOMAIN_MPR_MAXLEN];
+  uint8_t mpr_willingness;
+};
+
+struct _generic_parameters {
+  char mpr_name[NHDP_DOMAIN_MPR_MAXLEN];
+  uint8_t mpr_willingness;
 };
 
 /* prototypes */
@@ -67,10 +73,30 @@ static void _cleanup(void);
 
 static void _cb_cfg_domain_changed(void);
 static void _cb_cfg_interface_changed(void);
+static void _cb_cfg_nhdp_changed(void);
 static int _cb_validate_domain_section(const char *section_name,
     struct cfg_named_section *, struct autobuf *);
 
 /* subsystem definition */
+static struct cfg_schema_entry _nhdp_entries[] = {
+  CFG_MAP_STRING_ARRAY(_generic_parameters, mpr_name, "mpr", "*",
+      "ID of the mpr algorithm used for this domain. '"CFG_DOMAIN_NO_MPR"'"
+      " means no mpr algorithm (everyone is MPR), '"CFG_DOMAIN_ANY_MPR"' means"
+      " any metric that is loaded (with fallback on '"CFG_DOMAIN_NO_MPR"').",
+      NHDP_DOMAIN_MPR_MAXLEN),
+  CFG_MAP_INT32_MINMAX(_generic_parameters, mpr_willingness, "willingness",
+      RFC7181_WILLINGNESS_DEFAULT_STRING,
+      "Flooding willingness for MPR calculation", 0, false,
+      RFC7181_WILLINGNESS_MIN, RFC7181_WILLINGNESS_MAX),
+};
+
+static struct cfg_schema_section _nhdp_section = {
+  .type = OONF_NHDP_SUBSYSTEM,
+  .cb_delta_handler = _cb_cfg_nhdp_changed,
+  .entries = _nhdp_entries,
+  .entry_count = ARRAYSIZE(_nhdp_entries),
+};
+
 static struct cfg_schema_entry _interface_entries[] = {
   CFG_MAP_ACL_V46(nhdp_interface, ifaddr_filter, "ifaddr_filter",
       "-127.0.0.0/8\0-::1\0" ACL_DEFAULT_ACCEPT,
@@ -87,6 +113,7 @@ static struct cfg_schema_section _interface_section = {
   .cb_delta_handler = _cb_cfg_interface_changed,
   .entries = _interface_entries,
   .entry_count = ARRAYSIZE(_interface_entries),
+  .next_section = &_nhdp_section,
 };
 
 static struct cfg_schema_entry _domain_entries[] = {
@@ -100,6 +127,9 @@ static struct cfg_schema_entry _domain_entries[] = {
       " means no mpr algorithm (everyone is MPR), '"CFG_DOMAIN_ANY_MPR"' means"
       " any metric that is loaded (with fallback on '"CFG_DOMAIN_NO_MPR"').",
       NHDP_DOMAIN_MPR_MAXLEN),
+  CFG_MAP_INT32_MINMAX(_domain_parameters, mpr_willingness, "willingness",
+      RFC7181_WILLINGNESS_DEFAULT_STRING, "Routing willingness used for MPR calculation",
+      0, false, RFC7181_WILLINGNESS_MIN, RFC7181_WILLINGNESS_MAX),
 };
 
 static struct cfg_schema_section _domain_section = {
@@ -332,7 +362,8 @@ _cb_cfg_domain_changed(void) {
     return;
   }
 
-  nhdp_domain_configure(ext, param.metric_name, param.mpr_name);
+  nhdp_domain_configure(ext, param.metric_name,
+      param.mpr_name, param.mpr_willingness);
 }
 
 /**
@@ -370,6 +401,18 @@ _cb_cfg_interface_changed(void) {
   nhdp_interface_apply_settings(interf);
 }
 
+static void
+_cb_cfg_nhdp_changed(void) {
+  struct _generic_parameters param;
+  if (cfg_schema_tobin(&param, _nhdp_section.post,
+      _nhdp_entries, ARRAYSIZE(_nhdp_entries))) {
+    OONF_WARN(LOG_NHDP, "Cannot convert NHDP configuration.");
+    return;
+  }
+
+  nhdp_domain_set_flooding_mpr(param.mpr_name, param.mpr_willingness);
+}
+
 /**
  * Validate that the name of the domain section is valid
  * @param section_name name of section including type
index aad89cc..638a7a3 100644 (file)
 
 static void _apply_metric(struct nhdp_domain *domain, const char *metric_name);
 static void _remove_metric(struct nhdp_domain *);
-static void _apply_mpr(struct nhdp_domain *domain, const char *mpr_name);
+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 _recalculate_neighbor_metric(struct nhdp_domain *domain,
         struct nhdp_neighbor *neigh);
 static const char *_link_to_string(struct nhdp_metric_str *, uint32_t);
@@ -91,12 +94,13 @@ static struct nhdp_domain_metric _no_metric = {
 };
 
 /* default MPR handler (no MPR handling) */
-static struct nhdp_domain_mpr _no_mprs = {
+static struct nhdp_domain_mpr _everyone_mprs = {
   .name = "Everyone MPR",
 
   .mpr_start = true,
   .mprs_start = true,
-  .willingness = RFC7181_WILLINGNESS_DEFAULT,
+
+  .update_mpr = _cb_update_everyone_mpr,
 };
 
 /* non-default routing domains registered to NHDP */
@@ -106,12 +110,11 @@ static struct list_entity _domain_listener_list;
 static size_t _domain_counter = 0;
 
 /* tree of known routing metrics/mpr-algorithms */
-struct avl_tree nhdp_domain_metrics;
-struct avl_tree nhdp_domain_mprs;
+static struct avl_tree _domain_metrics;
+static struct avl_tree _domain_mprs;
 
-/* flooding MPR handler registered to NHDP */
-static struct nhdp_domain_mpr *_flooding_mpr = &_no_mprs;
-uint8_t _flooding_ext = 0;
+/* flooding domain */
+struct nhdp_domain _flooding_domain;
 
 /* NHDP RFC5444 protocol */
 static struct oonf_rfc5444_protocol *_protocol;
@@ -131,8 +134,15 @@ nhdp_domain_init(struct oonf_rfc5444_protocol *p) {
   list_init_head(&_domain_list);
   list_init_head(&_domain_listener_list);
 
-  avl_init(&nhdp_domain_metrics, avl_comp_strcasecmp, false);
-  avl_init(&nhdp_domain_mprs, avl_comp_strcasecmp, false);
+  avl_init(&_domain_metrics, avl_comp_strcasecmp, false);
+  avl_init(&_domain_mprs, avl_comp_strcasecmp, false);
+
+  /* initialize flooding domain */
+  _flooding_domain.metric = &_no_metric;
+  _flooding_domain.mpr = &_everyone_mprs;
+
+  _flooding_domain.mpr->_refcount++;
+  _flooding_domain.metric->_refcount++;
 }
 
 /**
@@ -170,14 +180,6 @@ nhdp_domain_get_count(void) {
   return _domain_counter;
 }
 
-/**
- * @return current flooding mpr
- */
-struct nhdp_domain_mpr *
-nhdp_domain_get_flooding_mpr(void) {
-  return _flooding_mpr;
-}
-
 /**
  * Add a new metric handler to nhdp
  * @param metric pointer to NHDP link metric
@@ -215,7 +217,7 @@ nhdp_domain_metric_add(struct nhdp_domain_metric *metric) {
   }
 
   /* hook into tree */
-  return avl_insert(&nhdp_domain_metrics, &metric->_node);
+  return avl_insert(&_domain_metrics, &metric->_node);
 }
 
 /**
@@ -233,7 +235,7 @@ nhdp_domain_metric_remove(struct nhdp_domain_metric *metric) {
     }
   }
 
-  avl_remove(&nhdp_domain_metrics, &metric->_node);
+  avl_remove(&_domain_metrics, &metric->_node);
 }
 
 /**
@@ -248,15 +250,19 @@ nhdp_domain_mpr_add(struct nhdp_domain_mpr *mpr) {
   /* initialize key */
   mpr->_node.key = mpr->name;
 
-  if (avl_insert(&nhdp_domain_mprs, &mpr->_node)) {
+  if (avl_insert(&_domain_mprs, &mpr->_node)) {
     return -1;
   }
 
   list_for_each_element(&_domain_list, domain, _node) {
-    if (domain->mpr == &_no_mprs) {
-      _apply_mpr(domain, domain->mpr_name);
+    if (domain->mpr == &_everyone_mprs) {
+      _apply_mpr(domain, domain->mpr_name, domain->local_willingness);
     }
   }
+  if (_flooding_domain.mpr == &_everyone_mprs) {
+    _apply_mpr(&_flooding_domain,
+        _flooding_domain.mpr_name, _flooding_domain.local_willingness);
+  }
   return 0;
 }
 
@@ -275,7 +281,7 @@ nhdp_domain_mpr_remove(struct nhdp_domain_mpr *mpr) {
     }
   }
 
-  avl_remove(&nhdp_domain_mprs, &mpr->_node);
+  avl_remove(&_domain_mprs, &mpr->_node);
 }
 
 /**
@@ -372,9 +378,9 @@ nhdp_domain_init_neighbor(struct nhdp_neighbor *neigh) {
   int i;
 
   /* initialize flooding MPR settings */
-  neigh->flooding_willingness = _flooding_mpr->willingness;
-  neigh->local_is_flooding_mpr = _flooding_mpr->mprs_start;
-  neigh->neigh_is_flooding_mpr = _flooding_mpr->mpr_start;
+  neigh->flooding_willingness = RFC7181_WILLINGNESS_NEVER;
+  neigh->local_is_flooding_mpr = _flooding_domain.mpr->mprs_start;
+  neigh->neigh_is_flooding_mpr = _flooding_domain.mpr->mpr_start;
 
   for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
     neigh->_domaindata[i].metric.in = RFC7181_METRIC_MAX;
@@ -390,7 +396,7 @@ nhdp_domain_init_neighbor(struct nhdp_neighbor *neigh) {
 
     data->best_link = NULL;
 
-    data->willingness = domain->mpr->willingness;
+    data->willingness = RFC7181_WILLINGNESS_NEVER;
     data->local_is_mpr = domain->mpr->mprs_start;
     data->neigh_is_mpr = domain->mpr->mpr_start;
   }
@@ -498,6 +504,7 @@ nhdp_domain_neighbor_changed(struct nhdp_neighbor *neigh) {
   struct nhdp_domain_listener *listener;
   struct nhdp_domain *domain;
   
+
   list_for_each_element(&_domain_list, domain, _node) {
     _recalculate_neighbor_metric(domain, neigh);
 
@@ -622,22 +629,25 @@ 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
+ * temporary storage in MPR handler object. Call
+ * nhdp_domain_store_willingness to permanently store them later.
+ * @param neighbor neighbor we received a willingness TLV from
  * @param mprtypes list of extenstions for MPR
  * @param mprtypes_size length of mprtypes array
  * @param tlvvalue willingness array to parse
  * @param tlvsize length of willingness array
  */
 void
-nhdp_domain_process_willingness_tlv(uint8_t *mprtypes, size_t mprtypes_size,
+nhdp_domain_process_willingness_tlv(
+    uint8_t *mprtypes, size_t mprtypes_size,
     struct rfc5444_reader_tlvblock_entry *tlv) {
   struct nhdp_domain *domain;
   size_t idx, i;
   uint8_t value;
 
-  _flooding_mpr->willingness = RFC7181_WILLINGNESS_NEVER;
+  _flooding_domain._tmp_willingness = RFC7181_WILLINGNESS_NEVER;
   list_for_each_element(&_domain_list, domain, _node) {
-    domain->mpr->willingness = RFC7181_WILLINGNESS_NEVER;
+    domain->_tmp_willingness= RFC7181_WILLINGNESS_NEVER;
   }
 
   if (!tlv) {
@@ -645,9 +655,10 @@ nhdp_domain_process_willingness_tlv(uint8_t *mprtypes, size_t mprtypes_size,
   }
 
   /* copy flooding willingness */
-  _flooding_mpr->willingness = tlv->single_value[0] & RFC7181_WILLINGNESS_MASK;
+  _flooding_domain._tmp_willingness
+    = tlv->single_value[0] & RFC7181_WILLINGNESS_MASK;
   OONF_DEBUG(LOG_NHDP_R, "Received flooding willingness: %u",
-      _flooding_mpr->willingness);
+      _flooding_domain._tmp_willingness);
 
   for (i=0; i<mprtypes_size; i++) {
     domain = nhdp_domain_get_by_ext(mprtypes[i]);
@@ -668,10 +679,27 @@ nhdp_domain_process_willingness_tlv(uint8_t *mprtypes, size_t mprtypes_size,
       value &= RFC7181_WILLINGNESS_MASK;
     }
 
-    domain->mpr->willingness = value;
+    domain->_tmp_willingness = value;
 
     OONF_DEBUG(LOG_NHDP_R, "Received routing willingness for domain %u: %u",
-        domain->ext, _flooding_mpr->willingness);
+        domain->ext, domain->_tmp_willingness);
+  }
+}
+
+/**
+ * Stores the willingness data processed by
+ * nhdp_domain_process_willingness_tlv() into a neighbor object
+ * @param neigh NHDP neighbor
+ */
+void
+nhdp_domain_store_willingness(struct nhdp_neighbor *neigh) {
+  struct nhdp_neighbor_domaindata *neighdata;
+  struct nhdp_domain *domain;
+
+  neigh->flooding_willingness = _flooding_domain._tmp_willingness;
+  list_for_each_element(&_domain_list, domain, _node) {
+    neighdata = nhdp_domain_get_neighbordata(domain, neigh);
+    neighdata->willingness = domain->_tmp_willingness;
   }
 }
 
@@ -760,9 +788,9 @@ nhdp_domain_encode_willingness_tlvvalue(uint8_t *tlvvalue, size_t tlvsize) {
   len = 0;
 
   /* set flooding willingness */
-  tlvvalue[0] = _flooding_mpr->willingness;
+  tlvvalue[0] = _flooding_domain.local_willingness;
   OONF_DEBUG(LOG_NHDP_W, "Set flooding willingness: %u",
-      _flooding_mpr->willingness);
+      _flooding_domain.local_willingness);
 
   /* set routing willingness */
   list_for_each_element(&_domain_list, domain, _node) {
@@ -774,7 +802,7 @@ nhdp_domain_encode_willingness_tlvvalue(uint8_t *tlvvalue, size_t tlvsize) {
       len = idx + 1;
     }
 
-    value = domain->mpr->willingness & RFC7181_WILLINGNESS_MASK;
+    value = domain->local_willingness & RFC7181_WILLINGNESS_MASK;
 
     OONF_DEBUG(LOG_NHDP_W, "Set routing willingness for domain %u: %u"
         " (%"PRINTF_SIZE_T_SPECIFIER")",
@@ -791,19 +819,12 @@ nhdp_domain_encode_willingness_tlvvalue(uint8_t *tlvvalue, size_t tlvsize) {
 
 /**
  * Sets a new flodding MPR algorithm
- * @param mpr pointer to flooding MPR handler
- * @param ext TLV extension to transport flooding MPR settings
+ * @param mpr_name name of MPR algorithm
+ * @param willingness of MPR algorithm
  */
 void
-nhdp_domain_set_flooding_mpr(struct nhdp_domain_mpr *mpr, uint8_t ext) {
-  if (mpr == NULL) {
-    _flooding_mpr = &_no_mprs;
-    _flooding_ext = 0;
-  }
-  else {
-    _flooding_mpr = mpr;
-    _flooding_ext = ext;
-  }
+nhdp_domain_set_flooding_mpr(const char *mpr_name, uint8_t willingness) {
+  _apply_mpr(&_flooding_domain, mpr_name, willingness);
 }
 
 /**
@@ -819,16 +840,14 @@ nhdp_domain_set_incoming_metric(struct nhdp_domain_metric *metric,
     struct nhdp_link *lnk, uint32_t metric_in) {
   struct nhdp_link_domaindata *linkdata;
   struct nhdp_domain *domain;
-  uint32_t old_metric;
   bool changed;
 
   changed = false;
   list_for_each_element(&_domain_list, domain, _node) {
     if (domain->metric == metric) {
       linkdata = nhdp_domain_get_linkdata(domain, lnk);
-      old_metric = linkdata->metric.in;
+      changed |= (linkdata->metric.in != metric_in);
       linkdata->metric.in = metric_in;
-      changed |= (old_metric != metric_in);
     }
   }
   return changed;
@@ -926,7 +945,10 @@ nhdp_domain_add(uint8_t ext) {
   domain->ext = ext;
   domain->index = _domain_counter++;
   domain->metric = &_no_metric;
-  domain->mpr = &_no_mprs;
+  domain->mpr = &_everyone_mprs;
+
+  domain->mpr->_refcount++;
+  domain->metric->_refcount++;
 
   /* initialize metric TLVs */
   for (i=0; i<4; i++) {
@@ -955,11 +977,13 @@ nhdp_domain_add(uint8_t ext) {
  *   might be CFG_DOMAIN_NO_MPR (every node is MPR)
  *   or CFG_DOMAIN_ANY_MPR (for a MPR the NHDP core should
  *   choose).
+ * @param willingness routing willingness for domain
  * @return pointer to configured domain, NULL, if out of memory or
  *   maximum number of domains has been reached.
  */
 struct nhdp_domain *
-nhdp_domain_configure(uint8_t ext, const char *metric_name, const char *mpr_name) {
+nhdp_domain_configure(uint8_t ext, const char *metric_name,
+    const char *mpr_name, uint8_t willingness) {
   struct nhdp_domain *domain;
 
   domain = nhdp_domain_add(ext);
@@ -967,8 +991,13 @@ nhdp_domain_configure(uint8_t ext, const char *metric_name, const char *mpr_name
     return NULL;
   }
 
+  OONF_DEBUG(LOG_NHDP, "Configure domain %u to metric=%s",
+      domain->index, metric_name);
   _apply_metric(domain, metric_name);
-  _apply_mpr(domain, mpr_name);
+
+  OONF_DEBUG(LOG_NHDP, "Configure domain %u to mpr=%s, willingness=%u",
+      domain->index, mpr_name, willingness);
+  _apply_mpr(domain, mpr_name, willingness);
 
   oonf_class_event(&_domain_class, domain, OONF_OBJECT_CHANGED);
 
@@ -988,30 +1017,32 @@ _apply_metric(struct nhdp_domain *domain, const char *metric_name) {
   struct nhdp_domain_metric *metric;
 
   /* check if we have to remove the old metric first */
-  if (strcasecmp(domain->metric_name, metric_name) != 0) {
-    if (domain->metric != &_no_metric) {
-      _remove_metric(domain);
-      strscpy(domain->metric_name, CFG_DOMAIN_NO_METRIC, sizeof(domain->metric_name));
-    }
+  if (strcasecmp(domain->metric_name, metric_name) == 0) {
+    /* nothing to do, we already have the right metric */
+    return;
+  }
+
+  if (domain->metric != &_no_metric) {
+    _remove_metric(domain);
   }
 
   /* Handle wildcard metric name first */
   if (strcasecmp(metric_name, CFG_DOMAIN_ANY_METRIC) == 0
-      && !avl_is_empty(&nhdp_domain_metrics)) {
-    metric_name = avl_first_element(&nhdp_domain_metrics, metric, _node)->name;
+      && !avl_is_empty(&_domain_metrics)) {
+    metric_name = avl_first_element(&_domain_metrics, metric, _node)->name;
   }
 
-  /* copy new metric name */
-  strscpy(domain->metric_name, metric_name, sizeof(domain->metric_name));
-
   /* look for metric implementation */
-  metric = avl_find_element(&nhdp_domain_metrics, metric_name, metric, _node);
+  metric = avl_find_element(&_domain_metrics, metric_name, metric, _node);
   if (metric == NULL) {
     domain->metric = &_no_metric;
-    return;
   }
 
+  /* copy new metric name */
+  strscpy(domain->metric_name, metric->name, sizeof(domain->metric_name));
+
   /* link domain and metric */
+  domain->metric->_refcount--;
   domain->metric = metric;
 
   /* activate metric */
@@ -1028,13 +1059,12 @@ _apply_metric(struct nhdp_domain *domain, const char *metric_name) {
 static void
 _remove_metric(struct nhdp_domain *domain) {
   domain->metric->_refcount--;
-  if (!domain->metric->_refcount) {
-    if (domain->metric->disable) {
-      domain->metric->disable();
-    }
+  if (!domain->metric->_refcount && domain->metric->disable) {
+    domain->metric->disable();
   }
   strscpy(domain->metric_name, CFG_DOMAIN_NO_METRIC, sizeof(domain->metric_name));
   domain->metric = &_no_metric;
+  domain->metric->_refcount++;
 }
 
 /**
@@ -1044,38 +1074,49 @@ _remove_metric(struct nhdp_domain *domain) {
  *   might be CFG_DOMAIN_NO_MPR (every node is MPR)
  *   or CFG_DOMAIN_ANY_MPR (for a MPR the NHDP core should
  *   choose).
+ * @param willingness routing willingness for domain
  */
 static void
-_apply_mpr(struct nhdp_domain *domain, const char *mpr_name) {
+_apply_mpr(struct nhdp_domain *domain, const char *mpr_name, uint8_t willingness) {
   struct nhdp_domain_mpr *mpr;
 
   /* check if we have to remove the old mpr first */
-  if (strcasecmp(domain->mpr_name, mpr_name) != 0) {
-    if (domain->mpr != &_no_mprs) {
-      _remove_mpr(domain);
-      strscpy(domain->mpr_name, CFG_DOMAIN_NO_MPR, sizeof(domain->mpr_name));
-    }
+  if (strcasecmp(domain->mpr_name, mpr_name) == 0) {
+    domain->local_willingness = willingness;
+
+    /* nothing else to do, we already have the right MPR */
+    return;
+  }
+  if (domain->mpr != &_everyone_mprs) {
+    /* replace old MPR algorithm with "everyone MPR" */
+    _remove_mpr(domain);
   }
 
   /* Handle wildcard mpr name first */
   if (strcasecmp(mpr_name, CFG_DOMAIN_ANY_METRIC) == 0
-      && !avl_is_empty(&nhdp_domain_mprs)) {
-    mpr_name = avl_first_element(&nhdp_domain_mprs, mpr, _node)->name;
+      && !avl_is_empty(&_domain_mprs)) {
+    mpr_name = avl_first_element(&_domain_mprs, mpr, _node)->name;
   }
 
-  /* copy new metric name */
-  strscpy(domain->mpr_name, mpr_name, sizeof(domain->mpr_name));
-
   /* look for mpr implementation */
-  mpr = avl_find_element(&nhdp_domain_mprs, mpr_name, mpr, _node);
+  mpr = avl_find_element(&_domain_mprs, mpr_name, mpr, _node);
   if (mpr == NULL) {
-    domain->mpr = &_no_mprs;
-    return;
+    mpr = &_everyone_mprs;
   }
 
+  /* copy new metric name */
+  strscpy(domain->mpr_name, mpr->name, sizeof(domain->mpr_name));
+
   /* link domain and mpr */
+  domain->mpr->_refcount--;
   domain->mpr = mpr;
-  mpr->domain = domain;
+  domain->local_willingness = willingness;
+
+  /* activate mpr */
+  if (mpr->_refcount == 0 && mpr->enable) {
+    mpr->enable();
+  }
+  mpr->_refcount++;
 }
 
 /**
@@ -1084,9 +1125,35 @@ _apply_mpr(struct nhdp_domain *domain, const char *mpr_name) {
  */
 static void
 _remove_mpr(struct nhdp_domain *domain) {
+  domain->mpr->_refcount--;
+  if (!domain->mpr->_refcount && domain->mpr->disable) {
+    domain->mpr->disable();
+  }
   strscpy(domain->mpr_name, CFG_DOMAIN_NO_MPR, sizeof(domain->mpr_name));
-  domain->mpr->domain = NULL;
-  domain->mpr = &_no_mprs;
+  domain->mpr = &_everyone_mprs;
+  domain->mpr->_refcount++;
+}
+
+static void
+_cb_update_everyone_mpr(void) {
+  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;
+    }
+
+    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;
+      }
+    }
+  }
 }
 
 /**
index 97c15cd..a2d0d56 100644 (file)
@@ -107,8 +107,9 @@ struct nhdp_domain_mpr {
   /* calculate MPR set */
   void (*update_mpr)(void);
 
-  /* routing willingness */
-  enum rfc7181_willingness_values willingness;
+  /* callbacks for enable/disable mpr */
+  void (*enable)(void);
+  void (*disable)(void);
 
   /* default value for neighbor MPR setting */
   bool mpr_start;
@@ -116,8 +117,8 @@ struct nhdp_domain_mpr {
   /* default value for local MPR (selector) setting */
   bool mprs_start;
 
-  /* backpointer to domain */
-  struct nhdp_domain *domain;
+  /* reference count */
+  int _refcount;
 
   /* node for tree of MPR algorithms */
   struct avl_node _node;
@@ -137,6 +138,8 @@ struct nhdp_domain {
   struct nhdp_domain_metric *metric;
   struct nhdp_domain_mpr *mpr;
 
+  uint8_t local_willingness;
+
   /*
    * true if a neighbor metric of this domain has changed
    * since the last reset of this variable
@@ -146,9 +149,12 @@ struct nhdp_domain {
   /* tlv extension */
   uint8_t ext;
 
-  /* index in the metric array */
+  /* index in the domain array */
   int index;
 
+  /* temporary storage for willingness processing */
+  uint8_t _tmp_willingness;
+
   /* storage for the up to four additional link metrics */
   struct rfc5444_writer_tlvtype _metric_addrtlvs[4];
 
@@ -168,8 +174,8 @@ void nhdp_domain_cleanup(void);
 
 EXPORT size_t nhdp_domain_get_count(void);
 EXPORT struct nhdp_domain *nhdp_domain_add(uint8_t ext);
-EXPORT struct nhdp_domain *nhdp_domain_configure(
-    uint8_t ext, const char *metric_name, const char *mpr_name);
+EXPORT struct nhdp_domain *nhdp_domain_configure(uint8_t ext,
+    const char *metric_name, const char *mpr_name, uint8_t willingness);
 
 EXPORT int nhdp_domain_metric_add(struct nhdp_domain_metric *);
 EXPORT void nhdp_domain_metric_remove(struct nhdp_domain_metric *);
@@ -180,10 +186,6 @@ EXPORT void nhdp_domain_mpr_remove(struct nhdp_domain_mpr *);
 EXPORT void nhdp_domain_listener_add(struct nhdp_domain_listener *);
 EXPORT void nhdp_domain_listener_remove(struct nhdp_domain_listener *);
 
-EXPORT struct nhdp_domain_mpr *nhdp_domain_get_flooding_mpr(void);
-EXPORT void nhdp_domain_set_flooding_mpr(
-    struct nhdp_domain_mpr *, uint8_t ext);
-
 EXPORT struct nhdp_domain *nhdp_domain_get_by_ext(uint8_t);
 
 EXPORT void nhdp_domain_init_link(struct nhdp_link *);
@@ -207,6 +209,7 @@ EXPORT void nhdp_domain_process_mpr_tlv(uint8_t *mprtypes, size_t mprtypes_size,
 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 size_t nhdp_domain_encode_mprtypes_tlvvalue(
     uint8_t *mprtypes, size_t mprtypes_size);
 EXPORT size_t nhdp_domain_encode_mpr_tlvvalue(
@@ -219,6 +222,8 @@ EXPORT bool nhdp_domain_set_incoming_metric(
 
 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 void nhdp_domain_set_flooding_mpr(const char *mpr_name, uint8_t willingness);
 
 /**
  * @param domain NHDP domain
@@ -226,7 +231,7 @@ EXPORT struct list_entity *nhdp_domain_get_listener_list(void);
  * @return domain data of specified link
  */
 static INLINE struct nhdp_link_domaindata *
-nhdp_domain_get_linkdata(struct nhdp_domain *domain, struct nhdp_link *lnk) {
+nhdp_domain_get_linkdata(const struct nhdp_domain *domain, struct nhdp_link *lnk) {
   return &lnk->_domaindata[domain->index];
 }
 
@@ -237,7 +242,7 @@ nhdp_domain_get_linkdata(struct nhdp_domain *domain, struct nhdp_link *lnk) {
  */
 static INLINE struct nhdp_neighbor_domaindata *
 nhdp_domain_get_neighbordata(
-    struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
+    const struct nhdp_domain *domain, struct nhdp_neighbor *neigh) {
   return &neigh->_domaindata[domain->index];
 }
 
@@ -248,7 +253,7 @@ nhdp_domain_get_neighbordata(
  */
 static INLINE struct nhdp_l2hop_domaindata *
 nhdp_domain_get_l2hopdata(
-    struct nhdp_domain *domain, struct nhdp_l2hop *l2hop) {
+    const struct nhdp_domain *domain, struct nhdp_l2hop *l2hop) {
   return &l2hop->_domaindata[domain->index];
 }
 
@@ -261,7 +266,7 @@ nhdp_domain_get_l2hopdata(
  */
 static INLINE const char *
 nhdp_domain_get_link_metric_value(struct nhdp_metric_str *buf,
-    struct nhdp_domain *domain, uint32_t metric) {
+    const struct nhdp_domain *domain, uint32_t metric) {
   return domain->metric->link_to_string(buf, metric);
 }
 
@@ -274,7 +279,7 @@ nhdp_domain_get_link_metric_value(struct nhdp_metric_str *buf,
  */
 static INLINE const char *
 nhdp_domain_get_path_metric_value(struct nhdp_metric_str *buf,
-    struct nhdp_domain *domain, uint32_t metric, uint8_t hopcount) {
+    const struct nhdp_domain *domain, uint32_t metric, uint8_t hopcount) {
   return domain->metric->path_to_string(buf, metric, hopcount);
 }
 
@@ -286,7 +291,7 @@ nhdp_domain_get_path_metric_value(struct nhdp_metric_str *buf,
  */
 static INLINE const char *
 nhdp_domain_get_internal_link_metric_value(struct nhdp_metric_str *buf,
-    struct nhdp_domain_metric *metric, struct nhdp_link *lnk) {
+    const struct nhdp_domain_metric *metric, struct nhdp_link *lnk) {
   return metric->internal_link_to_string(buf, lnk);
 }
 
index 5cf548f..c693902 100644 (file)
@@ -430,7 +430,7 @@ _cb_messagetlvs(struct rfc5444_reader_tlvblock_context *context) {
       _current.mprtypes, sizeof(_current.mprtypes),
       _nhdp_message_tlvs[IDX_TLV_MPRTYPES].tlv);
 
-  /* extract willingness */
+  /* extract willingness into temporary buffers */
   nhdp_domain_process_willingness_tlv(_current.mprtypes, _current.mprtypes_size,
         _nhdp_message_tlvs[IDX_TLV_WILLINGNESS].tlv);
 
@@ -690,6 +690,9 @@ _cb_addresstlvs_pass1_end(struct rfc5444_reader_tlvblock_context *context, bool
     }
   }
 
+  /* copy willingness to permanent storage */
+  nhdp_domain_store_willingness(_current.neighbor);
+
   OONF_DEBUG(LOG_NHDP_R, "pass1 finished");
 
   return RFC5444_OKAY;
index 398c1d5..2a76cfb 100644 (file)
@@ -135,6 +135,7 @@ static int _cb_create_text_neighbor_address(struct oonf_viewer_template *);
 #define KEY_NEIGHBOR_FLOOD_REMOTE   "neighbor_flood_remote"
 #define KEY_NEIGHBOR_SYMMETRIC      "neighbor_symmetric"
 #define KEY_NEIGHBOR_LINKCOUNT      "neighbor_linkcount"
+#define KEY_NEIGHBOR_FLOOD_WILL     "neighbor_flood_willingness"
 #define KEY_NEIGHBOR_ADDRESS        "neighbor_address"
 #define KEY_NEIGHBOR_ADDRESS_LOST   "neighbor_address_lost"
 #define KEY_NEIGHBOR_ADDRESS_VTIME  "neighbor_address_lost_vtime"
@@ -149,6 +150,7 @@ static int _cb_create_text_neighbor_address(struct oonf_viewer_template *);
 #define KEY_DOMAIN_MPR              "domain_mpr"
 #define KEY_DOMAIN_MPR_LOCAL        "domain_mpr_local"
 #define KEY_DOMAIN_MPR_REMOTE       "domain_mpr_remote"
+#define KEY_DOMAIN_MPR_WILL         "domain_mpr_willingness"
 
 /*
  * buffer space for values that will be assembled
@@ -187,6 +189,7 @@ static char                       _value_neighbor_flood_local[TEMPLATE_JSON_BOOL
 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;
@@ -201,6 +204,7 @@ static struct nhdp_metric_str     _value_domain_metric_internal;
 static char                       _value_domain_mpr[NHDP_DOMAIN_MPR_MAXLEN];
 static char                       _value_domain_mpr_local[TEMPLATE_JSON_BOOL_LENGTH];
 static char                       _value_domain_mpr_remote[TEMPLATE_JSON_BOOL_LENGTH];
+static char                       _value_domain_mpr_will[3];
 
 
 /* definition of the template data entries for JSON and table output */
@@ -262,6 +266,7 @@ static struct abuf_template_data_entry _tde_domain_mpr[] = {
     { KEY_DOMAIN_MPR, _value_domain_mpr, true },
     { KEY_DOMAIN_MPR_LOCAL, _value_domain_mpr_local, true },
     { KEY_DOMAIN_MPR_REMOTE, _value_domain_mpr_remote, true},
+    { KEY_DOMAIN_MPR_WILL, _value_domain_mpr_will, false },
 };
 
 static struct abuf_template_data_entry _tde_link_addr[] = {
@@ -282,6 +287,7 @@ 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 },
 };
@@ -575,6 +581,8 @@ _initialize_nhdp_neighbor_mpr_values(struct nhdp_domain *domain,
       json_getbool(domaindata->neigh_is_mpr),
       sizeof(_value_domain_mpr_remote));
 
+  snprintf(_value_domain_mpr_will, sizeof(_value_domain_mpr_will),
+      "%d", domaindata->willingness);
 }
 
 static void
@@ -630,6 +638,8 @@ _initialize_nhdp_neighbor_values(struct nhdp_neighbor *neigh) {
   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),