Fix a segfault for fast changing meshs
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 20 May 2010 11:20:19 +0000 (13:20 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 20 May 2010 11:20:19 +0000 (13:20 +0200)
lib/txtinfo/src/olsrd_txtinfo.c
src/link_set.c
src/routing_table.c
src/scheduler.c
src/scheduler.h
src/tc_set.c
src/tc_set.h

index 77b4e0b..f889f6b 100644 (file)
@@ -457,6 +457,10 @@ txtinfo_routes(struct comport_connection *con,
 
   /* Walk the route table */
   OLSR_FOR_ALL_RT_ENTRIES(rt) {
+    if (!rt->rt_best) {
+      /* ignore entries without paths, they will be erased soon */
+      continue;
+    }
     olsr_ip_prefix_to_string(&buf_destprefix, &rt->rt_dst);
     olsr_ip_to_string(&buf_neighip, &rt->rt_best->rtp_nexthop.gateway);
     snprintf(buf_hopcount, sizeof(buf_hopcount), "%d", rt->rt_best->rtp_metric.hops);
index 3ce3635..a99afca 100644 (file)
@@ -278,6 +278,8 @@ olsr_delete_link_entry(struct link_entry *link)
    * Delete the corresponding tc-edge for that link.
    */
   if (link->link_tc_edge) {
+    /* remove backpointer in tc edge */
+    link->link_tc_edge->link = NULL;
     olsr_delete_tc_edge_entry(link->link_tc_edge);
     link->link_tc_edge = NULL;
 
@@ -525,6 +527,9 @@ add_link_entry(const union olsr_ip_addr *local,
     link->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, remote_main, 0);
   }
 
+  /* set backpointer */
+  link->link_tc_edge->link = link;
+
   /*
    * Add the rt_path for the link-end. This is an optimization
    * that lets us install > 1 hop routes prior to receiving
index 46c0dca..7fd95d5 100644 (file)
@@ -460,6 +460,15 @@ olsr_delete_rt_path(struct rt_path *rtp)
   /* remove from the originator tree */
   if (rtp->rtp_rt) {
     avl_delete(&rtp->rtp_rt->rt_path_tree, &rtp->rtp_tree_node);
+    /* clean up rt_best */
+    if (rtp->rtp_rt->rt_best == rtp) {
+      if (rtp->rtp_rt->rt_path_tree.count) {
+        olsr_rt_best(rtp->rtp_rt);
+      }
+      else {
+        rtp->rtp_rt->rt_best = NULL;
+      }
+    }
     rtp->rtp_rt = NULL;
   }
 
index f40ef25..a4379fc 100644 (file)
@@ -595,7 +595,9 @@ walk_timers(uint32_t * last_run)
                    timer, timer->timer_cb_context, (unsigned int)*last_run, olsr_wallclock_string());
 
         /* This timer is expired, call into the provided callback function */
+        timer->timer_in_callback = true;
         timer->timer_cb(timer->timer_cb_context);
+        timer->timer_in_callback = false;
 
         /* Only act on actually running timers */
         if (timer->timer_running) {
@@ -612,6 +614,10 @@ walk_timers(uint32_t * last_run)
             olsr_stop_timer(timer);
           }
         }
+        else {
+          /* free memory */
+          olsr_cookie_free(timer_mem_cookie, timer);
+        }
 
         timers_fired++;
       }
@@ -820,7 +826,9 @@ olsr_stop_timer(struct timer_entry *timer)
   timer->timer_running = false;
   olsr_cookie_usage_decr(timer->timer_cookie);
 
-  olsr_cookie_free(timer_mem_cookie, timer);
+  if (!timer->timer_in_callback) {
+    olsr_cookie_free(timer_mem_cookie, timer);
+  }
 }
 
 /**
index 42d5f2e..bd34656 100644 (file)
@@ -71,7 +71,8 @@ struct timer_entry {
   unsigned int timer_period;           /* set for periodical timers (relative time) */
   struct olsr_cookie_info *timer_cookie;       /* used for diag stuff */
   uint8_t timer_jitter_pct;            /* the jitter expressed in percent */
-  bool timer_running;                 /* misc flags */
+  bool timer_running;                  /* misc flags */
+  bool timer_in_callback;              /* true if callback is active */
   unsigned int timer_random;           /* cache random() result for performance reasons */
   timer_cb_func timer_cb;              /* callback function */
   void *timer_cb_context;              /* context pointer */
index 2f17183..5911b72 100644 (file)
@@ -168,6 +168,16 @@ olsr_change_myself_tc(void)
       return;
     }
 
+    /* flush local edges */
+    OLSR_FOR_ALL_LINK_ENTRIES(entry) {
+      if (entry->link_tc_edge) {
+        /* clean up local edges if necessary */
+        entry->link_tc_edge->link = NULL;
+        olsr_delete_tc_edge_entry(entry->link_tc_edge);
+        entry->link_tc_edge = NULL;
+      }
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
+
     /*
      * Flush our own tc_entry.
      */
@@ -188,16 +198,18 @@ olsr_change_myself_tc(void)
   tc_myself = olsr_add_tc_entry(&olsr_cnf->router_id);
   olsr_lock_tc_entry(tc_myself);
 
-  OLSR_FOR_ALL_LINK_ENTRIES(entry) {
-
-    /**
-     * check if a main ip change destroyed our TC entries
-     */
-    if (main_ip_change || entry->link_tc_edge == NULL) {
-      struct nbr_entry *ne = entry->neighbor;
-      entry->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, &ne->nbr_addr, 0);
-    }
-  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  if (main_ip_change) {
+    OLSR_FOR_ALL_LINK_ENTRIES(entry) {
+      /**
+       * check if a main ip change destroyed our TC entries
+       */
+      if (entry->link_tc_edge == NULL) {
+        struct nbr_entry *ne = entry->neighbor;
+        entry->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, &ne->nbr_addr, 0);
+        entry->link_tc_edge->link = entry;
+      }
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+  }
   changes_topology = true;
 }
 
@@ -469,6 +481,11 @@ olsr_delete_tc_edge_entry(struct tc_edge_entry *tc_edge)
   struct ipaddr_str buf;
 #endif
 
+  if (tc_edge->link) {
+    /* don't remove tc_edge for link entry */
+    return;
+  }
+
   tc_edge->is_virtual = 1;
 
   tc_edge_inv = tc_edge->edge_inv;
index 41f52e3..a382e2e 100644 (file)
@@ -62,6 +62,7 @@ struct tc_edge_entry {
   union olsr_ip_addr T_dest_addr;      /* edge_node key */
   struct tc_edge_entry *edge_inv;      /* shortcut, used during SPF calculation */
   struct tc_entry *tc;                 /* backpointer to owning tc entry */
+  struct link_entry *link;             /* back pointer for link edges */
   olsr_linkcost cost;                  /* metric for tc received by this tc */
   olsr_linkcost common_cost;           /* common metric of both edges used for SPF calculation */
   unsigned int is_virtual:1;           /* 1 if this is a virtual edge created by the neighbors TC ? */