Merge branch 'master' into mpr_rework
[oonf.git] / src-plugins / nhdp / nhdp / nhdp_db.c
index dadce18..8685f29 100644 (file)
@@ -229,11 +229,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));
@@ -259,9 +262,23 @@ 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;
+    }
+  }
+
   /* remove from global list and free memory */
   list_remove(&neigh->_global_node);
   oonf_class_free(&_neigh_info, neigh);
+
+  if (was_mpr) {
+    nhdp_domain_recalculate_mpr(true);
+  }
 }
 
 /**
@@ -793,6 +810,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 */
@@ -809,7 +827,10 @@ nhdp_db_link_update_status(struct nhdp_link *lnk) {
   }
 
   /* trigger change event */
-  oonf_class_event(&_link_info, lnk, OONF_OBJECT_CHANGED);
+  if (lnk->last_status != lnk->status) {
+    oonf_class_event(&_link_info, lnk, OONF_OBJECT_CHANGED);
+    nhdp_domain_recalculate_mpr(true);
+  }
 }
 
 /**
@@ -948,10 +969,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);
   }
 }
 
@@ -975,11 +992,20 @@ _cb_link_heard(struct oonf_timer_instance *ptr) {
 static void
 _cb_link_symtime(struct oonf_timer_instance *ptr) {
   struct nhdp_link *lnk;
+  struct nhdp_neighbor_domaindata *data;
+  struct nhdp_domain *domain;
 
   lnk = container_of(ptr, struct nhdp_link, sym_time);
   OONF_DEBUG(LOG_NHDP, "Link Symtime fired: 0x%0zx", (size_t)lnk);
   nhdp_db_link_update_status(lnk);
-  nhdp_domain_neighbor_changed(lnk->neigh);
+
+  list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+    data = nhdp_domain_get_neighbordata(domain, lnk->neigh);
+    if (data->neigh_is_mpr) {
+      nhdp_domain_recalculate_mpr(false);
+      return;
+    }
+  }
 }
 
 /**
@@ -1003,12 +1029,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);
 }