Fix neighborhood routing
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 31 Jan 2017 13:46:54 +0000 (14:46 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 31 Jan 2017 13:46:54 +0000 (14:46 +0100)
src-plugins/nhdp/mpr/neighbor-graph.c
src-plugins/nhdp/nhdp/nhdp_db.c
src-plugins/nhdp/nhdp/nhdp_db.h
src-plugins/olsrv2/olsrv2/olsrv2_tc.c
src-plugins/olsrv2/olsrv2/olsrv2_tc.h
src-plugins/olsrv2/olsrv2info/olsrv2info.c

index 3944ef9..c402646 100644 (file)
@@ -275,4 +275,3 @@ mpr_calculate_d_of_y_s(const struct nhdp_domain *domain, struct neighbor_graph *
 
   return min_cost;
 }
-
index d8c879f..a99fd53 100644 (file)
@@ -460,6 +460,12 @@ nhdp_db_neighbor_set_originator(struct nhdp_neighbor *neigh,
       avl_insert(&lnk->local_if->_link_originators, &lnk->_originator_node);
     }
   }
+
+  /* inform everyone */
+  oonf_class_event(&_neigh_info, neigh, OONF_OBJECT_CHANGED);
+
+  /* overwrite "old originator" */
+  memcpy(&neigh->_old_originator, originator, sizeof(*originator));
 }
 
 /**
index 9be562d..f18920d 100644 (file)
@@ -293,6 +293,12 @@ struct nhdp_neighbor {
   /*! internal field for NHDP processing */
   int _process_count;
 
+  /*!
+   * originator address of this node before it was changed.
+   * Mostly used in CHANGE events
+   */
+  struct netaddr _old_originator;
+
   /*! list of links for this neighbor */
   struct list_entity _links;
 
index 347b8f9..6b0f6d4 100644 (file)
@@ -61,6 +61,9 @@
 static void _cb_tc_node_timeout(struct oonf_timer_instance *);
 static bool _remove_edge(struct olsrv2_tc_edge *edge, bool cleanup);
 
