sgw: introduce function to process multi-sgw changes
authorFerry Huberts <ferry.huberts@pelagic.nl>
Fri, 31 Oct 2014 11:33:12 +0000 (12:33 +0100)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Wed, 12 Nov 2014 10:45:25 +0000 (11:45 +0100)
Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
src/egressFile.c
src/gateway.c
src/gateway.h

index 3744988..0665574 100644 (file)
@@ -7,6 +7,7 @@
 /* OLSRD includes */
 #include "olsr_cfg.h"
 #include "gateway_costs.h"
+#include "gateway.h"
 #include "scheduler.h"
 #include "ipcalc.h"
 #include "log.h"
@@ -323,7 +324,7 @@ static struct timer_entry *egress_file_timer;
  */
 static void egress_file_timer_callback(void *unused __attribute__ ((unused))) {
   if (readEgressFile(olsr_cnf->smart_gw_egress_file)) {
-    // FIXME process changes
+    doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_RUNTIME);
   }
 }
 
index fa9a978..556c844 100644 (file)
@@ -503,7 +503,7 @@ static void doEgressInterface(int if_index, enum olsr_ifchg_flag flag) {
       return;
   }
 
-  // FIXME process changes
+  doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_RUNTIME);
 }
 
 /*
@@ -772,7 +772,7 @@ int olsr_startup_gateways(void) {
   }
 
   startEgressFile();
-  // FIXME process changes (always: initial setup)
+  doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_STARTUP);
 
   olsr_add_ifchange_handler(smartgw_tunnel_monitor);
 
@@ -839,7 +839,7 @@ void olsr_shutdown_gateways(void) {
       egress_if = egress_if->next;
     }
   }
-  // FIXME process changes (always: shutdown)
+  doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_SHUTDOWN);
 
   (void)multiGwRulesSgwTunnels(false);
   (void)multiGwRulesEgressInterfaces(false);
@@ -1101,6 +1101,14 @@ void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_add
       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv6, new_gw_in_list);
       assert(new_gw_in_list);
     }
+
+    if (multi_gateway_mode() && //
+        ((!gw->ipv6 && current_ipv4_gw && current_ipv4_gw->gw == gw) || //
+         (gw->ipv6 && current_ipv6_gw && current_ipv6_gw->gw == gw)) //
+        ) {
+      /* the active gw has changed its costs: re-evaluate egress routes */
+      doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
+    }
   }
 
   /* call update handler */
@@ -1299,6 +1307,10 @@ bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv
       assert(new_gw_in_list->tunnel);
       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
       current_ipv4_gw = new_gw_in_list;
+
+      if (multi_gateway_mode()) {
+        doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
+      }
     } else {
       /* new gw is not yet in the gw list */
       char name[IFNAMSIZ];
@@ -1325,6 +1337,10 @@ bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv
         new_gw_in_list->gw = new_gw;
         new_gw_in_list->tunnel = new_v4gw_tunnel;
         current_ipv4_gw = olsr_gw_list_add(&gw_list_ipv4, new_gw_in_list);
+
+        if (multi_gateway_mode()) {
+          doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
+        }
       } else {
         /* adding the tunnel failed, we try again in the next cycle */
         set_unused_iptunnel_name(new_gw);
@@ -1345,6 +1361,10 @@ bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv
       assert(new_gw_in_list->tunnel);
       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
       current_ipv6_gw = new_gw_in_list;
+
+      if (multi_gateway_mode()) {
+        doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
+      }
     } else {
       /* new gw is not yet in the gw list */
       char name[IFNAMSIZ];
@@ -1371,6 +1391,10 @@ bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv
         new_gw_in_list->gw = new_gw;
         new_gw_in_list->tunnel = new_v6gw_tunnel;
         current_ipv6_gw = olsr_gw_list_add(&gw_list_ipv6, new_gw_in_list);
+
+        if (multi_gateway_mode()) {
+          doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
+        }
       } else {
         /* adding the tunnel failed, we try again in the next cycle */
         set_unused_iptunnel_name(new_gw);
@@ -1396,4 +1420,33 @@ struct gateway_entry *olsr_get_inet_gateway(bool ipv6) {
        return current_ipv4_gw ? current_ipv4_gw->gw : NULL;
 }
 
+/*
+ * Process Egress Changes
+ */
+
+/**
+ * Process changes that are relevant to egress interface: changes to the
+ * egress interfaces themselves and to the smart gateway that is chosen by olsrd
+ *
+ * @param egressChanged true when an egress interface changed
+ * @param olsrChanged true when the smart gateway changed
+ * @param phase the phase of the change (startup/runtime/shutdown)
+ */
+void doRoutesMultiGw(bool egressChanged, bool olsrChanged __attribute__((unused)), enum sgw_multi_change_phase phase __attribute__((unused))) {
+  if (egressChanged) {
+    /* clear the 'changed' flags of egress interfaces */
+    struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
+    while (egress_if) {
+      egress_if->upChanged = false;
+
+      egress_if->bwCostsChanged = false;
+      egress_if->bwNetworkChanged = false;
+      egress_if->bwGatewayChanged = false;
+      egress_if->bwChanged = false;
+
+      egress_if = egress_if->next;
+    }
+  }
+}
+
 #endif /* __linux__ */
index 52dfe30..c761c4f 100644 (file)
@@ -70,6 +70,12 @@ struct gateway_entry {
     uint16_t seqno;
 };
 
+enum sgw_multi_change_phase {
+  GW_MULTI_CHANGE_PHASE_STARTUP = 0,
+  GW_MULTI_CHANGE_PHASE_RUNTIME = 1,
+  GW_MULTI_CHANGE_PHASE_SHUTDOWN = 2
+};
+
 /**
  * static inline struct gateway_entry * node2gateway (struct avl_node *ptr)
  *
@@ -191,4 +197,10 @@ void olsr_trigger_gatewayloss_check(void);
 bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv6);
 struct gateway_entry *olsr_get_inet_gateway(bool ipv6);
 
+/*
+ * Multi Smart Gateway functions
+ */
+
+void doRoutesMultiGw(bool egressChanged, bool olsrChanged, enum sgw_multi_change_phase phase);
+
 #endif /* GATEWAY_H_ */