[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(®exComment, regexCommentString, REG_EXTENDED)) {
+ olsr_printf(0, "Could not compile regex \"%s\"\n", regexCommentString);
+ return false;
+ }
+
+ if (regcomp(®exNameValue, 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(®exNameValue);
+ regfree(®exComment);
+ 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(®exComment, line, 0, NULL)) {
+ continue;
+ }
+
+ if (!regexMatch(®exNameValue, 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