[Olsr-dev] [PATCH RFC v1 2/4] smart gateway: hook up SmartGatewaySpeedFile{, Period} parameters

Ferry Huberts (spam-protected)
Thu May 10 17:56:42 CEST 2012


From: Ferry Huberts <(spam-protected)>

Signed-off-by: Ferry Huberts <(spam-protected)>
---
 make/Makefile.win32    |    2 +-
 src/gateway.c          |   52 ++++++++++++-
 src/gatewaySpeedFile.c |  201 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/gatewaySpeedFile.h |   13 +++
 4 files changed, 266 insertions(+), 2 deletions(-)
 create mode 100644 src/gatewaySpeedFile.c
 create mode 100644 src/gatewaySpeedFile.h

diff --git a/make/Makefile.win32 b/make/Makefile.win32
index cf4a4a2..3693ef4 100644
--- a/make/Makefile.win32
+++ b/make/Makefile.win32
@@ -9,7 +9,7 @@ SRCS +=		$(wildcard src/win32/*.c)
 HDRS +=		$(wildcard src/win32/*.h)
 
 CPPFLAGS +=	-DWIN32 -D_WIN32_WINNT=0x0600
-LIBS +=		-mno-cygwin -lws2_32 -liphlpapi
+LIBS +=		-mno-cygwin -lws2_32 -liphlpapi -lregex
 CPPFLAGS += 	-I$(TOPDIR)/src/win32
 CFLAGS +=	-mno-cygwin
 
diff --git a/src/gateway.c b/src/gateway.c
index 048a7cb..84d88b3 100644
--- a/src/gateway.c
+++ b/src/gateway.c
@@ -19,6 +19,7 @@
 #include "log.h"
 #include "gateway_default_handler.h"
 #include "gateway.h"
+#include "gatewaySpeedFile.h"
 
 #include <assert.h>
 #include <net/if.h>
@@ -87,6 +88,14 @@ static void smartgw_tunnel_monitor (int if_index __attribute__ ((unused)),
 }
 
 /**
+ * Timer callback that reads the smart gateway speed file
+ */
+static void smartgw_read_speed_file(void *context __attribute__ ((unused))) {
+	readGatewaySpeedFile(olsr_cnf->smart_gw_speed_file);
+	return;
+}
+
+/**
  * Initialize gateway system
  */
 int
@@ -107,6 +116,10 @@ olsr_init_gateways(void) {
     return 1;
   }
 
+  if (!startGatewaySpeedFile()) {
+	  return 1;
+  }
+
   olsr_add_ifchange_handler(smartgw_tunnel_monitor);
 
   /*
@@ -140,10 +153,26 @@ void refresh_smartgw_netmask(void) {
   }
 }
 
+/** 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;
+
 /**
  * Cleanup gateway tunnel system
  */
 void olsr_cleanup_gateways(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;
+  }
+  stopGatewaySpeedFile();
+
   if (current_ipv4_gw) {
     olsr_os_del_ipip_tunnel(v4gw_tunnel);
   }
@@ -161,7 +190,28 @@ void olsr_cleanup_gateways(void) {
  */
 void
 olsr_trigger_inetgw_startup(void) {
-  gw_handler->handle_startup();
+	if (olsr_cnf->smart_gw_speed_file) {
+		smartgw_read_speed_file(NULL);
+
+		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) {
+				olsr_syslog(OLSR_LOG_ERR,
+						"Could not allocate smart gateway speed file cookie, will not read the file.\n");
+				return;
+			}
+		}
+		if (smartgw_speed_file_timer == NULL) {
+			smartgw_speed_file_timer = olsr_start_timer(olsr_cnf->smart_gw_speed_file_period, 0, OLSR_TIMER_PERIODIC,
+					&smartgw_read_speed_file, NULL, smartgw_speed_file_timer_cookie);
+			if (smartgw_speed_file_timer == NULL) {
+				olsr_syslog(OLSR_LOG_ERR, "Could not start smart gateway speed file timer, will not read the file.\n");
+				return;
+			}
+		}
+	}
+
+	gw_handler->handle_startup();
 }
 
 /**
diff --git a/src/gatewaySpeedFile.c b/src/gatewaySpeedFile.c
new file mode 100644
index 0000000..72cfbf9
--- /dev/null
+++ b/src/gatewaySpeedFile.c
@@ -0,0 +1,201 @@
+#include "gatewaySpeedFile.h"
+
+#include "log.h"
+#include <regex.h>
+#include <sys/stat.h>
+
+#define LINE_LENGTH 256
+
+static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
+static const char * regexNameValueString =
+		"^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
+static const size_t regexNameValuematchCount = 3;
+
+static regex_t regexComment;
+static regex_t regexNameValue;
+static bool started = false;
+
+typedef struct _CachedStat {
+#ifdef linux
+	struct timespec st_mtim; /* Time of last modification. */
+#else
+	time_t st_mtime; /* Time of last modification. */
+#endif
+} CachedStat;
+
+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 */
+		olsr_syslog(OLSR_LOG_ERR, "Configured %s (%s) could not be converted to a number: %s\n", valueName, value,
+				strerror(errno));
+		return false;
+	}
+
+	*valueNumber = valueNew;
+
+	return true;
+}
+
+bool startGatewaySpeedFile(void) {
+	if (started) {
+		return true;
+	}
+
+	if (regcomp(&regexComment, regexCommentString, REG_EXTENDED)) {
+		olsr_printf(0, "Could not compile regex \"%s\"\n", regexCommentString);
+		return false;
+	}
+
+	if (regcomp(&regexNameValue, regexNameValueString, REG_EXTENDED)) {
+		olsr_printf(0, "Could not compile regex \"%s\"\n", regexNameValueString);
+		return false;
+	}
+
+#ifdef linux
+	cachedStat.st_mtim.tv_sec = -1;
+	cachedStat.st_mtim.tv_nsec = -1;
+#else
+	cachedStat.st_mtime = -1;
+#endif
+
+	started = true;
+	return true;
+}
+
+void stopGatewaySpeedFile(void) {
+	if (started) {
+		regfree(&regexNameValue);
+		regfree(&regexComment);
+		started = false;
+	}
+}
+
+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));
+		olsr_syslog(OLSR_LOG_ERR, "Regex match failed: %s\n", msgbuf);
+	}
+
+	return false;
+}
+
+static char line[LINE_LENGTH];
+
+void readGatewaySpeedFile(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;
+	}
+
+#ifdef linux
+	if (!memcmp(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim))) {
+#else
+	if (!memcmp(&cachedStat.st_mtime, &statBuf.st_mtime, sizeof(cachedStat.st_mtime))) {
+#endif
+		/* file did not change since last read */
+		goto out;
+	}
+
+	fd = fopen(fileName, "r");
+	if (!fd) {
+		goto out;
+	}
+
+#ifdef linux
+	memcpy(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim));
+#else
+	memcpy(&cachedStat.st_mtime, &statBuf.st_mtime, sizeof(cachedStat.st_mtime));
+#endif
+
+	while (fgets(line, LINE_LENGTH, fd)) {
+		regmatch_t pmatch[regexNameValuematchCount];
+
+		lineNumber++;
+
+		if (regexMatch(&regexComment, line, 0, NULL)) {
+			continue;
+		}
+
+		if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
+			olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses invalid syntax: %s\n", fileName, lineNumber,
+					line);
+			goto out;
+		}
+
+		/* copy 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(GATEWAY_SPEED_UPLINK, name, sizeof(line))) {
+			if (!readUL(GATEWAY_SPEED_UPLINK, value, &uplink)) {
+				goto out;
+			}
+			uplinkSet = true;
+		} else if (!strncasecmp(GATEWAY_SPEED_DOWNLINK, name, sizeof(line))) {
+			if (!readUL(GATEWAY_SPEED_DOWNLINK, value, &downlink)) {
+				goto out;
+			}
+			downlinkSet = true;
+		} else {
+			olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
+					" valid options are [%s|%s]\n", fileName, lineNumber, name, GATEWAY_SPEED_UPLINK,
+					GATEWAY_SPEED_DOWNLINK);
+			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/src/gatewaySpeedFile.h b/src/gatewaySpeedFile.h
new file mode 100644
index 0000000..e50f607
--- /dev/null
+++ b/src/gatewaySpeedFile.h
@@ -0,0 +1,13 @@
+#ifndef GATEWAYSPEEDFILE_H
+#define GATEWAYSPEEDFILE_H
+
+#include "olsr.h"
+
+#define GATEWAY_SPEED_UPLINK   "upstream"
+#define GATEWAY_SPEED_DOWNLINK "downstream"
+
+bool startGatewaySpeedFile(void);
+void stopGatewaySpeedFile(void);
+void readGatewaySpeedFile(char * fileName);
+
+#endif /* GATEWAYSPEEDFILE_H */
-- 
1.7.7.6





More information about the Olsr-dev mailing list