[Olsr-dev] [PATCH v1 1/2] sgwdynspeed: add plugin

Ferry Huberts (spam-protected)
Tue May 15 15:06:04 CEST 2012


From: Ferry Huberts <(spam-protected)>

This plugins provides a means to dynamically adjust the
smartgateway upstream and downstream bandwidths.

Signed-off-by: Ferry Huberts <(spam-protected)>
---
 lib/sgwdynspeed/Makefile                           |   57 +++++
 lib/sgwdynspeed/Makefile.inc                       |    7 +
 lib/{pud => sgwdynspeed}/doc/.gitignore            |    2 +-
 lib/{pud => sgwdynspeed}/doc/Makefile              |    0
 lib/{pud => sgwdynspeed}/doc/doxygen.conf          |    0
 .../sgwdynspeed/resources/olsrd.conf.default.pud   |  140 ++++++++-----
 lib/sgwdynspeed/resources/olsrd.sgw.speed.conf     |   14 ++
 lib/sgwdynspeed/src/configuration.c                |  167 ++++++++++++++
 lib/sgwdynspeed/src/configuration.h                |   40 ++++
 .../src/olsrdPlugin.c}                             |   27 +--
 lib/sgwdynspeed/src/olsrdPlugin.h                  |   26 +++
 lib/sgwdynspeed/src/sgwDynSpeed.c                  |  122 ++++++++++
 lib/sgwdynspeed/src/sgwDynSpeed.h                  |   30 +++
 lib/sgwdynspeed/src/speedFile.c                    |  238 ++++++++++++++++++++
 lib/sgwdynspeed/src/speedFile.h                    |   15 ++
 lib/{arprefresh => sgwdynspeed}/version-script.txt |    0
 16 files changed, 819 insertions(+), 66 deletions(-)
 create mode 100644 lib/sgwdynspeed/Makefile
 create mode 100644 lib/sgwdynspeed/Makefile.inc
 copy lib/{pud => sgwdynspeed}/doc/.gitignore (63%)
 copy lib/{pud => sgwdynspeed}/doc/Makefile (100%)
 copy lib/{pud => sgwdynspeed}/doc/doxygen.conf (100%)
 copy files/olsrd.conf.default.full => lib/sgwdynspeed/resources/olsrd.conf.default.pud (86%)
 create mode 100644 lib/sgwdynspeed/resources/olsrd.sgw.speed.conf
 create mode 100644 lib/sgwdynspeed/src/configuration.c
 create mode 100644 lib/sgwdynspeed/src/configuration.h
 copy lib/{pud/src/pudOlsrdPlugin.c => sgwdynspeed/src/olsrdPlugin.c} (72%)
 create mode 100644 lib/sgwdynspeed/src/olsrdPlugin.h
 create mode 100644 lib/sgwdynspeed/src/sgwDynSpeed.c
 create mode 100644 lib/sgwdynspeed/src/sgwDynSpeed.h
 create mode 100644 lib/sgwdynspeed/src/speedFile.c
 create mode 100644 lib/sgwdynspeed/src/speedFile.h
 copy lib/{arprefresh => sgwdynspeed}/version-script.txt (100%)

