From c13be7d3b6289ee0ee693456541d656351adc3ec Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 30 Aug 2012 15:16:12 +0200
Subject: [PATCH] package/olsr-time: a simplified olsr_time test

This is a reduced test case for testing olsr_time
functionality.

The olsr_time function in scheduler-bad.c produces
the same binary code as the original function in
the olsrd package.

I have bricked all of my BCM4704/10 based boards long
time ago so the package is not tested on those. Even it
is possible that the test case does not shows the broken
behaviour at all.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 package/olsr-time/Makefile             |   47 ++++++++++++++++++++++
 package/olsr-time/src/Makefile         |   14 +++++++
 package/olsr-time/src/main.c           |   67 ++++++++++++++++++++++++++++++++
 package/olsr-time/src/olsr.h           |   43 ++++++++++++++++++++
 package/olsr-time/src/scheduler-bad.c  |   57 +++++++++++++++++++++++++++
 package/olsr-time/src/scheduler-good.c |   59 ++++++++++++++++++++++++++++
 6 files changed, 287 insertions(+)
 create mode 100644 package/olsr-time/Makefile
 create mode 100644 package/olsr-time/src/Makefile
 create mode 100644 package/olsr-time/src/main.c
 create mode 100644 package/olsr-time/src/olsr.h
 create mode 100644 package/olsr-time/src/scheduler-bad.c
 create mode 100644 package/olsr-time/src/scheduler-good.c

