Create 'leavinig network' Hello/TC messages when OLSRd shuts down.
authorHenning Rogge <hrogge@googlemail.com>
Sat, 19 Dec 2009 21:21:49 +0000 (22:21 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Sat, 19 Dec 2009 21:21:49 +0000 (22:21 +0100)
Cleanup MID/HNA/TC entries when 'leaving network TC' is received.

12 files changed:
src/build_msg.c
src/hna_set.c
src/hna_set.h
src/link_set.c
src/link_set.h
src/lq_plugin.c
src/lq_plugin.h
src/main.c
src/mid_set.c
src/mid_set.h
src/olsr_spf.c
src/tc_set.c

index a526c8b..7241dac 100644 (file)
@@ -250,7 +250,7 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
   union olsr_message *m;
   struct hellomsg *h;
   struct hellinfo *hinfo;
-  union olsr_ip_addr *haddr;
+  char *haddr;
   int i, j;
   bool first_entry;
 
@@ -273,7 +273,7 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
 
   h = &m->v4.message.hello;
   hinfo = h->hell_info;
-  haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
+  haddr = (char *)hinfo->neigh_addr;
 
   /* Fill message header */
   m->v4.ttl = message->ttl;
@@ -292,10 +292,10 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
 
   /*
    *Loops trough all possible neighbor statuses
-   *The negbor list is grouped by status
+   *The neighbor list is grouped by status
    *
    */
-  /* Nighbor statuses */
+  /* Neighbor statuses */
   for (i = 0; i <= MAX_NEIGH; i++) {
     /* Link statuses */
     for (j = 0; j <= MAX_LINK; j++) {
@@ -315,6 +315,7 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
         if ((nb->status != i) || (nb->link != j))
           continue;
 
+
 #ifdef DEBUG
         OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&buf, &nb->address));
         OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i);
@@ -349,7 +350,7 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
 
             h = &m->v4.message.hello;
             hinfo = h->hell_info;
-            haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
+            haddr = (char *)hinfo->neigh_addr;
             /* Make sure typeheader is added */
             first_entry = true;
           }
@@ -369,10 +370,10 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
           curr_size += 4;       /* HELLO type section header */
         }
 
-        *haddr = nb->address;
+        *((union olsr_ip_addr *)haddr) = nb->address;
 
         /* Point to next address */
-        haddr += sizeof(haddr->v4);
+        haddr += olsr_cnf->ipsize;
         curr_size += olsr_cnf->ipsize;  /* IP address added */
 
         first_entry = false;
@@ -380,8 +381,10 @@ serialize_hello4(struct hello_message *message, struct interface *ifp)
 
       if (!first_entry) {
         hinfo->size = htons((char *)haddr - (char *)hinfo);
+
         hinfo = (struct hellinfo *)((char *)haddr);
-        haddr = (union olsr_ip_addr *)&hinfo->neigh_addr;
+        haddr = (char *)hinfo->neigh_addr;
+
       }
     }                           /* for j */
   }                             /* for i */
index 08b3d13..5a92c21 100644 (file)
@@ -52,6 +52,8 @@ struct olsr_cookie_info *hna_net_timer_cookie = NULL;
 struct olsr_cookie_info *hna_entry_mem_cookie = NULL;
 struct olsr_cookie_info *hna_net_mem_cookie = NULL;
 
+static bool olsr_delete_hna_net_entry(struct hna_net *net_to_delete);
+
 /**
  * Initialize the HNA set
  */
@@ -76,6 +78,17 @@ olsr_init_hna_set(void)
   return 1;
 }
 
