Add listener for gateway changes.
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 27 Jan 2010 14:40:20 +0000 (15:40 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 27 Jan 2010 14:40:20 +0000 (15:40 +0100)
More code cleanup of gateway path.

lib/dot_draw/src/olsrd_dot_draw.c
lib/txtinfo/src/olsrd_txtinfo.c
src/gateway.c
src/gateway.h
src/hna_set.c
src/hna_set.h
src/olsr.c
src/tc_set.c

index 348380e..23f7113 100644 (file)
@@ -360,7 +360,8 @@ pcf_event(int my_changes_neighborhood, int my_changes_topology, int my_changes_h
 
       /* Check all networks */
       for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
-        ipc_print_net(&outbuffer, &tmp_hna->A_gateway_addr, &tmp_net->A_network_addr, tmp_net->prefixlen);
+        ipc_print_net(&outbuffer, &tmp_hna->A_gateway_addr,
+            &tmp_net->hna_prefix.prefix, tmp_net->hna_prefix.prefix_len);
       }
     }
     OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
index 94b7813..a3fcc33 100644 (file)
@@ -478,8 +478,8 @@ ipc_print_hna(struct autobuf *abuf)
                    olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr),
                    diff/1000, abs(diff%1000));
 #else
-      abuf_appendf(abuf, "%s/%d\t%s\n", olsr_ip_to_string(&buf, &tmp_net->A_network_addr), tmp_net->prefixlen,
-                olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
+      abuf_appendf(abuf, "%s/%d\t%s\n", olsr_ip_to_string(&buf, &tmp_net->hna_prefix.prefix),
+          tmp_net->hna_prefix.prefix_len, olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
 #endif /*vtime txtinfo*/
     }
   }
index a28614d..30ddd8e 100644 (file)
 #include "gateway.h"
 
 struct avl_tree gateway_tree;
+struct list_node gw_listener_list;;
+
 static struct olsr_cookie_info *gw_mem_cookie = NULL;
 static uint8_t smart_gateway_netmask[sizeof(union olsr_ip_addr)];
+static struct gateway_entry *current_ipv4_gw, *current_ipv6_gw;
 
 static uint32_t deserialize_gw_speed(uint8_t value) {
   uint32_t speed, exp;
@@ -50,23 +53,25 @@ olsr_init_gateways(void) {
   olsr_cookie_set_memory_size(gw_mem_cookie, sizeof(struct gateway_entry));
 
   avl_init(&gateway_tree, avl_comp_default);
+  list_head_init(&gw_listener_list);
+  current_ipv4_gw = NULL;
+  current_ipv6_gw = NULL;
 
   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
 
   if (olsr_cnf->smart_gw_active) {
     union olsr_ip_addr gw_net;
+#ifdef MAXIMUM_GATEWAY_PREFIX_LENGTH
     int prefix;
+#endif
 
     memset(&gw_net, 0, sizeof(gw_net));
 
-    /*
-     * hack for Vienna network to remove 0.0.0.0/128.0.0.0 and 128.0.0.0/128.0.0.0 routes
-     * just set MAXIMUM_GATEWAY_PREFIX_LENGTH to 1
-     */
+#ifdef MAXIMUM_GATEWAY_PREFIX_LENGTH
     for (prefix = 1; prefix <= MAXIMUM_GATEWAY_PREFIX_LENGTH; prefix++) {
       while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &gw_net, prefix));
     }
-
+#endif
     ip = (uint8_t *) &smart_gateway_netmask;
 
     if (olsr_cnf->smart_gw_uplink > 0 || olsr_cnf->smart_gw_downlink > 0) {
@@ -82,19 +87,33 @@ olsr_init_gateways(void) {
   }
 }
 
+void
+olsr_add_inetgw_listener(struct olsr_gw_change_handler *l) {
+  list_node_init(&l->node);
+  list_add_after(&gw_listener_list, &l->node);
+}
+
+void
+olsr_remove_inetgw_listener(struct olsr_gw_change_handler *l) {
+  list_remove(&l->node);
+}
+
 struct gateway_entry *
-olsr_find_gateway(union olsr_ip_addr *originator) {
+olsr_find_gateway_entry(union olsr_ip_addr *originator) {
   struct avl_node *node = avl_find(&gateway_tree, originator);
 
   return node == NULL ? NULL : node2gateway(node);
 }
 
 void
-olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen) {
+olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen) {
   struct gateway_entry *gw;
-  uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
+  struct olsr_gw_change_handler *listener;
+  uint8_t *ptr;
+
+  ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
 
-  gw = olsr_find_gateway(originator);
+  gw = olsr_find_gateway_entry(originator);
   if (!gw) {
     gw = olsr_cookie_malloc(gw_mem_cookie);
 
@@ -131,17 +150,49 @@ olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int p
       }
     }
   }
+
+  OLSR_FOR_ALL_GW_LISTENERS(listener) {
+    listener->handle_update_gw(gw);
+  } OLSR_FOR_ALL_GW_LISTENERS_END(listener)
 }
 
 void
