PUD: implement gateway selection / cluster leader selection
authorFerry Huberts <f.huberts@mindef.nl>
Wed, 24 Aug 2011 07:42:30 +0000 (09:42 +0200)
committerFerry Huberts <f.huberts@mindef.nl>
Tue, 18 Oct 2011 10:08:27 +0000 (12:08 +0200)
We use the smart gateway functionality of OLSR for
selection of the cluster leader. A cluster leader
is the node that receives position updates from
the relay server. These position updates are then
distributed over the MANET by the cluster leader.

Signed-off-by: Ferry Huberts <f.huberts@mindef.nl>
lib/pud/doc/olsrd.conf.default.pud
lib/pud/src/receiver.c
lib/pud/src/uplinkGateway.c [new file with mode: 0644]
lib/pud/src/uplinkGateway.h [new file with mode: 0644]

index 428aeb7..84a09c9 100644 (file)
@@ -141,7 +141,7 @@ LockFile "/tmp/olsrd.lock"
 # See README-Olsr-Extensions for a description of smartgateways.
 # (default is "yes")
 
-SmartGateway yes
+SmartGateway yes
 
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
@@ -166,6 +166,7 @@ LockFile "/tmp/olsrd.lock"
 # (default is 128/1024)
 
 # SmartGatewaySpeed 128 1024
+SmartGatewaySpeed 1024 8192
 
 # Specifies the EXTERNAL ipv6 prefix of the uplink. A prefix
 # length of more than 64 is not allowed.
@@ -208,7 +209,7 @@ LockFile "/tmp/olsrd.lock"
 Hna4
 {
 # Internet gateway
-0.0.0.0   0.0.0.0
+0.0.0.0   0.0.0.0
 # specific small networks reachable through this node
 # 15.15.0.0 255.255.255.0
 }
@@ -280,7 +281,7 @@ Hna6
 #   ethernet links with ETX 0.1.
 # (defaults to "etx_ff")
 
-# LinkQualityAlgorithm    "etx_ff"
+LinkQualityAlgorithm    "etx_ffeth"
 
 # Link quality aging factor (only for lq level 2)
 # Tuning parameter for etx_float and etx_fpm, smaller values
index 9b2a4f3..45581b8 100644 (file)
@@ -9,6 +9,7 @@
 #include "posAvg.h"
 #include "networkInterfaces.h"
 #include "compiler.h"
+#include "uplinkGateway.h"
 
 /* OLSRD includes */
 #include "net_olsr.h"
@@ -256,9 +257,7 @@ static void txToAllOlsrInterfaces(TimedTxInterface interfaces) {
                if (((interfaces & UPLINK) != 0) && isUplinkAddrSet()) {
                        int fd = getUplinkSocketFd();
                        if (fd != -1) {
-                               /* FIXME until we have gateway selection we just send ourselves
-                                * as cluster leader */
-                               union olsr_ip_addr * gwAddr = &olsr_cnf->main_addr;
+                               union olsr_ip_addr * gwAddr = getBestUplinkGateway();
 
                                UplinkMessage * message2 =
                                                (UplinkMessage *) &txBuffer[aligned_size
diff --git a/lib/pud/src/uplinkGateway.c b/lib/pud/src/uplinkGateway.c
new file mode 100644 (file)
index 0000000..c877692
--- /dev/null
@@ -0,0 +1,89 @@
+#include "uplinkGateway.h"
+
+/* Plugin includes */
+
+/* OLSRD includes */
+#include "gateway.h"
+#include "tc_set.h"
+#include "ipcalc.h"
+#include "olsr_types.h"
+
+/* System includes */
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+
+/**
+ * Determine the best gateway for uplink: this is the cluster leader.
+ *
+ * Loop over all gateways to find the best one and return it.
+ * When no best gateway is found then we return ourselves so that the behaviour
+ * degrades gracefully.
+ *
+ * A gateway is better when the sum of its uplink and downlink are greater than
+ * the previous best gateway. In case of a tie, the lowest IP address wins.
+ *
+ * This code is copied from lib/txtinfo/src/olsrd_txtinfo.c::ipc_print_gateway.
+ * It adjusted for best gateway selection but otherwise kept the same as much
+ * as possible.
+ *
+ * @return
+ * a pointer to the IP address of the best gateway
+ */
+union olsr_ip_addr * getBestUplinkGateway(void) {
+       struct gateway_entry *gw_best = NULL;
+       unsigned long long gw_best_value = 0;
+       struct gateway_entry *gw;
+
+       OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
+               bool eval4 = false;
+               bool eval6 = false;
+
+               struct tc_entry * tc = olsr_lookup_tc_entry(&gw->originator);
+               if (tc == NULL) {
+                       continue;
+               }
+
+               if (gw == olsr_get_ipv4_inet_gateway(NULL)) {
+                       eval4 = true;
+               } else if (gw->ipv4
+                               && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit)
+                               && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat)) {
+                       eval4 = true;
+               }
+
+               if (gw == olsr_get_ipv6_inet_gateway(NULL)) {
+                       eval6 = true;
+               } else if (gw->ipv6 && olsr_cnf->ip_version == AF_INET6) {
+                       eval6 = true;
+               }
+
+               if (eval4 || eval6) {
+                       unsigned long long gw_value = gw->uplink + gw->downlink;
+                       if (gw_value > gw_best_value) {
+                               gw_best = gw;
+                               gw_best_value = gw_value;
+                       } else if (gw_value == gw_best_value) {
+                               bool gwHaslowerIpAddress = false;
+                               if (eval4) {
+                                       gwHaslowerIpAddress = (ip4cmp(&gw->originator.v4,
+                                                       &gw_best->originator.v4) < 0);
+                               } else /* eval6 */{
+                                       gwHaslowerIpAddress = (ip6cmp(&gw->originator.v6,
+                                                       &gw_best->originator.v6) < 0);
+                               }
+                               if (gwHaslowerIpAddress) {
+                                       gw_best = gw;
+                                       gw_best_value = gw_value;
+                               }
+                       }
+               }
+       } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
+
+       if (!gw_best) {
+               /* degrade gracefully */
+               return &olsr_cnf->main_addr;
+       }
+
+       return &gw_best->originator;
+}
diff --git a/lib/pud/src/uplinkGateway.h b/lib/pud/src/uplinkGateway.h
new file mode 100644 (file)
index 0000000..2996748
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _PUD_UPLINKGATEWAY_H_
+#define _PUD_UPLINKGATEWAY_H_
+
+/* Plugin includes */
+
+/* OLSRD includes */
+#include "olsr_types.h"
+
+/* System includes */
+
+union olsr_ip_addr * getBestUplinkGateway(void);
+
+#endif /* _PUD_UPLINKGATEWAY_H_ */