+void
+olsr_cleanup_hna(union olsr_ip_addr *orig) {
+  struct hna_entry *hna;
+
+  OLSR_FOR_ALL_HNA_ENTRIES(hna) {
+    if (ipequal(&hna->A_gateway_addr, orig)) {
+      while (!olsr_delete_hna_net_entry(hna->networks.next));
+    }
+  } OLSR_FOR_ALL_HNA_ENTRIES_END(hna)
+}
+
 /**
  * Lookup a network entry in a networkentry list.
  *
@@ -193,19 +206,15 @@ olsr_add_hna_net(struct hna_entry *hna_gw, const union olsr_ip_addr *net, uint8_
   return new_net;
 }
 
-/**
- * Callback for the hna_net timer.
- */
-static void
-olsr_expire_hna_net_entry(void *context)
-{
+static bool
+olsr_delete_hna_net_entry(struct hna_net *net_to_delete) {
 #ifdef DEBUG
   struct ipaddr_str buf1, buf2;
 #endif
-  struct hna_net *net_to_delete;
   struct hna_entry *hna_gw;
+  bool removed_entry = false;
 
-  net_to_delete = (struct hna_net *)context;
+  olsr_stop_timer(net_to_delete->hna_net_timer);
   net_to_delete->hna_net_timer = NULL;  /* be pedandic */
   hna_gw = net_to_delete->hna_gw;
 
@@ -223,10 +232,21 @@ olsr_expire_hna_net_entry(void *context)
   if (hna_gw->networks.next == &hna_gw->networks) {
     DEQUEUE_ELEM(hna_gw);
     olsr_cookie_free(hna_entry_mem_cookie, hna_gw);
+    removed_entry = true;
   }
 
   DEQUEUE_ELEM(net_to_delete);
   olsr_cookie_free(hna_net_mem_cookie, net_to_delete);
+  return removed_entry;
+}
+
+/**
+ * Callback for the hna_net timer.
+ */
+static void
+olsr_expire_hna_net_entry(void *context)
+{
+  olsr_delete_hna_net_entry(context);
 }
 
 /**
index ad7df72..0ca01ed 100644 (file)
@@ -81,6 +81,7 @@ struct hna_entry {
 extern struct hna_entry hna_set[HASHSIZE];
 
 int olsr_init_hna_set(void);
+void olsr_cleanup_hna(union olsr_ip_addr *orig);
 
 struct hna_net *olsr_lookup_hna_net(const struct hna_net *, const union olsr_ip_addr *, uint8_t);
 
index f39ffa4..27306a9 100644 (file)
@@ -74,6 +74,7 @@ static int check_link_status(const struct hello_message *message, const struct i
 static struct link_entry *add_link_entry(const union olsr_ip_addr *, const union olsr_ip_addr *, const union olsr_ip_addr *,
                                          olsr_reltime, olsr_reltime, const struct interface *);
 static int get_neighbor_status(const union olsr_ip_addr *);
+static void olsr_expire_link_sym_timer(void *context);
 
 void
 olsr_init_link_set(void)
@@ -84,6 +85,31 @@ olsr_init_link_set(void)
 }
 
 /**
+ * This function resets all links to lost, so that
+ * a final "lost all links" hello can be generated to
+ * tell your neighbors that you are gone now.
+ */
+void olsr_reset_all_links(void) {
+  struct link_entry *link;
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    link->ASYM_time = now_times-1;
+
+    olsr_stop_timer(link->link_sym_timer);
+    link->link_sym_timer = NULL;
+
+    link->neighbor->is_mpr = false;
+    link->neighbor->status = NOT_SYM;
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
+
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    olsr_expire_link_sym_timer(link);
+    olsr_clear_hello_lq(link);
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
+}
+
+/**
  * Get the status of a link. The status is based upon different
  * timeouts in the link entry.
  *
index 1929542..f057e8c 100644 (file)
@@ -121,6 +121,7 @@ extern bool link_changes;
 
 void olsr_set_link_timer(struct link_entry *, unsigned int);
 void olsr_init_link_set(void);
+void olsr_reset_all_links(void);
 void olsr_delete_link_entry_by_ip(const union olsr_ip_addr *);
 void olsr_expire_link_hello_timer(void *);
 void signal_link_changes(bool);        /* XXX ugly */
index 9687500..caf76e5 100644 (file)
@@ -360,6 +360,11 @@ olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target, struct link
   active_lq_handler->copy_link_lq_into_tc(target->linkquality, source->linkquality);
 }
 
+/* clear the lq of a link set entry */
+void olsr_clear_hello_lq(struct link_entry *link) {
+  active_lq_handler->clear_hello(link->linkquality);
+}
+
 /*
  * olsr_clear_tc_lq
  *
index 7a1d62a..88b1b02 100644 (file)
@@ -127,6 +127,7 @@ const char *get_link_entry_text(struct link_entry *entry, char separator, struct
 const char *get_tc_edge_entry_text(struct tc_edge_entry *entry, char separator, struct lqtextbuffer *buffer);
 const char *get_linkcost_text(olsr_linkcost cost, bool route, struct lqtextbuffer *buffer);
 
+void olsr_clear_hello_lq(struct link_entry *link);
 void olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source);
 void olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target, struct link_entry *source);
 void olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source);
index 8682533..d940ca4 100644 (file)
@@ -58,6 +58,7 @@
 #include "build_msg.h"
 #include "net_olsr.h"
 #include "mid_set.h"
+#include "mpr_selector_set.h"
 
 #if LINUX_POLICY_ROUTING
 #include <linux/types.h>
@@ -523,6 +524,27 @@ void olsr_reconfigure(int signo __attribute__ ((unused))) {
 }
 #endif
 
+static void olsr_shutdown_messages(void) {
+  struct interface *ifn;
+
+  /* send TC reset */
+  for (ifn = ifnet; ifn; ifn = ifn->int_next) {
+    /* clean output buffer */
+    net_output(ifn);
+
+    /* send 'I'm gone' messages */
+    if (olsr_cnf->lq_level > 0) {
+      olsr_output_lq_tc(ifn);
+      olsr_output_lq_hello(ifn);
+    }
+    else {
+      generate_tc(ifn);
+      generate_hello(ifn);
+    }
+    net_output(ifn);
+  }
+}
+
 /**
  *Function called at shutdown. Signal handler
  *
@@ -551,8 +573,26 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
   OLSR_PRINTF(1, "Scheduler stopped.\n");
 #endif
 
+  /* clear all links and send empty hellos/tcs */
+  olsr_reset_all_links();
+
+  /* deactivate fisheye and immediate TCs */
+  olsr_cnf->lq_fish = 0;
+  for (ifn = ifnet; ifn; ifn = ifn->int_next) {
+    ifn->immediate_send_tc = false;
+  }
+  increase_local_ansn();
+
+  /* send first shutdown message burst */
+  olsr_shutdown_messages();
+
+  /* delete all routes */
   olsr_delete_all_kernel_routes();
 
