sgw: move cost calculation into it own unit
authorFerry Huberts <ferry.huberts@pelagic.nl>
Fri, 12 Jul 2013 08:27:12 +0000 (10:27 +0200)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Fri, 12 Jul 2013 08:40:31 +0000 (10:40 +0200)
I'm going to reuse the code in another project

Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
src/gateway_costs.c [new file with mode: 0644]
src/gateway_costs.h [new file with mode: 0644]
src/gateway_default_handler.c

diff --git a/src/gateway_costs.c b/src/gateway_costs.c
new file mode 100644 (file)
index 0000000..805012d
--- /dev/null
@@ -0,0 +1,34 @@
+#include "gateway_costs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SCALING_SHIFT_CLASSIC 32
+#define SCALING_SHIFT 24
+
+uint64_t gw_costs_weigh(const struct costs_weights weights, uint32_t path_cost, uint32_t exitUk, uint32_t exitDk) {
+  uint64_t costU;
+  uint64_t costD;
+  uint64_t costE;
+
+  if (!weights.Detx) {
+    /* only consider path costs (classic behaviour) (but scale to 64 bit) */
+    return (uint64_t) path_cost << SCALING_SHIFT_CLASSIC;
+  }
+
+  if (!exitUk || !exitDk) {
+    /* no weighing factors or zero bandwidth */
+    return UINT64_MAX;
+  }
+
+  costU = (((uint64_t) (1000 * weights.WexitU))    << SCALING_SHIFT) / exitUk;
+  costD = (((uint64_t) (1000 * weights.WexitD))    << SCALING_SHIFT) / exitDk;
+  costE = (((uint64_t) (weights.Wetx * path_cost)) << SCALING_SHIFT) / weights.Detx;
+
+  return (costU + costD + costE);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/gateway_costs.h b/src/gateway_costs.h
new file mode 100644 (file)
index 0000000..31ca3c5
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef GATEWAY_COSTS_H_
+#define GATEWAY_COSTS_H_
+
+/*
+ * Weighing of the path costs:
+ *
+ * exitUm = the gateway exit link uplink   bandwidth, in Mbps
+ * exitDm = the gateway exit link downlink bandwidth, in Mbps
+ * WexitU = the gateway exit link uplink   bandwidth weight   (configured)
+ * WexitD = the gateway exit link downlink bandwidth weight   (configured)
+ * Wetx   = the ETX path cost weight                          (configured)
+ * Detx   = the ETX path cost divider                         (configured)
+ *
+ *                     WexitU   WexitD   Wetx
+ * path_cost_weight =  ------ + ------ + ---- * path_cost
+ *                     exitUm   exitDm   Detx
+ *
+ * Since the gateway exit link bandwidths are in Kbps, the following formula
+ * is used to convert them to the desired Mbps:
+ *
+ *       bwK
+ * bwM = ----       bwK = bandwidth in Kbps
+ *       1000       bwM = bandwidth in Mbps
+ *
+ * exitUk = the gateway exit link uplink   bandwidth, in Kbps
+ * exitDk = the gateway exit link downlink bandwidth, in Kbps
+ *
+ *                     1000 * WexitU   1000 * WexitD   Wetx
+ * path_cost_weight =  ------------- + ------------- + ---- * path_cost
+ *                         exitUk          exitDk      Detx
+ *
+ *
+ * Analysis of the required bit width of the result:
+ *
+ * exitUk    = [1,   320,000,000] = 29 bits
+ * exitDk    = [1,   320,000,000] = 29 bits
+ * WexitU    = [1,           255] =  8 bits
+ * WexitD    = [1,           255] =  8 bits
+ * Wetx      = [1,           255] =  8 bits
+ * Detx      = [1,           255] =  8 bits
+ * path_cost = [1, 4,294,967,295] = 32 bits
+ *
+ *                         1000 * 255   1000 * 255   255
+ * path_cost_weight(max) = ---------- + ---------- + --- * 4,294,967,295
+ *                              1             1       1
+ *
+ * path_cost_weight(max) = 0x3E418    + 0x3E418    + 0xFEFFFFFF01
+ * path_cost_weight(max) = 0xFF0007C731
+ *
+ * Because we can multiply 0xFF0007C731 by 2^24 without overflowing a
+ * 64 bits number, we do this to increase accuracy.
+ */
+
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  /**
+   * Structure to keep weighing factors for the gw_costs_weigh function
+   */
+  struct costs_weights {
+      uint8_t WexitU;
+      uint8_t WexitD;
+      uint8_t Wetx;
+      uint8_t Detx;
+  };
+
+  /**
+   * Weigh the path costs and the gateway bandwidth.
+   *
+   * If the ETX divider is zero, then no weighing is performed and only the path
+   * costs are considered (classic behaviour), but scaled to a 64 bit number.
+   *
+   * @param weights the weights for the calculation
+   * @param path_cost the (ETX) path cost to the gateway
+   * @param exitUk the gateway exit link uplink bandwidth (in kbps)
+   * @param exitDk the gateway exit link downlink bandwidth (in kbps)
+   * @return the weighed path cost, UINT64_MAX when exitUk and/or exitDk are zero
+   */
+  uint64_t gw_costs_weigh(const struct costs_weights weights, uint32_t path_cost, uint32_t exitUk, uint32_t exitDk);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GATEWAY_COSTS_H_ */
index 11bca37..115d1b5 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "gateway_default_handler.h"
 
+#include "gateway_costs.h"
 #include "defs.h"
 #include "gateway.h"
 #include "lq_plugin.h"
@@ -17,6 +18,7 @@ static uint32_t gw_def_stablecount;
 static bool gw_def_choose_new_ipv4_gw;
 static bool gw_def_choose_new_ipv6_gw;
 static struct timer_entry *gw_def_timer;
+static struct costs_weights gw_costs_weights;
 
 /* forward declarations */
 static void gw_default_init(void);
@@ -59,96 +61,6 @@ static inline uint64_t gw_default_calc_threshold(uint64_t path_cost) {
 }
 
 /**
- * Weigh the path costs and the gateway bandwidth.
- *
- * If the ETX divider is zero, then no weighing is performed and only the path
- * costs are considered (classic behaviour).
- *
- * If either of the uplink or downlink bandwidths is zero, then UINT64_MAX is
- * returned.
- *
- * @param path_cost the (ETX) path cost to the gateway
- * @param exitUk the gateway exit link uplink bandwidth (in kbps)
- * @param exitDk the gateway exit link downlink bandwidth (in kbps)
- * @return the weighed path cost
- */
-static inline uint64_t gw_default_weigh_costs(uint32_t path_cost, uint32_t exitUk, uint32_t exitDk) {
-  uint8_t WexitU = olsr_cnf->smart_gw_weight_exitlink_up;
-  uint8_t WexitD = olsr_cnf->smart_gw_weight_exitlink_down;
-  uint8_t Wetx = olsr_cnf->smart_gw_weight_etx;
-  uint8_t Detx = olsr_cnf->smart_gw_divider_etx;
-  uint64_t costU;
-  uint64_t costD;
-  uint64_t costE;
-
-  if (!Detx) {
-    /* only consider path costs (classic behaviour) (but scale to 64 bit) */
-    return (uint64_t)path_cost << 32;
-  }
-
-  if (!exitUk || !exitDk) {
-    /* zero bandwidth */
-    return UINT64_MAX;
-  }
-
-  /*
-   * Weighing of the path costs:
-   *
-   * exitUm = the gateway exit link uplink   bandwidth, in Mbps
-   * exitDm = the gateway exit link downlink bandwidth, in Mbps
-   * WexitU = the gateway exit link uplink   bandwidth weight   (configured)
-   * WexitD = the gateway exit link downlink bandwidth weight   (configured)
-   * Wetx   = the ETX path cost weight                          (configured)
-   * Detx   = the ETX path cost divider                         (configured)
-   *
-   *                     WexitU   WexitD   Wetx
-   * path_cost_weight =  ------ + ------ + ---- * path_cost
-   *                     exitUm   exitDm   Detx
-   *
-   * Since the gateway exit link bandwidths are in Kbps, the following formula
-   * is used to convert them to the desired Mbps:
-   *
-   *       bwK
-   * bwM = ----       bwK = bandwidth in Kbps
-   *       1000       bwM = bandwidth in Mbps
-   *
-   * exitUk = the gateway exit link uplink   bandwidth, in Kbps
-   * exitDk = the gateway exit link downlink bandwidth, in Kbps
-   *
-   *                     1000 * WexitU   1000 * WexitD   Wetx
-   * path_cost_weight =  ------------- + ------------- + ---- * path_cost
-   *                         exitUk          exitDk      Detx
-   *
-   *
-   * Analysis of the required bit width of the result:
-   *
-   * exitUk    = [1,   320,000,000] = 29 bits
-   * exitDk    = [1,   320,000,000] = 29 bits
-   * WexitU    = [1,           255] =  8 bits
-   * WexitD    = [1,           255] =  8 bits
-   * Wetx      = [1,           255] =  8 bits
-   * Detx      = [1,           255] =  8 bits
-   * path_cost = [1, 4,294,967,295] = 32 bits
-   *
-   *                         1000 * 255   1000 * 255   255
-   * path_cost_weight(max) = ---------- + ---------- + --- * 4,294,967,295
-   *                              1             1       1
-   *
-   * path_cost_weight(max) = 0x3E418    + 0x3E418    + 0xFEFFFFFF01
-   * path_cost_weight(max) = 0xFF0007C731
-   *
-   * Because we can multiply 0xFF0007C731 by 2^24 without overflowing a
-   * 64 bits number, we do this to increase accuracy.
-   */
-
-  costU = (((uint64_t) (1000 * WexitU)) << 24) / exitUk;
-  costD = (((uint64_t) (1000 * WexitD)) << 24) / exitDk;
-  costE = (((uint64_t) (Wetx * path_cost)) << 24) / Detx;
-
-  return (costU + costD + costE);
-}
-
-/**
  * Look through the gateway list and select the best gateway
  * depending on the distance to this router
  */
@@ -301,6 +213,11 @@ static void gw_default_init(void) {
   gw_def_choose_new_ipv4_gw = true;
   gw_def_choose_new_ipv6_gw = true;
   gw_def_timer = NULL;
+
+  gw_costs_weights.WexitU = olsr_cnf->smart_gw_weight_exitlink_up;
+  gw_costs_weights.WexitD = olsr_cnf->smart_gw_weight_exitlink_down;
+  gw_costs_weights.Wetx = olsr_cnf->smart_gw_weight_etx;
+  gw_costs_weights.Detx = olsr_cnf->smart_gw_divider_etx;
 }
 
 /**
@@ -354,7 +271,7 @@ static uint64_t gw_default_getcosts(struct gateway_entry *gw) {
   }
 
   /* determine the path cost */
-  return gw_default_weigh_costs(tc->path_cost, gw->uplink, gw->downlink);
+  return gw_costs_weigh(gw_costs_weights, tc->path_cost, gw->uplink, gw->downlink);
 }
 
 /**