diff --git a/lib/sgwdynspeed/Makefile b/lib/sgwdynspeed/Makefile
new file mode 100644
index 0000000..d012702
--- /dev/null
+++ b/lib/sgwdynspeed/Makefile
@@ -0,0 +1,57 @@
+include Makefile.inc
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+
+CFLAGS += -Werror
+
+RESOURCESDIR = ./resources
+
+ifneq ($(OS),linux)
+
+.PHONY: all default_target install clean
+
+all: default_target
+
+default_target install clean:
+	@echo "*** $(PLUGIN_NAME) plugin only supported on Linux, sorry!"
+
+else
+
+GIT_SHA = $(shell git describe 2> /dev/null || echo "Unknown")
+CFLAGS += -DGIT_SHA=\"$(GIT_SHA)\" -DPLUGIN_VER=\"$(PLUGIN_VER)\"
+
+.PHONY: all default_target install uninstall clean doc doc-clean java java-instal java-uninstall
+
+all: default_target
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+	@echo "[LD] $@"
+	@$(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install: all
+	$(INSTALL_LIB)
+	mkdir -p "$(ETCDIR)"
+	cp "$(RESOURCESDIR)/olsrd.sgw.speed.conf" "$(ETCDIR)"
+	$(STRIP) "$(LIBDIR)/$(PLUGIN_FULLNAME)"
+
+uninstall:
+	rm -f "$(LIBDIR)/lib$(PLUGIN_NAME).so" "$(LIBDIR)/$(PLUGIN_NAME)" "$(ETCDIR)/olsrd.sgw.speed.conf"
+	$(UNINSTALL_LIB)
+	rmdir -v -p --ignore-fail-on-non-empty "$(LIBDIR)" "$(ETCDIR)"
+
+clean:
+	@echo "[$@]"
+	@rm -f $(OBJS) $(SRCS:%.c=%.d) "$(PLUGIN_FULLNAME)"
+	@$(MAKE) -C doc clean
+
+doc:
+	@$(MAKE) -C doc all
+
+doc-clean:
+	@$(MAKE) -C doc clean
+
+endif
diff --git a/lib/sgwdynspeed/Makefile.inc b/lib/sgwdynspeed/Makefile.inc
new file mode 100644
index 0000000..454884c
--- /dev/null
+++ b/lib/sgwdynspeed/Makefile.inc
@@ -0,0 +1,7 @@
+# activate debugging with 1 or deactivate with 0
+DEBUG ?= 1
+
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME  = olsrd_sgwdynspeed
+PLUGIN_VER   = 1.0.0
diff --git a/lib/pud/doc/.gitignore b/lib/sgwdynspeed/doc/.gitignore
similarity index 63%
copy from lib/pud/doc/.gitignore
copy to lib/sgwdynspeed/doc/.gitignore
index cebfb10..cee49b0 100644
--- a/lib/pud/doc/.gitignore
+++ b/lib/sgwdynspeed/doc/.gitignore
@@ -2,4 +2,4 @@
 /man/
 /latex/
 /doxygen.conf.temp
-/olsrd_pud.pdf
+/olsrd_sgwdynspeed.pdf
diff --git a/lib/pud/doc/Makefile b/lib/sgwdynspeed/doc/Makefile
similarity index 100%
copy from lib/pud/doc/Makefile
copy to lib/sgwdynspeed/doc/Makefile
diff --git a/lib/pud/doc/doxygen.conf b/lib/sgwdynspeed/doc/doxygen.conf
similarity index 100%
copy from lib/pud/doc/doxygen.conf
copy to lib/sgwdynspeed/doc/doxygen.conf
diff --git a/files/olsrd.conf.default.full b/lib/sgwdynspeed/resources/olsrd.conf.default.pud
similarity index 86%
copy from files/olsrd.conf.default.full
copy to lib/sgwdynspeed/resources/olsrd.conf.default.pud
index 8088a43..3306ed4 100644
--- a/files/olsrd.conf.default.full
+++ b/lib/sgwdynspeed/resources/olsrd.conf.default.pud
@@ -18,12 +18,12 @@
 # If set to 0 the daemon runs in the background, unless "NoFork" is set to true
 # (Default is 1)
 
-# DebugLevel  1
+DebugLevel  0
 
 # IP version to use (4 or 6)
 # (Default is 4)
 
-# IpVersion 4
+IpVersion 4
 
 #################################
 ### OLSRd agent configuration ###
@@ -49,7 +49,7 @@
 # (Linux/BSD default is "/var/run/olsrd-ipv(4/6).lock")
 # (Win32 default is "<configfile>-ipv(4/6).lock")
 
-# LockFile "olsrd.lock"
+LockFile "/tmp/olsrd.lock"
 
 # Polling rate for OLSR sockets in seconds (float). 
 # (Default is 0.05)
@@ -62,11 +62,10 @@
 
 # NicChgsPollInt  2.5
 
-# TOS(type of service) byte value for the IP header of control traffic.
-# Must be multiple of 4, because OLSR doesn't use ECN
-# (Default is 192, CS6 - Network Control)
+# TOS(type of service) value for the IP header of control traffic.
+# (Default is 16)
 
-# TosValue 192
+# TosValue 16
 
 # FIBMetric controls the metric value of the host-routes OLSRd sets.
 # - "flat" means that the metric value is always 2. This is the preferred value
@@ -140,9 +139,9 @@
 
 # Activates the smartgateway ipip tunnel feature.
 # See README-Olsr-Extensions for a description of smartgateways.
-# (default is "no")
+# (default is "yes")
 
-# SmartGateway no
+SmartGateway yes
 
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
@@ -167,6 +166,7 @@
 # (defaults to 0)
 
 # SmartGatewayThreshold 0
+SmartGatewayThreshold   67
 
 # Defines what kind of Uplink this node will publish as a
 # smartgateway. The existence of the uplink is detected by
@@ -186,22 +186,14 @@
 # (default is 128/1024)
 
 # SmartGatewaySpeed 128 1024
+SmartGatewaySpeed 128 1024
 
 # Specifies the EXTERNAL ipv6 prefix of the uplink. A prefix
 # length of more than 64 is not allowed.
-# (default is 0::/0)
+# (default is 0::/0
 
 # SmartGatewayPrefix 0::/0
 
-# Set to yes will make OLSRd to set the file 
-# /proc/sys/net/ipv4/ip_forward to 1 during startup. It will be
-# restored to the original value during shutdown
-# Set this to no makes OLSRd check the value, if its not 1
-# OLSRd will exit with an error.
-# (default is yes)
-
-# SetIpForward yes
-
 ##############################
 ### OLSR protocol settings ###
 ##############################
@@ -237,7 +229,7 @@
 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
 }
@@ -284,6 +276,7 @@ Hna6
 # (default is 7)
 
 # MprCoverage 7
+MprCoverage	1
 
 ################################
 ### OLSR protocol extensions ###
@@ -309,7 +302,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
@@ -323,6 +316,7 @@ Hna6
 # (default is 1)
 
 # LinkQualityFishEye  1
+LinkQualityFishEye	0
 
 #
 # NatThreshold 
@@ -377,38 +371,32 @@ IpcConnect
 # each plugin should have a README file in it's lib subfolder
 
 # LoadPlugin "olsrd_httpinfo.dll"