+  /* send second shutdown message burst */
+  olsr_shutdown_messages();
+
+  /* now try to cleanup the rest of the mess */
   olsr_delete_all_tc_entries();
 
   olsr_delete_all_mid_entries();
index 0ea040f..fc86122 100644 (file)
@@ -89,6 +89,15 @@ void olsr_delete_all_mid_entries(void) {
     }
   }
 }
+
+void olsr_cleanup_mid(union olsr_ip_addr *orig) {
+  struct mid_entry *mid;
+  mid = mid_lookup_entry_bymain(orig);
+  if (mid) {
+    olsr_delete_mid_entry(mid);
+  }
+}
+
 /**
  * Wrapper for the timer callback.
  */
index 074b0a0..3069e36 100644 (file)
@@ -77,6 +77,7 @@ struct mid_alias;
 
 int olsr_init_mid_set(void);
 void olsr_delete_all_mid_entries(void);
+void olsr_cleanup_mid(union olsr_ip_addr *);
 void insert_mid_alias(union olsr_ip_addr *, const union olsr_ip_addr *, olsr_reltime);
 union olsr_ip_addr *mid_lookup_main_addr(const union olsr_ip_addr *);
 struct mid_address *mid_lookup_aliases(const union olsr_ip_addr *);
index fcc9961..760c62b 100644 (file)
@@ -371,11 +371,16 @@ olsr_calculate_routing_table(void)
    */
   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
 
-    if (neigh->status == SYM) {
-
+    if (neigh->status != SYM) {
+      tc_edge = olsr_lookup_tc_edge(tc_myself, &neigh->neighbor_main_addr);
+      if (tc_edge) {
+        olsr_delete_tc_edge_entry(tc_edge);
+      }
+    }
+    else {
       tc_edge = olsr_lookup_tc_edge(tc_myself, &neigh->neighbor_main_addr);
       link = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
-      if (!link) {
+      if (!link || lookup_link_status(link) == LOST_LINK) {
 
         /*
          * If there is no best link to this neighbor
index 2dd07d6..299cd2d 100644 (file)
@@ -792,6 +792,7 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
   union olsr_ip_addr originator;
   const unsigned char *limit, *curr;
   struct tc_entry *tc;
+  bool emptyTC;
 
   union olsr_ip_addr lower_border_ip, upper_border_ip;
   int borderSet = 0;
@@ -894,6 +895,7 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
 
   limit = (unsigned char *)msg + size;
   borderSet = 0;
+  emptyTC = curr >= limit;
   while (curr < limit) {
     if (olsr_tc_update_edge(tc, ansn, &curr, &upper_border_ip)) {
       changes_topology = true;
@@ -918,6 +920,13 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
   olsr_set_timer(&tc->validity_timer, vtime, OLSR_TC_VTIME_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_tc_entry, tc,
                  tc_validity_timer_cookie->ci_id);
 
+  if (emptyTC && lower_border == 0xff && upper_border == 0xff) {
+    /* handle empty TC with border flags 0xff */
+    memset(&lower_border_ip, 0x00, sizeof(lower_border_ip));
+    memset(&upper_border_ip, 0xff, sizeof(upper_border_ip));
+    borderSet = 1;
+  }
+
   if (borderSet) {
 
     /*
@@ -934,6 +943,11 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
                    tc, tc_edge_gc_timer_cookie->ci_id);
   }
 
+  if (emptyTC && borderSet) {
+    /* cleanup MIDs and HNAs if all edges have been erased by an empty TC */
+    olsr_cleanup_mid(&originator);
+    olsr_cleanup_hna(&originator);
+  }
   /* Forward the message */
   return true;
 }