-olsr_delete_gateway(union olsr_ip_addr *originator) {
+olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen) {
   struct gateway_entry *gw;
+  struct olsr_gw_change_handler *listener;
+  bool change = false;
 
-  gw = olsr_find_gateway(originator);
+  gw = olsr_find_gateway_entry(originator);
   if (gw) {
-    avl_delete(&gateway_tree, &gw->node);
+    if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
+      gw->ipv4 = false;
+      gw->ipv4nat = false;
+      change = true;
+    }
+    if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
+      gw->ipv6 = false;
+      change = true;
+    }
+    if (olsr_cnf->ip_version == AF_INET6 && prefixlen == mapped_v4_gw.prefix_len) {
+      gw->ipv4 = false;
+      gw->ipv4nat = false;
+      change = true;
+    }
+
+    if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
+      OLSR_FOR_ALL_GW_LISTENERS(listener) {
+        listener->handle_delete_gw(gw);
+      } OLSR_FOR_ALL_GW_LISTENERS_END(listener)
+
+      avl_delete(&gateway_tree, &gw->node);
 
-    olsr_cookie_free(gw_mem_cookie, gw);
+      olsr_cookie_free(gw_mem_cookie, gw);
+    }
+    else if (change) {
+      OLSR_FOR_ALL_GW_LISTENERS(listener) {
+        listener->handle_update_gw(gw);
+      } OLSR_FOR_ALL_GW_LISTENERS_END(listener)
+    }
   }
 }
 
@@ -176,7 +227,7 @@ void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
 }
 
 void
-olsr_print_gateway(void) {
+olsr_print_gateway_entries(void) {
 #ifndef NODEBUG
   struct ipaddr_str buf;
   struct gateway_entry *gw;
index c39d3c0..5ee55e5 100644 (file)
@@ -9,10 +9,17 @@
 #define GATEWAY_H_
 
 #include "common/avl.h"
+#include "common/list.h"
 #include "defs.h"
 #include "olsr.h"
 
-#define MAXIMUM_GATEWAY_PREFIX_LENGTH 0
+#define FORCE_DELETE_GW_ENTRY 255
+
+/*
+ * hack for Vienna network to remove 0.0.0.0/128.0.0.0 and 128.0.0.0/128.0.0.0 routes
+ * just set MAXIMUM_GATEWAY_PREFIX_LENGTH to 1
+ */
+// #define MAXIMUM_GATEWAY_PREFIX_LENGTH 1
 
 enum gateway_hna_flags {
   GW_HNA_FLAG_LINKSPEED  = 1<<0,
@@ -55,10 +62,37 @@ AVLNODE2STRUCT(node2gateway, struct gateway_entry, node);
 extern struct avl_tree gateway_tree;
 
 void olsr_init_gateways(void);
-struct gateway_entry *olsr_find_gateway(union olsr_ip_addr *originator);
-void olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen);
-void olsr_delete_gateway(union olsr_ip_addr *originator);
+
+struct gateway_entry *olsr_find_gateway_entry(union olsr_ip_addr *originator);
+void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen);
+void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen);
+void olsr_print_gateway_entries(void);
+
+void olsr_set_inet_gateway(union olsr_ip_addr *originator, bool ipv4, bool ipv6);
 bool olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *net);
-void olsr_print_gateway(void);
 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen);