-LoadPlugin "olsrd_httpinfo.so.0.1"
+LoadPlugin "./lib/httpinfo/olsrd_httpinfo.so.0.1"
 {
     # port number the httpinfo plugin will be listening, default 1978
-#   PlParam     "port"   "8000"
+    PlParam     "port"   "8000"
     
     # ip address that can access the plugin, use "0.0.0.0"
     # to allow everyone
-    PlParam     "Host"   "127.0.0.1"
+#    PlParam     "Host"   "127.0.0.1"
 #   PlParam     "Host"   "80.23.53.22"
     
     # networks that can access the plugin (ip/netmask)
     # careful with 0.0.0.0/0, makes (ddos) attacks poss.
-#   PlParam     "Net"    "0.0.0.0 0.0.0.0"
-    PlParam     "Net"    "104.0.0.0 255.255.0.0"
-    PlParam     "Net"    "192.168.0.0 255.255.0.0"
+#    PlParam     "Net"    "127.0.0.1 255.0.0.0"
+    PlParam     "Net"    "0.0.0.0 0.0.0.0"
+#    PlParam     "Net"    "104.0.0.0 255.255.0.0"
+#    PlParam     "Net"    "192.168.0.0 255.255.0.0"
 }
 
 # LoadPlugin "olsrd_txtinfo.dll"
-LoadPlugin "olsrd_txtinfo.so.0.1"
+LoadPlugin "./lib/txtinfo/olsrd_txtinfo.so.0.1"
 {
-    # the default port is 2006 but you can change it like this:
-    #PlParam     "port"   "8080"
-
-    # You can set a "accept" single address to allow to connect to
-    # txtinfo. If no address is specified, then localhost (127.0.0.1)
-    # is allowed by default.  txtinfo will only use the first "accept"
-    # parameter specified and will ignore the rest.
-
-    # to allow a specific host:
-    #PlParam      "accept" "172.29.44.23"
-    # if you set it to 0.0.0.0, it will accept all connections
-    #PlParam      "accept" "0.0.0.0"
+    # port number the txtinfo plugin will be listening, default 2006
+#   PlParam     "port"   "81"
+    # ip address that can access the plugin, use "0.0.0.0"
+    # to allow everyone
+    PlParam     "Accept"   "127.0.0.1"
 }
 
 #LoadPlugin "olsrd_secure.so.0.3"
@@ -419,8 +407,8 @@ LoadPlugin "olsrd_txtinfo.so.0.1"
 #   PlParam     "Keyfile"   "/etc/olsr-keyfile.txt"
 #}
 
-#LoadPlugin "olsrd_dyn_gw.so.0.5"
-#{
+LoadPlugin "./lib/dyn_gw/olsrd_dyn_gw.so.0.5"
+{
     # The plugin check interval can be set here in milliseconds.
     # The default is 1000 ms (1 second).
 #    PlParam     "CheckInterval"  "5000"
@@ -437,18 +425,18 @@ LoadPlugin "olsrd_txtinfo.so.0.1"
     # 2nd won't be pinged.
     #
     # The Ping list applies to the group of HNAs specified above or to the 
-		# default internet gateway when no HNA is specified.
-		#
-		# Running the plugin without parameters acts as the 'old' dyn_gw_plain.
+    # default internet gateway when no HNA is specified.
+    #
+    # Running the plugin without parameters acts as the 'old' dyn_gw_plain.
     
     #   The following ping entries for the internet gateway
 #    PlParam "Ping"   "141.1.1.1"
 #    PlParam "Ping"   "194.25.2.129"
     
     #   First group of HNAs with related ping host
-#    PlParam	"HNA"	   "192.168.80.0 255.255.255.0"
-#    PlParam	"HNA"	   "192.168.81.0 255.255.255.0"
-#    PlParam	"Ping"	 "192.168.81.12"
+#    PlParam    "HNA"    "192.168.80.0 255.255.255.0"
+#    PlParam    "HNA"    "192.168.81.0 255.255.255.0"
+#    PlParam    "Ping"   "192.168.81.12"
     
     #   Second HNA group with multiple related ping hosts.
     #   Specifying multiple ping hosts provides redundancy.
@@ -462,12 +450,54 @@ LoadPlugin "olsrd_txtinfo.so.0.1"
 #    PlParam "HNA"    "192.168.200.0 255.255.255.0"
 #    PlParam "HNA"    "192.168.201.0 255.255.255.0"
 #    PlParam "HNA"    "192.168.202.0 255.255.255.0"
-#}
+
+PlParam "HNA"   "0.0.0.0 0.0.0.0"
+PlParam "HNA"   "0.0.0.0 128.0.0.0"
+PlParam "HNA"   "128.0.0.0 128.0.0.0"
+PlParam "HNA"   "0.0.0.0 192.0.0.0"
+PlParam "HNA"   "64.0.0.0 192.0.0.0"
+PlParam "HNA"   "128.0.0.0 192.0.0.0"
+PlParam "HNA"   "192.0.0.0 192.0.0.0"
+}
 
 #LoadPlugin "olsrd_dyn_gw_plain.so.0.4"
 #{
 #}
 