+static void _cb_neighbor_change(void *ptr);
+static void _cb_neighbor_remove(void *ptr);
+
 /* classes for topology data */
 static struct oonf_class _tc_node_class = {
   .name = OLSRV2_CLASS_TC_NODE,
@@ -82,6 +85,14 @@ static struct oonf_class _tc_endpoint_class = {
   .size = sizeof(struct olsrv2_tc_endpoint),
 };
 
+/* keep track of direct neighbors */
+static struct oonf_class_extension _nhdp_neighbor_extension = {
+  .ext_name = "olsrv2_tc tracking",
+  .class_name = NHDP_CLASS_NEIGHBOR,
+  .cb_change = _cb_neighbor_change,
+  .cb_remove = _cb_neighbor_remove,
+};
+
 /* validity timer for tc nodes */
 static struct oonf_timer_class _validity_info = {
   .name = "olsrv2 tc node validity",
@@ -102,6 +113,8 @@ olsrv2_tc_init(void) {
   oonf_class_add(&_tc_attached_class);
   oonf_class_add(&_tc_endpoint_class);
 
+  oonf_class_extension_add(&_nhdp_neighbor_extension);
+
   avl_init(&_tc_tree, avl_comp_netaddr, false);
   avl_init(&_tc_endpoint_tree, os_routing_avl_cmp_route_key, true);
 }
@@ -130,6 +143,8 @@ olsrv2_tc_cleanup(void) {
     olsrv2_tc_node_remove(node);
   }
 
+  oonf_class_extension_remove(&_nhdp_neighbor_extension);
+
   oonf_class_remove(&_tc_endpoint_class);
   oonf_class_remove(&_tc_attached_class);
   oonf_class_remove(&_tc_edge_class);
@@ -217,7 +232,7 @@ olsrv2_tc_node_remove(struct olsrv2_tc_node *node) {
   oonf_timer_stop(&node->_validity_time);
 
   /* remove from global tree and free memory if node is not needed anymore*/
-  if (node->_edges.count == 0) {
+  if (node->_edges.count == 0 && !node->direct_neighbor) {
     avl_remove(&_tc_tree, &node->_originator_node);
     oonf_class_free(&_tc_node_class, node);
   }
@@ -498,3 +513,60 @@ _remove_edge(struct olsrv2_tc_edge *edge, bool cleanup) {
 
   return removed_node;
 }
+
+static void
+_cb_neighbor_change(void *ptr) {
+  struct nhdp_neighbor *neigh;
+  struct olsrv2_tc_node *tc_node;
+
+  neigh = ptr;
+  if (memcmp(&neigh->originator, &neigh->_old_originator,
+      sizeof(neigh->originator)) == 0) {
+    /* no change */
+    return;
+  }
+
+  /* remove old tc_node if necessary */
+  _cb_neighbor_remove(ptr);
+
+  /* see if we have a new originator */
+  if (netaddr_is_unspec(&neigh->originator)) {
+    return;
+  }
+
+  /* add tc_node if necessary */
+  tc_node = olsrv2_tc_node_get(&neigh->originator);
+  if (!tc_node) {
+    tc_node = olsrv2_tc_node_add(&neigh->originator, 0, 0);
+    if (!tc_node) {
+      return;
+    }
+  }
+
+  /* mark as direct neighbor */
+  tc_node->direct_neighbor = true;
+}
+
+static void
+_cb_neighbor_remove(void *ptr) {
+  struct nhdp_neighbor *neigh;
+  struct olsrv2_tc_node *tc_node;
+
+  neigh = ptr;
+
+  if (netaddr_is_unspec(&neigh->originator)) {
+    return;
+  }
+
+  tc_node = olsrv2_tc_node_get(&neigh->originator);
+  if (!tc_node) {
+    return;
+  }
+
+  tc_node->direct_neighbor = false;
+
+  if (!oonf_timer_is_active(&tc_node->_validity_time)) {
+    /* virtual node, kill it */
+    olsrv2_tc_node_remove(tc_node);
+  }
+}
index bc03041..f8bd102 100644 (file)
@@ -117,6 +117,9 @@ struct olsrv2_tc_node {
   /*! reported interval time */
   uint64_t interval_time;
 
+  /*! true if node has to be kept alive because of HELLOs */
+  bool direct_neighbor;
+
   /*! node has announced it can do source specific routing */
   bool source_specific;
 
index b3dd52c..7f8e87a 100644 (file)
@@ -146,6 +146,12 @@ static int _cb_create_text_route(struct oonf_viewer_template *);
 /*! template key for current node answer set number */
 #define KEY_NODE_ANSN               "node_ansn"
 
+/*! template key for nodes that exist because of HELLOs or foreign TCs */
+#define KEY_NODE_VIRTUAL            "node_virtual"
+
+/*! template key for nodes that are direct neighbors */
+#define KEY_NODE_NEIGHBOR           "node_neighbor"
+
 /*! template key for attached network destination prefix*/
 #define KEY_ATTACHED_NET            "attached_net"
 
@@ -213,6 +219,8 @@ static struct netaddr_str         _value_lan_src;
 static struct netaddr_str         _value_node;
 static struct isonumber_str       _value_node_vtime;
 static char                       _value_node_ansn[6];
+static char                       _value_node_virtual[TEMPLATE_JSON_BOOL_LENGTH];
+static char                       _value_node_neighbor[TEMPLATE_JSON_BOOL_LENGTH];
 
 static struct netaddr_str         _value_attached_net_dst;
 static struct netaddr_str         _value_attached_net_src;
@@ -273,6 +281,8 @@ static struct abuf_template_data_entry _tde_node[] = {
     { KEY_NODE, _value_node.buf, true },
     { KEY_NODE_ANSN, _value_node_ansn, false },
     { KEY_NODE_VTIME, _value_node_vtime.buf, false },
+    { KEY_NODE_VIRTUAL, _value_node_virtual, true },
+    { KEY_NODE_NEIGHBOR, _value_node_neighbor, true },
 };
 
 static struct abuf_template_data_entry _tde_attached_net[] = {
@@ -550,6 +560,13 @@ _initialize_node_values(struct olsrv2_tc_node *node) {
       oonf_timer_get_due(&node->_validity_time));
 
   snprintf(_value_node_ansn, sizeof(_value_node_ansn), "%u", node->ansn);
+
+  strscpy(_value_node_virtual,
+      json_getbool(!oonf_timer_is_active(&node->_validity_time)),
+      sizeof(_value_node_virtual));
+  strscpy(_value_node_neighbor,
+      json_getbool(node->direct_neighbor),
+      sizeof(_value_node_neighbor));
 }
 
 /**
@@ -677,9 +694,6 @@ _cb_create_text_node(struct oonf_viewer_template *template) {
   struct olsrv2_tc_node *node;
 
   avl_for_each_element(olsrv2_tc_get_tree(), node, _originator_node) {
-    if (olsrv2_tc_is_node_virtual(node)) {
-      continue;
-    }
     _initialize_node_values(node);
 
     oonf_viewer_output_print_line(template);