diff --git a/package/olsr-time/Makefile b/package/olsr-time/Makefile
new file mode 100644
index 0000000..b09354e
--- /dev/null
+++ b/package/olsr-time/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=olsr-time
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/olsr-time
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=OLSR time test
+endef
+
+define Package/olsr-time/description
+ This package contains an utility to test olsr_time functionality.
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	$(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall -fpic --save-temps -fverbose-asm" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/olsr-time/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/olsr-time $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,olsr-time))
diff --git a/package/olsr-time/src/Makefile b/package/olsr-time/src/Makefile
new file mode 100644
index 0000000..4c71949
--- /dev/null
+++ b/package/olsr-time/src/Makefile
@@ -0,0 +1,14 @@
+CC := gcc
+CFLAGS := -Wall
+OBJS := scheduler-bad.o scheduler-good.o main.o
+
+all: olsr-time
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+olsr-time: $(OBJS)
+	$(CC) -o $@ $(OBJS)
+
+clean:
+	rm -f olsr-time *.o
diff --git a/package/olsr-time/src/main.c b/package/olsr-time/src/main.c
new file mode 100644
index 0000000..72a6692
--- /dev/null
+++ b/package/olsr-time/src/main.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "olsr.h"
+
+static struct timeval const_tv;
+static int use_const_tv;
+
+#undef gettimeofday
+
+void
+olsr_exit(const char *msg, int val)
+{
+	/* dummy */
+}
+
+int olsr_gettimeofday(struct timeval *__restrict __tv, __timezone_ptr_t __tz)
+{
+	int ret;
+
+	ret = 0;
+	if (!use_const_tv) {
+		ret = gettimeofday(&const_tv, __tz);
+		use_const_tv = 1;
+	}
+
+	__tv->tv_sec = const_tv.tv_sec;
+	__tv->tv_usec = const_tv.tv_usec;
+	return ret;
+}
+
+void
+olsr_init_all_timers(void)
+{
+	olsr_init_timers();
+	olsr_init_timers2();
+}
+
+int main(int argc, char *argv[])
+{
+	int i;
+
+	olsr_init_all_timers();
+	use_const_tv = 0;
+
+	for (i = 0; i < 200; i++) {
+		int times2, times;
+
+		times = olsr_times();
+		times2 = olsr_times2();
+
+		printf("good:%10d  bad:%10d  sec:%10u  usec:%06u\n",
+			times2, times,
+			(unsigned)const_tv.tv_sec,
+			(unsigned)const_tv.tv_usec);
+
+		use_const_tv = 0;
+		usleep(476865);
+	};
+
+	return 0;
+}
diff --git a/package/olsr-time/src/olsr.h b/package/olsr-time/src/olsr.h
new file mode 100644
index 0000000..358b47e
--- /dev/null
+++ b/package/olsr-time/src/olsr.h
@@ -0,0 +1,43 @@
+#ifndef _OLSR_H_
+#define _OLSR_H_
+
+/* Debug helper macro */
+#ifdef DEBUG
+#define olsr_debug(lvl, format, args...) do {                           \
+    OLSR_PRINTF(lvl, "%s (%s:%d): ", __func__, __FILE__, __LINE__);     \
+    OLSR_PRINTF(lvl, (format), ##args);                                 \
+  } while (0)
+#endif
+
+extern FILE *debug_handle;
+
+#define NODEBUG
+
+#ifdef NODEBUG
+#define OLSR_PRINTF(lvl, format, args...) do { } while(0)
+#else
+#define OLSR_PRINTF(lvl, format, args...) do {                    \
+    if((olsr_cnf->debug_level >= (lvl)) && debug_handle)          \
+      fprintf(debug_handle, (format), ##args);                    \
+  } while (0)
+#endif
+
+struct olsrd_config {
+  uint16_t olsrport;
+  int debug_level;
+};
+
+extern void olsr_exit(const char *, int);
+extern struct olsrd_config *olsr_cnf;
+
+extern uint32_t olsr_times(void);
+extern void olsr_init_timers(void);
+
+extern uint32_t olsr_times2(void);
+extern void olsr_init_timers2(void);
+
+extern int olsr_gettimeofday(struct timeval *__restrict __tv, __timezone_ptr_t __tz);
+
+#define gettimeofday	olsr_gettimeofday
+
+#endif /* _OLSR_H_ */
\ No newline at end of file
diff --git a/package/olsr-time/src/scheduler-bad.c b/package/olsr-time/src/scheduler-bad.c
new file mode 100644
index 0000000..180798b
--- /dev/null
+++ b/package/olsr-time/src/scheduler-bad.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "olsr.h"
+
+uint32_t now_times;                    /* relative time compared to startup (in milliseconds */
+struct timeval first_tv;               /* timevalue during startup */
+struct timeval last_tv;                /* timevalue used for last olsr_times() calculation */
+
+uint32_t
+olsr_times(void)
+{
+  struct timeval tv;
+  uint32_t t;
+
+  if (gettimeofday(&tv, NULL) != 0) {
+    olsr_exit("OS clock is not working, have to shut down OLSR", 1);
+  }
+
+  /* test if time jumped backward or more than 60 seconds forward */
+  if (tv.tv_sec < last_tv.tv_sec || (tv.tv_sec == last_tv.tv_sec && tv.tv_usec < last_tv.tv_usec)
+      || tv.tv_sec - last_tv.tv_sec > 60) {
+    OLSR_PRINTF(1, "Time jump (%d.%06d to %d.%06d)\n",
+              (int32_t) (last_tv.tv_sec), (int32_t) (last_tv.tv_usec), (int32_t) (tv.tv_sec), (int32_t) (tv.tv_usec));
+
+    t = (last_tv.tv_sec - first_tv.tv_sec) * 1000 + (last_tv.tv_usec - first_tv.tv_usec) / 1000;
+    t++;                        /* advance time by one millisecond */
+
+    first_tv = tv;
+    first_tv.tv_sec -= (t / 1000);
+    first_tv.tv_usec -= ((t % 1000) * 1000);
+
+    if (first_tv.tv_usec < 0) {
+      first_tv.tv_sec--;
+      first_tv.tv_usec += 1000000;
+    }
+    last_tv = tv;
+    return t;
+  }
+  last_tv = tv;
+  return (tv.tv_sec - first_tv.tv_sec) * 1000 + (tv.tv_usec - first_tv.tv_usec) / 1000;
+}
+
+void
+olsr_init_timers(void)
+{
+  /* Grab initial timestamp */
+  if (gettimeofday(&first_tv, NULL)) {
+    olsr_exit("OS clock is not working, have to shut down OLSR", 1);
+  }
+  last_tv = first_tv;
+  now_times = olsr_times();
+}
diff --git a/package/olsr-time/src/scheduler-good.c b/package/olsr-time/src/scheduler-good.c
new file mode 100644
index 0000000..56fd704
--- /dev/null
+++ b/package/olsr-time/src/scheduler-good.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "olsr.h"
+
+uint32_t now_times2;                    /* relative time compared to startup (in milliseconds */
+struct timeval first_tv2;               /* timevalue during startup */
+struct timeval last_tv2;                /* timevalue used for last olsr_times() calculation */
+
+uint32_t
+olsr_times2(void)
+{
+  struct timeval tv;
+  volatile uint32_t t, ms;
+
+  if (gettimeofday(&tv, NULL) != 0) {
+    olsr_exit("OS clock is not working, have to shut down OLSR", 1);
+  }
+
+  /* test if time jumped backward or more than 60 seconds forward */
+  if (tv.tv_sec < last_tv2.tv_sec || (tv.tv_sec == last_tv2.tv_sec && tv.tv_usec < last_tv2.tv_usec)
+      || tv.tv_sec - last_tv2.tv_sec > 60) {
+    OLSR_PRINTF(1, "Time jump (%d.%06d to %d.%06d)\n",
+              (int32_t) (last_tv2.tv_sec), (int32_t) (last_tv2.tv_usec), (int32_t) (tv.tv_sec), (int32_t) (tv.tv_usec));
+
+    t = (last_tv2.tv_sec - first_tv2.tv_sec) * 1000 + (last_tv2.tv_usec - first_tv2.tv_usec) / 1000;
+    t++;                        /* advance time by one millisecond */
+
+    first_tv2 = tv;
+    first_tv2.tv_sec -= (t / 1000);
+    first_tv2.tv_usec -= ((t % 1000) * 1000);
+
+    if (first_tv2.tv_usec < 0) {
+      first_tv2.tv_sec--;
+      first_tv2.tv_usec += 1000000;
+    }
+    last_tv2 = tv;
+    return t;
+  }
+  last_tv2 = tv;
+  t = (tv.tv_sec - first_tv2.tv_sec) * 1000;
+  ms = (tv.tv_usec - first_tv2.tv_usec) / 1000;
+  return t + ms;
+}
+
+void
+olsr_init_timers2(void)
+{
+  /* Grab initial timestamp */
+  if (gettimeofday(&first_tv2, NULL)) {
+    olsr_exit("OS clock is not working, have to shut down OLSR", 1);
+  }
+  last_tv2 = first_tv2;
+  now_times2 = olsr_times2();
+}
-- 
1.7.10