+LoadPlugin "./lib/p2pd/olsrd_p2pd.so.0.1.0"
+{
+  PlParam     "NonOlsrIf"    "lo"
+  PlParam     "P2pdTtl"      "5"
+  PlParam     "UdpDestPort"  "255.255.255.255 1211"
+}
+
+LoadPlugin "./lib/bmf/olsrd_bmf.so.1.7.0"
+{
+  PlParam     "NonOlsrIf"  "lo"
+}
+
+LoadPlugin "./lib/watchdog/olsrd_watchdog.so.0.1"
+{
+  PlParam "file" "/tmp/olsrd.watchdog"
+  PlParam "interval" "5"
+}
+
+LoadPlugin "./lib/sgwdynspeed/olsrd_sgwdynspeed.so.1.0.0"
+{
+  # Specifies the file to watch for (dynamic) values for SmartGatewaySpeed.
+  # If not specified then no watching is performed.
+  # (default is unspecified)
+
+  # PlParam "speedFile" ""
+
+  # Specifies the period in milliseconds on which to read the speedFile
+  # (if it changed) and activate its new setting for SmartGatewaySpeed.
+  # This setting is only relevant if speedFile has been configured.
+  # (default is 10000 milliseconds)
+
+  # PlParam "speedFilePeriod" "10000"
+}
+
 #############################################
 ### OLSRD default interface configuration ###
 #############################################