+
+struct olsr_gw_change_handler {
+  struct list_node node;
+  void (* handle_update_gw)(struct gateway_entry *);
+  void (* handle_delete_gw)(struct gateway_entry *);
+};
+
+LISTNODE2STRUCT(gwnode2list, struct olsr_gw_change_handler, node);
+
+/* deletion safe macro for list traversal */
+#define OLSR_FOR_ALL_GW_LISTENERS(l) \
+{ \
+  struct list_node *link_head_node, *link_node, *next_link_node; \
+  link_head_node = &gw_listener_list; \
+  for (link_node = link_head_node->next; \
+    link_node != link_head_node; link_node = next_link_node) { \
+    next_link_node = link_node->next; \
+    l = gwnode2list(link_node);
+#define OLSR_FOR_ALL_GW_LISTENERS_END(l) }}
+
+extern struct list_node gw_listener_list;
+
+void olsr_add_inetgw_listener(struct olsr_gw_change_handler *l);
+void olsr_remove_inetgw_listener(struct olsr_gw_change_handler *l);
 #endif /* GATEWAY_H_ */
index 7f5df3c..5d5f7ba 100644 (file)
@@ -107,7 +107,7 @@ olsr_lookup_hna_net(const struct hna_net *nets, const union olsr_ip_addr *net, u
 
   /* Loop trough entrys */
   for (tmp = nets->next; tmp != nets; tmp = tmp->next) {
-    if (tmp->prefixlen == prefixlen && ipequal(&tmp->A_network_addr, net)) {
+    if (tmp->hna_prefix.prefix_len == prefixlen && ipequal(&tmp->hna_prefix.prefix, net)) {
       return tmp;
     }
   }
@@ -193,8 +193,8 @@ olsr_add_hna_net(struct hna_entry *hna_gw, const union olsr_ip_addr *net, uint8_
 
   /* Fill struct */
   memset(new_net, 0, sizeof(struct hna_net));
-  new_net->A_network_addr = *net;
-  new_net->prefixlen = prefixlen;
+  new_net->hna_prefix.prefix = *net;
+  new_net->hna_prefix.prefix_len= prefixlen;
 
   /* Set backpointer */
   new_net->hna_gw = hna_gw;
@@ -216,9 +216,9 @@ olsr_delete_hna_net_entry(struct hna_net *net_to_delete) {
   struct hna_entry *hna_gw;
   bool removed_entry = false;
 
-  if (net_to_delete->prefixlen == 0) {
-    /* remove gateway if HNA 0/0 is removed */
-    olsr_delete_gateway(&net_to_delete->hna_gw->A_gateway_addr);
+  if (ip_is_inetgw_prefix(&net_to_delete->hna_prefix)) {
+    /* modify smart gateway entry if necessary */
+    olsr_delete_gateway_entry(&net_to_delete->hna_gw->A_gateway_addr, net_to_delete->hna_prefix.prefix_len);
   }
 
   olsr_stop_timer(net_to_delete->hna_net_timer);
@@ -226,14 +226,16 @@ olsr_delete_hna_net_entry(struct hna_net *net_to_delete) {
   hna_gw = net_to_delete->hna_gw;
 
 #ifdef DEBUG
-  OLSR_PRINTF(5, "HNA: timeout %s/%u via hna-gw %s\n", olsr_ip_to_string(&buf1, &net_to_delete->A_network_addr),
-              net_to_delete->prefixlen, olsr_ip_to_string(&buf2, &hna_gw->A_gateway_addr));
+  OLSR_PRINTF(5, "HNA: timeout %s via hna-gw %s\n",
+      olsr_ip_prefix_to_string(&net_to_delete->hna_prefix),
+              olsr_ip_to_string(&buf2, &hna_gw->A_gateway_addr));
 #endif
 
   /*
    * Delete the rt_path for the entry.
    */
-  olsr_delete_routing_table(&net_to_delete->A_network_addr, net_to_delete->prefixlen, &hna_gw->A_gateway_addr);
+  olsr_delete_routing_table(&net_to_delete->hna_prefix.prefix,
+      net_to_delete->hna_prefix.prefix_len, &hna_gw->A_gateway_addr);
 
   DEQUEUE_ELEM(net_to_delete);
 
@@ -294,7 +296,8 @@ olsr_update_hna_entry(const union olsr_ip_addr *gw, const union olsr_ip_addr *ne
   /*
    * Add the rt_path for the entry.
    */
-  olsr_insert_routing_table(&net_entry->A_network_addr, net_entry->prefixlen, &gw_entry->A_gateway_addr, OLSR_RT_ORIGIN_HNA);
+  olsr_insert_routing_table(&net_entry->hna_prefix.prefix,
+      net_entry->hna_prefix.prefix_len, &gw_entry->A_gateway_addr, OLSR_RT_ORIGIN_HNA);
 
   /*
    * Start, or refresh the timer, whatever is appropriate.
@@ -448,12 +451,14 @@ olsr_input_hna(union olsr_message *m, struct interface *in_if __attribute__ ((un
     prefix.prefix_len = olsr_netmask_to_prefix(&mask);
 
     if (olsr_cnf->smart_gw_active && olsr_is_smart_gateway(&prefix, &mask)) {
-      olsr_set_gateway(&originator, &mask, prefix.prefix_len);
+      olsr_update_gateway_entry(&originator, &mask, prefix.prefix_len);
     }
 
+#ifdef MAXIMUM_GATEWAY_PREFIX_LENGTH
     if (olsr_cnf->smart_gw_active && prefix.prefix_len > 0 && prefix.prefix_len <= MAXIMUM_GATEWAY_PREFIX_LENGTH) {
       continue;
     }
+#endif
 
 #ifndef NO_DUPLICATE_DETECTION_HANDLER
     for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
index 2ea93e0..cb87186 100644 (file)
@@ -52,8 +52,7 @@
 /* hna_netmask declared in packet.h */
 
 struct hna_net {
-  union olsr_ip_addr A_network_addr;
-  uint8_t prefixlen;
+  struct olsr_ip_prefix hna_prefix;
   struct timer_entry *hna_net_timer;
   struct hna_entry *hna_gw;            /* backpointer to the owning HNA entry */
   struct hna_net *next;
index 0baf5f8..e118d02 100644 (file)
@@ -231,7 +231,7 @@ olsr_process_changes(void)
     olsr_print_tc_table();
 
     // TODO push this to debug level 3 or 4
-    olsr_print_gateway();
+    olsr_print_gateway_entries();
 #endif
   }
 
index 9cf22a0..ee8af8d 100644 (file)
@@ -286,7 +286,7 @@ olsr_delete_tc_entry(struct tc_entry *tc)
 #endif
 
   /* delete gateway if available */
-  olsr_delete_gateway(&tc->addr);
+  olsr_delete_gateway_entry(&tc->addr, FORCE_DELETE_GW_ENTRY);
 
   /*
    * Delete the rt_path for ourselves.