@@ -486,7 +516,7 @@ InterfaceDefaults {
 # multiple configuration blocks can be specified
 
 # WARNING, don't forget to insert your interface names here !
-Interface "<OLSRd-Interface1>" "<OLSRd-Interface2>"
+Interface "em1"
 {
     # Interface Mode is used to prevent unnecessary
     # packet forwarding on switched ethernet interfaces
@@ -508,7 +538,7 @@ Interface "<OLSRd-Interface1>" "<OLSRd-Interface2>"
     # IPv6 multicast address
     # (default is FF02::6D, the manet-router linklocal multicast)
 
-    # IPv6Multicast	FF02::6D
+    # IPv6Multicast FF02::6D
 
     # IPv4 src address for outgoing OLSR packages
     # (default is 0.0.0.0, which triggers usage of the interface IP)
@@ -534,6 +564,14 @@ Interface "<OLSRd-Interface1>" "<OLSRd-Interface2>"
     # MidValidityTime   300.0
     # HnaInterval         5.0
     # HnaValidityTime   300.0
+HelloInterval     2.00
+HelloValidityTime 20.00
+TcInterval        5.00
+TcValidityTime    30.00
+MidInterval       5.00
+MidValidityTime   50.00
+HnaInterval       5.00
+HnaValidityTime   15.00
     
     # When multiple links exist between hosts
     # the weight of interface is used to determine
diff --git a/lib/sgwdynspeed/resources/olsrd.sgw.speed.conf b/lib/sgwdynspeed/resources/olsrd.sgw.speed.conf
new file mode 100644
index 0000000..ae795d8
--- /dev/null
+++ b/lib/sgwdynspeed/resources/olsrd.sgw.speed.conf
@@ -0,0 +1,14 @@
+#
+# OLSrd Smart Gateway uplink speed configuration file
+#
+
+
+#
+# Upstream speed in kilobit/s
+# Default: 128
+#upstream=128
+
+#
+# Downstream speed in kilobit/s
+# Default: 1024
+#downstream=1024
diff --git a/lib/sgwdynspeed/src/configuration.c b/lib/sgwdynspeed/src/configuration.c
new file mode 100644
index 0000000..32a0fc6
--- /dev/null
+++ b/lib/sgwdynspeed/src/configuration.c
@@ -0,0 +1,167 @@
+#include "configuration.h"
+
+/* Plugin includes */
+#include "sgwDynSpeed.h"
+
+/* OLSR includes */
+
+/* System includes */
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <assert.h>
+
+/*
+ * Utility functions
+ */
+
+/**
+ Read an unsigned long long number from a value string
+
+ @param valueName
+ the name of the value
+ @param value
+ the string to convert to a number
+ @param valueNumber
+ a pointer to the location where to store the number upon successful conversion
+
+ @return
+ - true on success
+ - false otherwise
+ */
+static bool readULL(const char * valueName, const char * value, unsigned long long * valueNumber) {
+	char * endPtr = NULL;
+	unsigned long long valueNew;
+
+	errno = 0;
+	valueNew = strtoull(value, &endPtr, 10);
+
+	if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
+		/* invalid conversion */
+		sgwDynSpeedError(true, "Configured %s (%s) could not be converted to a number", valueName, value);
+		return false;
+	}
+
+	*valueNumber = valueNew;
+
+	return true;
+}
+
+/*
+ * speedFile
+ */
+
+/** The speedFile buffer */
+static char speedFile[PATH_MAX];
+
+/** True when the speedFile is set */
+static bool speedFileSet = false;
+
+/**
+ @return
+ The speed file filename. returns NULL if not set
+ */
+char * getSpeedFile(void) {
+	if (!speedFileSet) {
+		return NULL;
+	}
+
+	return &speedFile[0];
+}
+
+/**
+ Set the speed file filename.
+
+ @param value
+ The value of the speed file filename to set
+ @param data
+ Unused
+ @param addon
+ Unused
+
+ @return
+ - true when an error is detected
+ - false otherwise
+ */
+int setSpeedFile(const char *value, void *data __attribute__ ((unused)),
+		set_plugin_parameter_addon addon __attribute__ ((unused))) {
+	size_t valueLength;
+
+	if (!value) {
+		speedFileSet = false;
+		return false;
+	}
+
+	valueLength = strlen(value);
+	if (!valueLength) {
+		speedFileSet = false;
+		return false;
+	}
+
+	if (valueLength > (PATH_MAX - 1)) {
+		sgwDynSpeedError(false, "Configured %s is too long, maximum length is"
+				" %u, current length is %lu", SGWDYNSPEED_SPEEDFILE_NAME, PATH_MAX, (unsigned long) valueLength);
+		return true;
+	}
+
+	strcpy(&speedFile[0], value);
+	speedFileSet = true;
+
+	return false;
+}
+
+/*
+ * speedFilePeriod
+ */
+
+/** The speedFilePeriod value (milliseconds) */
+unsigned long long speedFilePeriod = SGWDYNSPEED_SPEEDFILEPERIOD_DEFAULT;
+
+/**
+ @return
+ The speedFilePeriod (in milliseconds)
+ */
+unsigned long long getSpeedFilePeriod(void) {
+	return speedFilePeriod;
+}
+
+/**
+ Set the speedFilePeriod
+
+ @param value
+ The speedFilePeriod (a number in string representation)
+ @param data
+ Unused
+ @param addon
+ Unused
+
+ @return
+ - true when an error is detected
+ - false otherwise
+ */
+int setSpeedFilePeriod(const char *value, void *data __attribute__ ((unused)),
+		set_plugin_parameter_addon addon __attribute__ ((unused))) {
+	static const char * valueName = SGWDYNSPEED_SPEEDFILEPERIOD_NAME;
+	unsigned long long speedFilePeriodNew;
+
+	assert(value != NULL);
+
+	if (!readULL(valueName, value, &speedFilePeriodNew)) {
+		return true;
+	}
+
+	if ((speedFilePeriodNew < SGWDYNSPEED_SPEEDFILEPERIOD_MIN)
+			|| (speedFilePeriodNew > SGWDYNSPEED_SPEEDFILEPERIOD_MAX)) {
+		sgwDynSpeedError(false, "Configured %s (%llu) is outside of"
+				" valid range %llu-%llu", valueName, speedFilePeriodNew, SGWDYNSPEED_SPEEDFILEPERIOD_MIN,
+				SGWDYNSPEED_SPEEDFILEPERIOD_MAX);
+		return true;
+	}
+
+	speedFilePeriod = speedFilePeriodNew;
+
+	return false;
+}
diff --git a/lib/sgwdynspeed/src/configuration.h b/lib/sgwdynspeed/src/configuration.h
new file mode 100644
index 0000000..045da6e
--- /dev/null
+++ b/lib/sgwdynspeed/src/configuration.h
@@ -0,0 +1,40 @@
+#ifndef _SGWDYNSPEED_CONFIGURATION_H_
+#define _SGWDYNSPEED_CONFIGURATION_H_
+
+/* Plugin includes */
+
+/* OLSR includes */
+#include "olsrd_plugin.h"
+
+/* System includes */
+
+/*
+ * speedFile
+ */
+
+/** The name of the speedFile plugin parameter */
+#define SGWDYNSPEED_SPEEDFILE_NAME				"speedFile"
+
+char * getSpeedFile(void);
+int setSpeedFile(const char *value, void *data, set_plugin_parameter_addon addon);
+
+/*
+ * speedFilePeriod
+ */
+
+/** The name of the speedFilePeriod plugin parameter */
+#define SGWDYNSPEED_SPEEDFILEPERIOD_NAME		"speedFilePeriod"
+
+/** The default value of the speedFilePeriod plugin parameter */
+#define SGWDYNSPEED_SPEEDFILEPERIOD_DEFAULT		((unsigned long long)10000)
+
+/** The minimal value of the speedFilePeriod plugin parameter */
+#define SGWDYNSPEED_SPEEDFILEPERIOD_MIN			((unsigned long long)1000)
+
+/** The maximal value of the speedFilePeriod plugin parameter */
+#define SGWDYNSPEED_SPEEDFILEPERIOD_MAX			((unsigned long long)320000000)
+
+unsigned long long getSpeedFilePeriod(void);
+int setSpeedFilePeriod(const char *value, void *data, set_plugin_parameter_addon addon);
+
+#endif /* _SGWDYNSPEED_CONFIGURATION_H_ */
diff --git a/lib/pud/src/pudOlsrdPlugin.c b/lib/sgwdynspeed/src/olsrdPlugin.c
similarity index 72%
copy from lib/pud/src/pudOlsrdPlugin.c
copy to lib/sgwdynspeed/src/olsrdPlugin.c
index d2c4b4a..3f80b59 100644
--- a/lib/pud/src/pudOlsrdPlugin.c
+++ b/lib/sgwdynspeed/src/olsrdPlugin.c
@@ -1,12 +1,13 @@
-#include "pudOlsrdPlugin.h"
+#include "olsrdPlugin.h"
 
 /* Plugin includes */
-#include "pud.h"
+#include "sgwDynSpeed.h"
 
 /* OLSRD includes */
 #include "olsr.h"
 
 /* System includes */
+#include <stdbool.h>
 
 /*
  * OLSR Entrypoints
@@ -20,13 +21,13 @@
  - 1 on success
  */
 int olsrd_plugin_init(void) {
-	bool retval = initPud();
+	bool retval = initSgwDynSpeed();
 	if (retval) {
-		olsr_printf(0, "%s\n", PUD_PLUGIN_NAME_LONG
+		olsr_printf(0, "%s\n", SGWDYNSPEED_PLUGIN_NAME_LONG
 #ifdef GIT_SHA
 				" (" GIT_SHA ")"
 #endif
-		);
+				);
 	}
 	return (retval ? 1 : 0);
 }
@@ -38,7 +39,7 @@ int olsrd_plugin_init(void) {
  the supported interface version
  */
 int olsrd_plugin_interface_version(void) {
-	return PUD_PLUGIN_INTERFACE_VERSION;
+	return SGWDYNSPEED_PLUGIN_INTERFACE_VERSION;
 }
 
 /**
@@ -51,8 +52,7 @@ int olsrd_plugin_interface_version(void) {
  a pointer to a variable in which the function stores the number of rows of the
  plugin parameter configuration
  */
-void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params,
-		int *size) {
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size) {
 	*params = &plugin_parameters[0];
 	*size = ARRAYSIZE(plugin_parameters);
 }
@@ -64,23 +64,22 @@ void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params,
 /**
  Shared library entrypoint declaration for initialisation
  */
-static void __attribute__ ((constructor)) pud_init(void);
+static void __attribute__ ((constructor)) sgwDynSpeed_init(void);
 
 /**
  Shared library entrypoint declaration for destruction
  */
-static void __attribute__ ((destructor)) pud_fini(void);
-
+static void __attribute__ ((destructor)) sgwDynSpeed_fini(void);
 
 /**
  Shared library entrypoint for initialisation
  */
-static void pud_init(void) {
+static void sgwDynSpeed_init(void) {
 }
 
 /**
  Shared library entrypoint for destruction
  */
-static void pud_fini(void) {
-	closePud();
+static void sgwDynSpeed_fini(void) {
+	stopSgwDynSpeed();
 }
diff --git a/lib/sgwdynspeed/src/olsrdPlugin.h b/lib/sgwdynspeed/src/olsrdPlugin.h
new file mode 100644
index 0000000..7e6a84e
--- /dev/null
+++ b/lib/sgwdynspeed/src/olsrdPlugin.h
@@ -0,0 +1,26 @@
+#ifndef _SGWDYNSPEED_OLSRD_PLUGIN_H_
+#define _SGWDYNSPEED_OLSRD_PLUGIN_H_
+
+/* Plugin includes */
+#include "configuration.h"
+
+/* OLSRD includes */
+#include "olsrd_plugin.h"
+
+/* System includes */
+#include <stddef.h>
+
+/** The interface version supported by the plugin */
+#define SGWDYNSPEED_PLUGIN_INTERFACE_VERSION	5
+
+/**
+ The plugin parameter configuration, containing the parameter names, pointers
+ to their setters, and an optional data pointer that is given to the setter
+ when it is called.
+ */
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+	{	.name = SGWDYNSPEED_SPEEDFILE_NAME, .set_plugin_parameter = &setSpeedFile, .data = NULL},
+	{	.name = SGWDYNSPEED_SPEEDFILEPERIOD_NAME, .set_plugin_parameter = &setSpeedFilePeriod, .data = NULL}
+};
+
+#endif /* _SGWDYNSPEED_OLSRD_PLUGIN_H_ */
diff --git a/lib/sgwdynspeed/src/sgwDynSpeed.c b/lib/sgwdynspeed/src/sgwDynSpeed.c
new file mode 100644
index 0000000..28f6a2a
--- /dev/null
+++ b/lib/sgwdynspeed/src/sgwDynSpeed.c
@@ -0,0 +1,122 @@
+#include "sgwDynSpeed.h"
+
+/* Plugin includes */
+#include "speedFile.h"
+#include "configuration.h"
+
+/* OLSRD includes */
+#include "olsr.h"
+#include "olsr_cookie.h"
+#include "scheduler.h"
+
+/* System includes */
+
+/**
+ Report a plugin error.
+
+ @param useErrno
+ when true then errno is used in the error message; the error reason is also
+ reported.
+ @param format
+ a pointer to the format string
+ @param ...
+ arguments to the format string
+ */
+void sgwDynSpeedError(bool useErrno, const char *format, ...) {
+	char strDesc[256];
+	char *stringErr = NULL;
+
+	if (useErrno) {
+		stringErr = strerror(errno);
+	}
+
+	if ((format == NULL) || (*format == '\0')) {
+		if (useErrno) {
+			olsr_printf(0, "%s: %s\n", SGWDYNSPEED_PLUGIN_ABBR, stringErr);
+		} else {
+			olsr_printf(0, "%s: Unknown error\n", SGWDYNSPEED_PLUGIN_ABBR);
+		}
+	} else {
+		va_list arglist;
+
+		va_start(arglist, format);
+		vsnprintf(strDesc, sizeof(strDesc), format, arglist);
+		va_end(arglist);
+
+		strDesc[sizeof(strDesc) - 1] = '\0'; /* Ensures null termination */
+
+		if (useErrno) {
+			olsr_printf(0, "%s: %s: %s\n", SGWDYNSPEED_PLUGIN_ABBR, strDesc, stringErr);
+		} else {
+			olsr_printf(0, "%s: %s\n", SGWDYNSPEED_PLUGIN_ABBR, strDesc);
+		}
+	}
+}
+
+/**
+ * Timer callback that reads the smart gateway speed file
+ */
+static void smartgw_read_speed_file(void *context __attribute__ ((unused))) {
+	readSpeedFile(getSpeedFile());
+	return;
+}
+
+/** The timer cookie, used to trace back the originator in debug */
+static struct olsr_cookie_info *smartgw_speed_file_timer_cookie = NULL;
+
+/** The timer */
+static struct timer_entry * smartgw_speed_file_timer = NULL;
+
+/**
+ Initialise the plugin: check the configuration, initialise the NMEA parser,
+ create network interface sockets, hookup the plugin to OLSR and setup data
+ that can be setup in advance.
+
+ @return
+ - false upon failure
+ - true otherwise
+ */bool initSgwDynSpeed(void) {
+	char * speedFile;
+
+	if (!startSpeedFile()) {
+		return false;
+	}
+
+	speedFile = getSpeedFile();
+	if (speedFile) {
+		readSpeedFile(speedFile);
+
+		if (smartgw_speed_file_timer_cookie == NULL) {
+			smartgw_speed_file_timer_cookie = olsr_alloc_cookie("smartgw speed file", OLSR_COOKIE_TYPE_TIMER);
+			if (smartgw_speed_file_timer_cookie == NULL) {
+				sgwDynSpeedError(false, "Could not allocate smart gateway speed file cookie");
+				return false;
+			}
+		}
+		if (smartgw_speed_file_timer == NULL) {
+			smartgw_speed_file_timer = olsr_start_timer(getSpeedFilePeriod(), 0, OLSR_TIMER_PERIODIC,
+					&smartgw_read_speed_file, NULL, smartgw_speed_file_timer_cookie);
+			if (smartgw_speed_file_timer == NULL) {
+				sgwDynSpeedError(false, "Could not start smart gateway speed file timer");
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+ /**
+  * stop the plugin, free resources
+  */
+void stopSgwDynSpeed(void) {
+	if (smartgw_speed_file_timer != NULL) {
+		olsr_stop_timer(smartgw_speed_file_timer);
+		smartgw_speed_file_timer = NULL;
+	}
+	if (smartgw_speed_file_timer_cookie != NULL) {
+		olsr_free_cookie(smartgw_speed_file_timer_cookie);
+		smartgw_speed_file_timer_cookie = NULL;
+	}
+	stopSpeedFile();
+}
diff --git a/lib/sgwdynspeed/src/sgwDynSpeed.h b/lib/sgwdynspeed/src/sgwDynSpeed.h
new file mode 100644
index 0000000..bee8a4e
--- /dev/null
+++ b/lib/sgwdynspeed/src/sgwDynSpeed.h
@@ -0,0 +1,30 @@
+#ifndef _SGWDYNSPEED_SGWDYNSPEED_H
+#define _SGWDYNSPEED_SGWDYNSPEED_H
+
+/* Plugin includes */
+
+/* OLSR includes */
+
+/* System includes */
+#include <stdbool.h>
+
+/*
+ * Global
+ */
+
+/** The long plugin name */
+#define SGWDYNSPEED_PLUGIN_NAME_LONG			"OLSRD Smart Gateway Dynamic Speed plugin"
+
+/** The short plugin name / abbreviation */
+#define SGWDYNSPEED_PLUGIN_ABBR					"SGWDYNSPEED"
+
+/*
+ *  Interface
+ */
+
+bool initSgwDynSpeed(void);
+void stopSgwDynSpeed(void);
+
+void sgwDynSpeedError(bool useErrno, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
+
+#endif /* _SGWDYNSPEED_SGWDYNSPEED_H */
diff --git a/lib/sgwdynspeed/src/speedFile.c b/lib/sgwdynspeed/src/speedFile.c
new file mode 100644
index 0000000..1ebc0fa
--- /dev/null
+++ b/lib/sgwdynspeed/src/speedFile.c
@@ -0,0 +1,238 @@
+#include "speedFile.h"
+
+/* Plugin includes */
+#include "sgwDynSpeed.h"
+
+/* OLSRD includes */
+#include "olsr_cfg.h"
+
+/* System includes */
+#include <stddef.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#define SPEED_UPLINK_NAME   "upstream"
+#define SPEED_DOWNLINK_NAME "downstream"
+
+/** the maximal length of a line that is read from the file */
+#define LINE_LENGTH 256
+
+/** regular expression describing a comment */
+static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
+
+/** regular expression describing a key/value pair */
+static const char * regexNameValueString =
+		"^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
+
+/** the number of matches in regexNameValueString */
+static const size_t regexNameValuematchCount = 3;
+
+/** the compiled regular expression describing a comment */
+static regex_t regexComment;
+
+/** the compiled regular expression describing a key/value pair */
+static regex_t regexNameValue;
+
+/** true when the plugin has been started */
+static bool started = false;
+
+/** type to hold the cached stat result */
+typedef struct _CachedStat {
+	struct timespec st_mtim; /* Time of last modification. */
+} CachedStat;
+
+/** the cached stat result */
+static CachedStat cachedStat;
+
+/**
+ Read an unsigned long number from a value string
+
+ @param valueName
+ the name of the value
+ @param value
+ the string to convert to a number
+ @param valueNumber
+ a pointer to the location where to store the number upon successful conversion
+
+ @return
+ - true on success
+ - false otherwise
+ */
+static bool readUL(const char * valueName, const char * value, unsigned long * valueNumber) {
+	char * endPtr = NULL;
+	unsigned long valueNew;
+
+	errno = 0;
+	valueNew = strtoul(value, &endPtr, 10);
+
+	if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
+		/* invalid conversion */
+		sgwDynSpeedError(true, "Configured %s (%s) could not be converted to a number", valueName, value);
+		return false;
+	}
+
+	*valueNumber = valueNew;
+
+	return true;
+}
+
+/**
+ * Initialises the speedFile reader.
+ * @return true upon success, false otherwise
+ */
+bool startSpeedFile(void) {
+	int result;
+
+	if (started) {
+		return true;
+	}
+
+	result = regcomp(&regexComment, regexCommentString, REG_EXTENDED | REG_ICASE);
+	if (result) {
+		char msgbuf[256];
+		regerror(result, &regexComment, msgbuf, sizeof(msgbuf));
+		sgwDynSpeedError(false, "Could not compile regex \"%s\": %s", regexCommentString, msgbuf);
+		return false;
+	}
+
+	result = regcomp(&regexNameValue, regexNameValueString, REG_EXTENDED | REG_ICASE);
+	if (result) {
+		char msgbuf[256];
+		regerror(result, &regexNameValue, msgbuf, sizeof(msgbuf));
+		sgwDynSpeedError(false, "Could not compile regex \"%s\": %s", regexNameValueString, msgbuf);
+		regfree(&regexComment);
+		return false;
+	}
+
+	cachedStat.st_mtim.tv_sec = -1;
+	cachedStat.st_mtim.tv_nsec = -1;
+
+	started = true;
+	return true;
+}
+
+/**
+ * Cleans up the speedFile reader.
+ */
+void stopSpeedFile(void) {
+	if (started) {
+		regfree(&regexNameValue);
+		regfree(&regexComment);
+		started = false;
+	}
+}
+
+/**
+ * Performs a regex match
+ * @param regex the compiled regex to match against
+ * @param line the line to match
+ * @param nmatch the number of matches to produce
+ * @param pmatch the array with match information
+ * @return true upon success, false otherwise
+ */
+static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
+	int result = regexec(regex, line, nmatch, pmatch, 0);
+	if (!result) {
+		return true;
+	}
+
+	if (result == REG_NOMATCH) {
+		return false;
+	}
+
+	{
+		char msgbuf[256];
+		regerror(result, regex, msgbuf, sizeof(msgbuf));
+		sgwDynSpeedError(false, "Regex match failed: %s", msgbuf);
+	}
+
+	return false;
+}
+
+/** the buffer in which to store a line read from the file */
+static char line[LINE_LENGTH];
+
+/**
+ * Read the speed file
+ * @param fileName the filename
+ */
+void readSpeedFile(char * fileName) {
+	struct stat statBuf;
+	FILE * fd = NULL;
+	unsigned int lineNumber = 0;
+	char * name = NULL;
+	char * value = NULL;
+	unsigned long uplink = DEF_UPLINK_SPEED;
+	unsigned long downlink = DEF_DOWNLINK_SPEED;
+	bool uplinkSet = false;
+	bool downlinkSet = false;
+
+	if (stat(fileName, &statBuf)) {
+		/* could not access the file */
+		goto out;
+	}
+
+	if (!memcmp(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim))) {
+		/* file did not change since last read */
+		goto out;
+	}
+
+	fd = fopen(fileName, "r");
+	if (!fd) {
+		goto out;
+	}
+
+	memcpy(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim));
+
+	while (fgets(line, LINE_LENGTH, fd)) {
+		regmatch_t pmatch[regexNameValuematchCount];
+
+		lineNumber++;
+
+		if (regexMatch(&regexComment, line, 0, NULL)) {
+			continue;
+		}
+
+		if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
+			sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses invalid syntax: %s", fileName, lineNumber,
+					line);
+			goto out;
+		}
+
+		/* determine name/value */
+		name = &line[pmatch[1].rm_so];
+		line[pmatch[1].rm_eo] = '\0';
+		value = &line[pmatch[2].rm_so];
+		line[pmatch[2].rm_eo] = '\0';
+
+		if (!strncasecmp(SPEED_UPLINK_NAME, name, sizeof(line))) {
+			if (!readUL(SPEED_UPLINK_NAME, value, &uplink)) {
+				goto out;
+			}
+			uplinkSet = true;
+		} else if (!strncasecmp(SPEED_DOWNLINK_NAME, name, sizeof(line))) {
+			if (!readUL(SPEED_DOWNLINK_NAME, value, &downlink)) {
+				goto out;
+			}
+			downlinkSet = true;
+		} else {
+			sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
+					" valid options are [%s|%s]", fileName, lineNumber, name, SPEED_UPLINK_NAME, SPEED_DOWNLINK_NAME);
+			goto out;
+		}
+	}
+
+	fclose(fd);
+
+	if (uplinkSet) {
+		olsr_cnf->smart_gw_uplink = uplink;
+	}
+	if (downlinkSet) {
+		olsr_cnf->smart_gw_downlink = downlink;
+	}
+
+	out: return;
+}
diff --git a/lib/sgwdynspeed/src/speedFile.h b/lib/sgwdynspeed/src/speedFile.h
new file mode 100644
index 0000000..66fdda9
--- /dev/null
+++ b/lib/sgwdynspeed/src/speedFile.h
@@ -0,0 +1,15 @@
+#ifndef SPEEDFILE_H
+#define SPEEDFILE_H
+
+/* Plugin includes */
+
+/* OLSRD includes */
+
+/* System includes */
+#include <stdbool.h>
+
+bool startSpeedFile(void);
+void stopSpeedFile(void);
+void readSpeedFile(char * fileName);
+
+#endif /* SPEEDFILE_H */
diff --git a/lib/arprefresh/version-script.txt b/lib/sgwdynspeed/version-script.txt
similarity index 100%
copy from lib/arprefresh/version-script.txt
copy to lib/sgwdynspeed/version-script.txt
-- 
1.7.7.6





More information about the Olsr-dev mailing list