Backport of development scheduler (supports sockets with immediately handling instead...
authorHenning Rogge <hrogge@googlemail.com>
Sun, 7 Feb 2010 19:33:10 +0000 (20:33 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Sun, 7 Feb 2010 19:33:10 +0000 (20:33 +0100)
25 files changed:
lib/dot_draw/src/olsrd_dot_draw.c
lib/httpinfo/src/olsrd_httpinfo.c
lib/pgraph/src/olsrd_pgraph.c
lib/secure/src/olsrd_secure.c
lib/txtinfo/src/olsrd_txtinfo.c
lib/watchdog/src/olsrd_plugin.c
src/defs.h
src/hna_set.c
src/interfaces.c
src/ipc_frontend.c
src/ipc_frontend.h
src/kernel_routes.h
src/link_set.c
src/linux/kernel_routes.c
src/main.c
src/mid_set.h
src/olsr_cfg.h
src/parser.c
src/parser.h
src/scheduler.c
src/scheduler.h
src/socket_parser.c [deleted file]
src/socket_parser.h [deleted file]
src/tc_set.c
src/unix/ifnet.c

index 23f7113..fef7430 100644 (file)
@@ -73,7 +73,6 @@
 #include "hna_set.h"
 #include "mid_set.h"
 #include "link_set.h"
-#include "socket_parser.h"
 #include "net_olsr.h"
 #include "lq_plugin.h"
 #include "common/autobuf.h"
@@ -104,7 +103,7 @@ static int plugin_ipc_init(void);
 /* Event function to register with the sceduler */
 static int pcf_event(int, int, int);
 
-static void ipc_action(int);
+static void ipc_action(int, void *, unsigned int);
 
 static void ipc_print_neigh_link(struct autobuf *abuf, const struct neighbor_entry *neighbor);
 
@@ -243,13 +242,13 @@ plugin_ipc_init(void)
 #if 0
   printf("Adding socket with olsrd\n");
 #endif
-  add_olsr_socket(ipc_socket, &ipc_action);
+  add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
 
   return 1;
 }
 
 static void
-ipc_action(int fd __attribute__ ((unused)))
+ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   struct sockaddr_in pin;
   socklen_t addrlen = sizeof(struct sockaddr_in);
index 08620ff..7244175 100644 (file)
@@ -60,7 +60,6 @@
 #include "olsr_protocol.h"
 #include "net_olsr.h"
 #include "link_set.h"
-#include "socket_parser.h"
 #include "ipcalc.h"
 #include "lq_plugin.h"
 #include "common/autobuf.h"
@@ -159,7 +158,7 @@ static int get_http_socket(int);
 
 static void build_tabs(struct autobuf *, int);
 
-static void parse_http_request(int);
+static void parse_http_request(int fd, void *, unsigned int);
 
 static int build_http_header(http_header_type, bool, uint32_t, char *, uint32_t);
 
@@ -313,14 +312,14 @@ olsrd_plugin_init(void)
   }
 
   /* Register socket */
-  add_olsr_socket(http_socket, &parse_http_request);
+  add_olsr_socket(http_socket, &parse_http_request, NULL, NULL, SP_PR_READ);
 
   return 1;
 }
 
 /* Non reentrant - but we are not multithreaded anyway */
-void
-parse_http_request(int fd)
+static void
+parse_http_request(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   struct sockaddr_in pin;
   struct autobuf body_abuf = { 0, 0, NULL };
index 2f79e96..fc6e8fa 100644 (file)
@@ -46,7 +46,6 @@
 
 #include "olsrd_pgraph.h"
 #include "ipcalc.h"
-#include "socket_parser.h"
 #include "olsrd_plugin.h"
 #include "plugin_util.h"
 #include "net_olsr.h"
@@ -139,7 +138,7 @@ olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *
 /* Event function to register with the sceduler */
 static int pcf_event(int, int, int);
 
-static void ipc_action(int);
+static void ipc_action(int, void *, unsigned int);
 
 static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
 
@@ -254,14 +253,14 @@ plugin_ipc_init(void)
     }
 
     /* Register with olsrd */
-    add_olsr_socket(ipc_socket, &ipc_action);
+    add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
   }
 
   return 1;
 }
 
 static void
-ipc_action(int fd __attribute__ ((unused)))
+ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   struct sockaddr_in pin;
   socklen_t addrlen;
index 2b4466c..c6033fc 100644 (file)
@@ -51,7 +51,6 @@
 #include "defs.h"
 #include "ipcalc.h"
 #include "olsr.h"
-#include "socket_parser.h"
 #include "parser.h"
 #include "scheduler.h"
 #include "net_olsr.h"
index f1e4150..df53063 100644 (file)
@@ -74,7 +74,6 @@
 #include "hna_set.h"
 #include "mid_set.h"
 #include "link_set.h"
-#include "socket_parser.h"
 #include "net_olsr.h"
 #include "lq_plugin.h"
 #include "common/autobuf.h"
@@ -93,7 +92,7 @@ static int plugin_ipc_init(void);
 
 static void send_info(int /*send_what*/, int /*socket*/);
 
-static void ipc_action(int);
+static void ipc_action(int, void *, unsigned int);
 
 static void ipc_print_neigh(struct autobuf *);
 
@@ -223,7 +222,7 @@ plugin_ipc_init(void)
     }
 
     /* Register with olsrd */
-    add_olsr_socket(ipc_socket, &ipc_action);
+    add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
 
 #ifndef NODEBUG
     olsr_printf(2, "(TXTINFO) listening on port %d\n", ipc_port);
@@ -233,7 +232,7 @@ plugin_ipc_init(void)
 }
 
 static void
-ipc_action(int fd)
+ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   struct sockaddr_storage pin;
   struct sockaddr_in *sin4;
index 4e2649c..849aac9 100644 (file)
@@ -132,7 +132,7 @@ olsrd_plugin_init(void)
 
   /* Register the GW check */
   olsr_start_timer(watchdog_interval * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
-                   &olsr_watchdog_write_alivefile, NULL, watchdog_timer_cookie->ci_id);
+                   &olsr_watchdog_write_alivefile, NULL, watchdog_timer_cookie);
 
   return 1;
 }
index b946180..23f956e 100644 (file)
@@ -181,14 +181,13 @@ extern struct olsrd_config *olsr_cnf;
 
 /* Timer data */
 extern uint32_t now_times;              /* current idea of times(2) reported uptime */
+extern struct olsr_cookie_info *def_timer_ci;
 
 #if defined WIN32
 extern bool olsr_win32_end_request;
 extern bool olsr_win32_end_flag;
 #endif
 
-uint32_t olsr_times(void);
-
 /*
  *IPC functions
  *These are moved to a plugin soon
index 2b5a962..fdb0648 100644 (file)
@@ -303,7 +303,7 @@ olsr_update_hna_entry(const union olsr_ip_addr *gw, const union olsr_ip_addr *ne
    * Start, or refresh the timer, whatever is appropriate.
    */
   olsr_set_timer(&net_entry->hna_net_timer, vtime, OLSR_HNA_NET_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_hna_net_entry, net_entry,
-                 hna_net_timer_cookie->ci_id);
+                 hna_net_timer_cookie);
 }
 
 /**
index 9fd7954..4497514 100644 (file)
@@ -51,7 +51,6 @@
 #include "ipcalc.h"
 #include "log.h"
 #include "parser.h"
-#include "socket_parser.h"
 
 #ifdef WIN32
 #include <winbase.h>
@@ -114,7 +113,7 @@ olsr_init_interfacedb(void)
 
   /* Kick a periodic timer for the network interface update function */
   olsr_start_timer((unsigned int)olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5, OLSR_TIMER_PERIODIC, &check_interface_updates, NULL,
-                   interface_poll_timer_cookie->ci_id);
+                   interface_poll_timer_cookie);
 
   return (ifnet == NULL) ? 0 : 1;
 }
@@ -429,11 +428,11 @@ olsr_remove_interface(struct olsr_if * iface)
 
   /* Close olsr socket */
   close(ifp->olsr_socket);
-  remove_olsr_socket(ifp->olsr_socket, &olsr_input);
+  remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL);
 
   if (ifp->send_socket != ifp->olsr_socket) {
     close(ifp->send_socket);
-    remove_olsr_socket(ifp->send_socket, &olsr_input);
+    remove_olsr_socket(ifp->send_socket, &olsr_input, NULL);
   }
 
   /* Free memory */
index ddcea77..50f52c4 100644 (file)
@@ -51,7 +51,7 @@
 #include "olsr.h"
 #include "log.h"
 #include "parser.h"
-#include "socket_parser.h"
+#include "scheduler.h"
 #include "net_olsr.h"
 #include "ipcalc.h"
 
@@ -125,13 +125,14 @@ ipc_init(void)
   }
 
   /* Register the socket with the socket parser */
-  add_olsr_socket(ipc_sock, &ipc_accept);
+  add_olsr_socket(ipc_sock, &ipc_accept, NULL, NULL, SP_PR_READ);
 
   return ipc_sock;
 }
 
+
 void
-ipc_accept(int fd)
+ipc_accept(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   socklen_t addrlen;
   struct sockaddr_in pin;
index af333ea..308f3a6 100644 (file)
@@ -96,7 +96,7 @@ struct ipc_net_msg {
 
 bool ipc_check_allowed_ip(const union olsr_ip_addr *);
 
-void ipc_accept(int);
+void ipc_accept(int fd, void *, unsigned int);
 
 bool frontend_msgparser(union olsr_message *, struct interface *, union olsr_ip_addr *);
 
index 59bd4a3..b2dba0c 100644 (file)
@@ -66,7 +66,6 @@ int olsr_del_tunl(void);
 
 #if LINUX_RTNETLINK_LISTEN
 int rtnetlink_register_socket(int);
-void rtnetlink_read(int);
 #endif /*LINUX_RTNETLINK_LISTEN*/
 
 #endif
index 27306a9..a4bf43d 100644 (file)
@@ -504,7 +504,7 @@ olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
 
   OLSR_PRINTF(3, "reset link timer: %s = %u\n",
     olsr_ip_to_string(&buf, &link->neighbor_iface_addr),
-    (unsigned int)(olsr_times() + rel_timer/1000));
+    (unsigned int)(now_times + rel_timer/1000));
   olsr_set_timer(&link->link_timer, rel_timer, OLSR_LINK_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_link_entry, link, 0);
 }
 
index aef684b..7a597fa 100644 (file)
@@ -81,6 +81,8 @@ static int delete_all_inet_gws(void);
 
 // static struct rtnl_handle rth;
 
+static void rtnetlink_read(int sock, void *, unsigned int);
+
 struct olsr_rtreq {
   struct nlmsghdr n;
   struct rtmsg r;
@@ -95,7 +97,6 @@ struct olsr_ipadd_req {
 
 #if LINUX_RTNETLINK_LISTEN
 #include "ifnet.h"
-#include "socket_parser.h"
 
 int rtnetlink_register_socket(int rtnl_mgrp)
 {
@@ -117,7 +118,7 @@ int rtnetlink_register_socket(int rtnl_mgrp)
     return -1;
   }
 
-  add_olsr_socket(sock, &rtnetlink_read);
+  add_olsr_socket(sock, NULL, &rtnetlink_read, NULL, SP_IMM_READ);
   return sock;
 }
 
@@ -187,7 +188,7 @@ static void netlink_process_link(struct nlmsghdr *h)
   }
 }
 
-void rtnetlink_read(int sock)
+static void rtnetlink_read(int sock, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   int len, plen;
   struct iovec iov;
index 89e348b..60d599a 100644 (file)
@@ -52,7 +52,6 @@
 #include "parser.h"
 #include "generate_msg.h"
 #include "plugin_loader.h"
-#include "socket_parser.h"
 #include "apm.h"
 #include "net_os.h"
 #include "build_msg.h"
@@ -114,6 +113,7 @@ static char
 static int lock_fd = 0;
 #endif
 static char lock_file_name[FILENAME_MAX];
+struct olsr_cookie_info *def_timer_ci = NULL;
 
 /*
  * Creates a zero-length locking file and use fcntl to
@@ -372,6 +372,8 @@ int main(int argc, char *argv[]) {
   disable_redirects_global(olsr_cnf->ip_version);
 #endif
 
+  def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER);
+
   /*
    * socket for ioctl calls
    */
index 3069e36..ad3097f 100644 (file)
@@ -45,6 +45,7 @@
 #include "olsr_types.h"
 #include "hashing.h"
 #include "mantissa.h"
+#include "packet.h"
 
 struct mid_address {
   union olsr_ip_addr alias;
@@ -73,8 +74,6 @@ struct mid_entry {
 extern struct mid_entry mid_set[HASHSIZE];
 extern struct mid_address reverse_mid_set[HASHSIZE];
 
-struct mid_alias;
-
 int olsr_init_mid_set(void);
 void olsr_delete_all_mid_entries(void);
 void olsr_cleanup_mid(union olsr_ip_addr *);
index 4e0e604..eafc24c 100644 (file)
@@ -64,7 +64,7 @@
 #endif
 
 /* Default values not declared in olsr_protocol.h */
-#define DEF_POLLRATE         0.05
+#define DEF_POLLRATE         0.1
 #define DEF_NICCHGPOLLRT     2.5
 #define DEF_WILL_AUTO        false
 #define DEF_WILLINGNESS      3
index f7e61be..4cd4dcb 100644 (file)
@@ -65,7 +65,7 @@ char *StrError(unsigned int ErrNo);
 #define strerror(x) StrError(x)
 #endif
 
-/* Sven-Ola: On very slow devices used in huge networks
+    /* Sven-Ola: On very slow devices used in huge networks
  * the amount of lq_tc messages is so high, that the
  * recv() loop never ends. This is a small hack to end
  * the loop in this cases
@@ -422,7 +422,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
  *@return nada
  */
 void
-olsr_input(int fd)
+olsr_input(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   struct interface *olsr_in_if;
   union olsr_ip_addr from_addr;
@@ -515,7 +515,7 @@ olsr_input(int fd)
  *@return nada
  */
 void
-olsr_input_hostemu(int fd)
+olsr_input_hostemu(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
 {
   /* sockaddr_in6 is bigger than sockaddr !!!! */
   struct sockaddr_storage from;
index 99d50ed..f7e13ef 100644 (file)
@@ -76,9 +76,9 @@ void olsr_init_parser(void);
 
 void olsr_destroy_parser(void);
 
-void olsr_input(int);
+void olsr_input(int fd, void *, unsigned int);
 
-void olsr_input_hostemu(int);
+void olsr_input_hostemu(int fd, void *, unsigned int);
 
 void olsr_parser_add_function(parse_function, uint32_t);
 
index 6f6c26c..7325b1b 100644 (file)
@@ -1,8 +1,7 @@
 
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
- * Timer rewrite (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  */
 
-#include <assert.h>
-
-#include "defs.h"
 #include "scheduler.h"
 #include "log.h"
-#include "tc_set.h"
 #include "link_set.h"
-#include "duplicate_set.h"
-#include "mpr_selector_set.h"
-#include "mid_set.h"
-#include "mpr.h"
 #include "olsr.h"
-#include "build_msg.h"
-#include "net_olsr.h"
-#include "socket_parser.h"
-#include "olsr_spf.h"
-#include "link_set.h"
 #include "olsr_cookie.h"
-#ifdef WIN32
-/* Need stdlib for rand() */
-#include <stdlib.h>
-#define random() rand()
-#define srandom(x) srand(x)
-#endif
-
-/* Timer data, global. Externed in defs.h */
+#include "net_os.h"
+#include "mpr_selector_set.h"
+
+#include <sys/times.h>
+
+#include <unistd.h>
+#include <assert.h>
+
+/* Timer data, global. Externed in scheduler.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 */
 
 /* Hashed root of all timers */
 static struct list_node timer_wheel[TIMER_WHEEL_SLOTS];
-static uint32_t timer_last_run;                /* remember the last timeslot walk */
+static uint32_t timer_last_run;        /* remember the last timeslot walk */
 
-/* Pool of timers to avoid malloc() churn */
-static struct list_node free_timer_list;
+/* Memory cookie for the block based memory manager */
+static struct olsr_cookie_info *timer_mem_cookie = NULL;
 
-/* Statistics */
-unsigned int timers_running;
+/* Head of all OLSR used sockets */
+static struct list_node socket_head = { &socket_head, &socket_head };
 
-uint32_t
+/* Prototypes */
+static void walk_timers(uint32_t *);
+static void poll_sockets(void);
+static uint32_t calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val);
+
+/*
+ * A wrapper around times(2). Note, that this function has some
+ * portability problems, so do not rely on absolute values returned.
+ * Under Linux, uclibc and libc directly call the sys_times() located
+ * in kernel/sys.c and will only return an error if the tms_buf is
+ * not writeable.
+ */
+static uint32_t
 olsr_times(void)
 {
   struct timeval tv;
   uint32_t t;
 
   if (gettimeofday(&tv, NULL) != 0) {
-    OLSR_PRINTF(0, "OS clock is not working, have to shut down OLSR (%s)\n", strerror(errno));
-    exit(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(3, "Time jump (%d.%06d to %d.%06d)\n",
+    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;
@@ -161,37 +159,277 @@ olsr_isTimedOut(uint32_t s)
 }
 
 /**
- * Sleep until the next scheduling interval.
+ * Add a socket and handler to the socketset
+ * beeing used in the main select(2) loop
+ * in listen_loop
  *
- * @param scheduler loop runtime in clock ticks.
- * @return nada
+ *@param fd the socket
+ *@param pf the processing function
+ */
+void
+add_olsr_socket(int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, void *data, unsigned int flags)
+{
+  struct olsr_socket_entry *new_entry;
+
+  if (fd < 0 || (pf_pr == NULL && pf_imm == NULL)) {
+    OLSR_PRINTF(1, "Bogus socket entry - not registering...");
+    return;
+  }
+  OLSR_PRINTF(3, "Adding OLSR socket entry %d\n", fd);
+
+  new_entry = olsr_malloc(sizeof(*new_entry), "Socket entry");
+
+  new_entry->fd = fd;
+  new_entry->process_immediate = pf_imm;
+  new_entry->process_pollrate = pf_pr;
+  new_entry->data = data;
+  new_entry->flags = flags;
+
+  /* Queue */
+  list_node_init(&new_entry->socket_node);
+  list_add_before(&socket_head, &new_entry->socket_node);
+}
+
+/**
+ * Remove a socket and handler to the socketset
+ * beeing used in the main select(2) loop
+ * in listen_loop
+ *
+ *@param fd the socket
+ *@param pf the processing function
+ */
+int
+remove_olsr_socket(int fd, socket_handler_func pf_pr, socket_handler_func pf_imm)
+{
+  struct olsr_socket_entry *entry;
+
+  if (fd < 0 || (pf_pr == NULL && pf_imm == NULL)) {
+    OLSR_PRINTF(1, "Bogus socket entry - not processing...");
+    return 0;
+  }
+  OLSR_PRINTF(3, "Removing OLSR socket entry %d\n", fd);
+
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    if (entry->fd == fd && entry->process_immediate == pf_imm && entry->process_pollrate == pf_pr) {
+      list_remove(&entry->socket_node);
+      free(entry);
+      return 1;
+    }
+  }
+  OLSR_FOR_ALL_SOCKETS_END(entry);
+  return 0;
+}
+
+void
+enable_olsr_socket(int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, unsigned int flags)
+{
+  struct olsr_socket_entry *entry;
+
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    if (entry->fd == fd && entry->process_immediate == pf_imm && entry->process_pollrate == pf_pr) {
+      entry->flags |= flags;
+    }
+  }
+  OLSR_FOR_ALL_SOCKETS_END(entry);
+}
+
+void
+disable_olsr_socket(int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, unsigned int flags)
+{
+  struct olsr_socket_entry *entry;
+
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    if (entry->fd == fd && entry->process_immediate == pf_imm && entry->process_pollrate == pf_pr) {
+      entry->flags &= ~flags;
+    }
+  }
+  OLSR_FOR_ALL_SOCKETS_END(entry);
+}
+
+/**
+ * Close and free all sockets.
  */
+void
+olsr_flush_sockets(void)
+{
+  struct olsr_socket_entry *entry;
+
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    close(entry->fd);
+    list_remove(&entry->socket_node);
+    free(entry);
+  } OLSR_FOR_ALL_SOCKETS_END(entry);
+}
+
 static void
-olsr_scheduler_sleep(uint32_t scheduler_runtime)
+poll_sockets(void)
 {
-  struct timespec remainder_spec, sleeptime_spec;
-  struct timeval sleeptime_val, time_used, next_interval;
-  uint32_t next_interval_usec;
-  unsigned long milliseconds_used;
+  int n;
+  struct olsr_socket_entry *entry;
+  fd_set ibits, obits;
+  struct timeval tvp = { 0, 0 };
+  int hfd = 0, fdsets = 0;
+
+  /* If there are no registered sockets we
+   * do not call select(2)
+   */
+  if (list_is_empty(&socket_head)) {
+    return;
+  }
 
-  /* Calculate next planned scheduler invocation */
-  next_interval_usec = olsr_cnf->pollrate * USEC_PER_SEC;
-  next_interval.tv_sec = next_interval_usec / USEC_PER_SEC;
-  next_interval.tv_usec = next_interval_usec % USEC_PER_SEC;
+  FD_ZERO(&ibits);
+  FD_ZERO(&obits);
 
-  /* Determine used runtime */
-  milliseconds_used = scheduler_runtime;
-  time_used.tv_sec = milliseconds_used / MSEC_PER_SEC;
-  time_used.tv_usec = (milliseconds_used % MSEC_PER_SEC) * USEC_PER_MSEC;
+  /* Adding file-descriptors to FD set */
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    if (entry->process_pollrate == NULL) {
+      continue;
+    }
+    if ((entry->flags & SP_PR_READ) != 0) {
+      fdsets |= SP_PR_READ;
+      FD_SET((unsigned int)entry->fd, &ibits);  /* And we cast here since we get a warning on Win32 */
+    }
+    if ((entry->flags & SP_PR_WRITE) != 0) {
+      fdsets |= SP_PR_WRITE;
+      FD_SET((unsigned int)entry->fd, &obits);  /* And we cast here since we get a warning on Win32 */
+    }
+    if ((entry->flags & (SP_PR_READ | SP_PR_WRITE)) != 0 && entry->fd >= hfd) {
+      hfd = entry->fd + 1;
+    }
+  }
+  OLSR_FOR_ALL_SOCKETS_END(entry);
 
-  if (timercmp(&time_used, &next_interval, <)) {
-    timersub(&next_interval, &time_used, &sleeptime_val);
+  /* Running select on the FD set */
+  do {
+    n = olsr_select(hfd, fdsets & SP_PR_READ ? &ibits : NULL, fdsets & SP_PR_WRITE ? &obits : NULL, NULL, &tvp);
+  } while (n == -1 && errno == EINTR);
 
-    sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
-    sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * NSEC_PER_USEC;
+  if (n == 0) {
+    return;
+  }
+  if (n == -1) {                /* Did something go wrong? */
+    OLSR_PRINTF(1, "select error: %s", strerror(errno));
+    return;
+  }
 
-    while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
-      sleeptime_spec = remainder_spec;
+  /* Update time since this is much used by the parsing functions */
+  now_times = olsr_times();
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    int flags;
+    if (entry->process_pollrate == NULL) {
+      continue;
+    }
+    flags = 0;
+    if (FD_ISSET(entry->fd, &ibits)) {
+      flags |= SP_PR_READ;
+    }
+    if (FD_ISSET(entry->fd, &obits)) {
+      flags |= SP_PR_WRITE;
+    }
+    if (flags != 0) {
+      entry->process_pollrate(entry->fd, entry->data, flags);
+    }
+  }
+  OLSR_FOR_ALL_SOCKETS_END(entry);
+}
+
+static void
+handle_fds(uint32_t next_interval)
+{
+  struct timeval tvp;
+  int32_t remaining;
+
+  /* calculate the first timeout */
+  now_times = olsr_times();
+
+  remaining = TIME_DUE(next_interval);
+  if (remaining <= 0) {
+    /* we are already over the interval */
+    if (list_is_empty(&socket_head)) {
+      /* If there are no registered sockets we do not call select(2) */
+      return;
+    }
+    tvp.tv_sec = 0;
+    tvp.tv_usec = 0;
+  } else {
+    /* we need an absolute time - milliseconds */
+    tvp.tv_sec = remaining / MSEC_PER_SEC;
+    tvp.tv_usec = (remaining % MSEC_PER_SEC) * USEC_PER_MSEC;
+  }
+
+  /* do at least one select */
+  for (;;) {
+    struct olsr_socket_entry *entry;
+    fd_set ibits, obits;
+    int n, hfd = 0, fdsets = 0;
+    FD_ZERO(&ibits);
+    FD_ZERO(&obits);
+
+    /* Adding file-descriptors to FD set */
+    OLSR_FOR_ALL_SOCKETS(entry) {
+      if (entry->process_immediate == NULL) {
+        continue;
+      }
+      if ((entry->flags & SP_IMM_READ) != 0) {
+        fdsets |= SP_IMM_READ;
+        FD_SET((unsigned int)entry->fd, &ibits);        /* And we cast here since we get a warning on Win32 */
+      }
+      if ((entry->flags & SP_IMM_WRITE) != 0) {
+        fdsets |= SP_IMM_WRITE;
+        FD_SET((unsigned int)entry->fd, &obits);        /* And we cast here since we get a warning on Win32 */
+      }
+      if ((entry->flags & (SP_IMM_READ | SP_IMM_WRITE)) != 0 && entry->fd >= hfd) {
+        hfd = entry->fd + 1;
+      }
+    }
+    OLSR_FOR_ALL_SOCKETS_END(entry);
+
+    if (hfd == 0 && (long)remaining <= 0) {
+      /* we are over the interval and we have no fd's. Skip the select() etc. */
+      return;
+    }
+
+    do {
+      n = olsr_select(hfd, fdsets & SP_IMM_READ ? &ibits : NULL, fdsets & SP_IMM_WRITE ? &obits : NULL, NULL, &tvp);
+    } while (n == -1 && errno == EINTR);
+
+    if (n == 0) {               /* timeout! */
+      break;
+    }
+    if (n == -1) {              /* Did something go wrong? */
+      OLSR_PRINTF(1, "select error: %s", strerror(errno));
+      break;
+    }
+
+    /* Update time since this is much used by the parsing functions */
+    now_times = olsr_times();
+    OLSR_FOR_ALL_SOCKETS(entry) {
+      int flags;
+      if (entry->process_immediate == NULL) {
+        continue;
+      }
+      flags = 0;
+      if (FD_ISSET(entry->fd, &ibits)) {
+        flags |= SP_IMM_READ;
+      }
+      if (FD_ISSET(entry->fd, &obits)) {
+        flags |= SP_IMM_WRITE;
+      }
+      if (flags != 0) {
+        entry->process_immediate(entry->fd, entry->data, flags);
+      }
+    }
+    OLSR_FOR_ALL_SOCKETS_END(entry);
+
+    /* calculate the next timeout */
+    remaining = TIME_DUE(next_interval);
+    if (remaining <= 0) {
+      /* we are already over the interval */
+      break;
+    }
+    /* we need an absolute time - milliseconds */
+    tvp.tv_sec = remaining / MSEC_PER_SEC;
+    tvp.tv_usec = (remaining % MSEC_PER_SEC) * USEC_PER_MSEC;
   }
 }
 
@@ -204,69 +442,41 @@ olsr_scheduler_sleep(uint32_t scheduler_runtime)
  *
  * @return nada
  */
-void
+void __attribute__ ((noreturn))
 olsr_scheduler(void)
 {
-  struct interface *ifn;
-
-  OLSR_PRINTF(1, "Scheduler started - polling every %0.2f seconds\n", olsr_cnf->pollrate);
-  OLSR_PRINTF(3, "Max jitter is %f\n\n", olsr_cnf->max_jitter);
+  OLSR_PRINTF(1, "Scheduler started - polling every %f ms\n", olsr_cnf->pollrate);
 
   /* Main scheduler loop */
-  for (;;) {
+  while (true) {
+    uint32_t next_interval;
 
     /*
      * Update the global timestamp. We are using a non-wallclock timer here
      * to avoid any undesired side effects if the system clock changes.
      */
     now_times = olsr_times();
+    next_interval = GET_TIMESTAMP(olsr_cnf->pollrate * 1000);
 
     /* Read incoming data */
-    olsr_poll_sockets();
+    poll_sockets();
 
-    /* Process timers (before packet generation) */
-    olsr_walk_timers(&timer_last_run);
+    /* Process timers */
+    walk_timers(&timer_last_run);
 
     /* Update */
     olsr_process_changes();
 
     /* Check for changes in topology */
     if (link_changes) {
-      OLSR_PRINTF(3, "ANSN UPDATED %d\n\n", get_local_ansn());
       increase_local_ansn();
+      OLSR_PRINTF(3, "ANSN UPDATED %d\n\n", get_local_ansn());
       link_changes = false;
     }
 
-    /* looping trough interfaces and emmitting pending data */
-    for (ifn = ifnet; ifn; ifn = ifn->int_next) {
-      if (net_output_pending(ifn) && TIMED_OUT(ifn->fwdtimer)) {
-        net_output(ifn);
-      }
-    }
-
-    /* We are done, sleep until the next scheduling interval. */
-    olsr_scheduler_sleep(olsr_times() - now_times);
-
-#if defined WIN32
-    /* The Ctrl-C signal handler thread asks us to exit */
-    if (olsr_win32_end_request) {
-      break;
-    }
-#endif
+    /* Read incoming data and handle it immediiately */
+    handle_fds(next_interval);
   }
-
-#if defined WIN32
-  /* Tell the Ctrl-C signal handler thread that we have exited */
-  olsr_win32_end_flag = TRUE;
-
-  /*
-   * The Ctrl-C signal handler thread will exit the process
-   * and hence also kill us.
-   */
-  while (1) {
-    Sleep(1000);                /* milliseconds */
-  }
-#endif
 }
 
 /**
@@ -278,7 +488,7 @@ olsr_scheduler(void)
  * @return the absolute timer in system clock tick units
  */
 static uint32_t
-olsr_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val)
+calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val)
 {
   unsigned int jitter_time;
 
@@ -294,95 +504,32 @@ olsr_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val)
    * Play some tricks to avoid overflows with integer arithmetic.
    */
   jitter_time = (jitter_pct * rel_time) / 100;
-  jitter_time = random_val / (1 + RAND_MAX / jitter_time);
+  jitter_time = random_val / (1 + RAND_MAX / (jitter_time + 1));
 
-#if 0
   OLSR_PRINTF(3, "TIMER: jitter %u%% rel_time %ums to %ums\n", jitter_pct, rel_time, rel_time - jitter_time);
-#endif
 
   return GET_TIMESTAMP(rel_time - jitter_time);
 }
 
-/**
- * Allocate a timer_entry.
- * Do this first by checking if something is available in the free_timer_pool
- * If not then allocate a big chunk of memory and thread its elements up
- * to the free_timer_list.
- */
-static struct timer_entry *
-olsr_get_timer(void)
-{
-  void *timer_block;
-  struct timer_entry *timer;
-  struct list_node *timer_list_node;
-  unsigned int timer_index;
-
-  /*
-   * If there is at least one timer in the pool then remove the first
-   * element from the pool and recycle it.
-   */
-  if (!list_is_empty(&free_timer_list)) {
-    timer_list_node = free_timer_list.next;
-
-    /* carve it out of the pool, do not memset overwrite timer->timer_random */
-    list_remove(timer_list_node);
-    timer = list2timer(timer_list_node);
-
-    return timer;
-  }
-
-  /*
-   * Nothing in the pool, allocate a new chunk.
-   */
-  timer_block = olsr_malloc(sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK, "timer chunk");
-
-#if 0
-  OLSR_PRINTF(3, "TIMER: alloc %u bytes chunk at %p\n", sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK, timer_block);
-#endif
-
-  /*
-   * Slice the chunk up and put the future timer_entries in the free timer pool.
-   */
-  timer = timer_block;
-  for (timer_index = 0; timer_index < OLSR_TIMER_MEMORY_CHUNK; timer_index++) {
-
-    /* Insert new timers at the tail of the free_timer list */
-    list_add_before(&free_timer_list, &timer->timer_list);
-
-    /*
-     * For performance reasons (read: frequent timer changes),
-     * precompute a random number once per timer and reuse later.
-     * The random number only gets recomputed if a periodical timer fires,
-     * such that a different jitter is applied for future firing.
-     */
-    timer->timer_random = random();
-
-    timer++;
-  }
-
-  /*
-   * There are now timers in the pool, recurse once.
-   */
-  return olsr_get_timer();
-}
-
 /**
  * Init datastructures for maintaining timers.
  */
 void
 olsr_init_timers(void)
 {
-  struct list_node *timer_head_node;
   int idx;
 
-  OLSR_PRINTF(5, "TIMER: init timers\n");
+  OLSR_PRINTF(3, "Initializing scheduler.\n");
 
-  memset(timer_wheel, 0, sizeof(timer_wheel));
+  /* 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();
 
-  timer_head_node = timer_wheel;
   for (idx = 0; idx < TIMER_WHEEL_SLOTS; idx++) {
-    list_head_init(timer_head_node);
-    timer_head_node++;
+    list_head_init(&timer_wheel[idx]);
   }
 
   /*
@@ -390,30 +537,19 @@ olsr_init_timers(void)
    */
   timer_last_run = now_times;
 
-  if (gettimeofday(&first_tv, NULL)) {
-    OLSR_PRINTF(0, "OS clock is not working, have to shut down OLSR (%d)\n", errno);
-    exit(1);
-  }
-  last_tv = first_tv;
-  now_times = olsr_times();
-
-  /* Timer memory pooling */
-  list_head_init(&free_timer_list);
-  timers_running = 0;
+  /* Allocate a cookie for the block based memeory manager. */
+  timer_mem_cookie = olsr_alloc_cookie("timer_entry", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(timer_mem_cookie, sizeof(struct timer_entry));
 }
 
 /**
  * Walk through the timer list and check if any timer is ready to fire.
  * Callback the provided function with the context pointer.
  */
-void
-olsr_walk_timers(uint32_t * last_run)
+static void
+walk_timers(uint32_t * last_run)
 {
-  static struct timer_entry *timer;
-  struct list_node *timer_head_node;
-  struct list_node *timer_node, tmp_head_node;
-  unsigned int timers_walked, timers_fired;
-  unsigned int total_timers_walked, total_timers_fired;
+  unsigned int total_timers_walked = 0, total_timers_fired = 0;
   unsigned int wheel_slot_walks = 0;
 
   /*
@@ -421,21 +557,22 @@ olsr_walk_timers(uint32_t * last_run)
    * or check *all* the wheel slots, whatever is less work.
    * The latter is meant as a safety belt if the scheduler falls behind.
    */
-  total_timers_walked = total_timers_fired = timers_walked = timers_fired = 0;
   while ((*last_run <= now_times) && (wheel_slot_walks < TIMER_WHEEL_SLOTS)) {
-
+    struct list_node tmp_head_node;
     /* keep some statistics */
-    total_timers_walked += timers_walked;
-    total_timers_fired += timers_fired;
-    timers_walked = 0;
-    timers_fired = 0;
+    unsigned int timers_walked = 0, timers_fired = 0;
 
     /* Get the hash slot for this clocktick */
-    timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK];
+    struct list_node *const timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK];
 
-    /* Walk all entries hanging off this hash bucket */
+    /* Walk all entries hanging off this hash bucket. We treat this basically as a stack
+     * so that we always know if and where the next element is.
+     */
     list_head_init(&tmp_head_node);
-    for (timer_node = timer_head_node->next; !list_is_empty(timer_head_node); timer_node = timer_head_node->next) {
+    while (!list_is_empty(timer_head_node)) {
+      /* the top element */
+      struct list_node *const timer_node = timer_head_node->next;
+      struct timer_entry *const timer = list2timer(timer_node);
 
       /*
        * Dequeue and insert to a temporary list.
@@ -444,40 +581,31 @@ olsr_walk_timers(uint32_t * last_run)
        */
       list_remove(timer_node);
       list_add_after(&tmp_head_node, timer_node);
-      timer = list2timer(timer_node);
       timers_walked++;
 
       /* Ready to fire ? */
       if (TIMED_OUT(timer->timer_clock)) {
 
-        OLSR_PRINTF(3, "TIMER: fire %s timer %p, ctx %p, " "at clocktick %u (%s)\n", olsr_cookie_name(timer->timer_cookie), timer,
-                    timer->timer_cb_context, (unsigned int)*last_run, olsr_wallclock_string());
+        OLSR_PRINTF(7, "TIMER: fire %s timer %p, ctx %p, "
+                   "at clocktick %u (%s)\n",
+                   timer->timer_cookie->ci_name,
+                   timer, timer->timer_cb_context, (unsigned int)*last_run, olsr_wallclock_string());
 
         /* This timer is expired, call into the provided callback function */
         timer->timer_cb(timer->timer_cb_context);
 
-        if (timer->timer_period) {
-
+        /* Only act on actually running timers */
+        if (timer->timer_flags & OLSR_TIMER_RUNNING) {
           /*
            * Don't restart the periodic timer if the callback function has
            * stopped the timer.
            */
-          if (timer->timer_flags & OLSR_TIMER_RUNNING) {
-
+          if (timer->timer_period) {
             /* For periodical timers, rehash the random number and restart */
             timer->timer_random = random();
             olsr_change_timer(timer, timer->timer_period, timer->timer_jitter_pct, OLSR_TIMER_PERIODIC);
-          }
-
-        } else {
-
-          /*
-           * Don't stop the singleshot timer if the callback function has
-           * stopped the timer.
-           */
-          if (timer->timer_flags & OLSR_TIMER_RUNNING) {
-
-            /* Singleshot timers are stopped and returned to the pool */
+          } else {
+            /* Singleshot timers are stopped */
             olsr_stop_timer(timer);
           }
         }
@@ -491,15 +619,18 @@ olsr_walk_timers(uint32_t * last_run)
      */
     list_merge(timer_head_node, &tmp_head_node);
 
+    /* keep some statistics */
+    total_timers_walked += timers_walked;
+    total_timers_fired += timers_fired;
+
     /* Increment the time slot and wheel slot walk iteration */
     (*last_run)++;
     wheel_slot_walks++;
   }
 
-#ifdef DEBUG
-  OLSR_PRINTF(3, "TIMER: processed %4u/%u clockwheel slots, " "timers walked %4u/%u, timers fired %u\n", wheel_slot_walks,
-              TIMER_WHEEL_SLOTS, total_timers_walked, timers_running, total_timers_fired);
-#endif
+  OLSR_PRINTF(7, "TIMER: processed %4u/%d clockwheel slots, "
+             "timers walked %4u/%u, timers fired %u\n",
+             wheel_slot_walks, TIMER_WHEEL_SLOTS, total_timers_walked, timer_mem_cookie->ci_usage, total_timers_fired);
 
   /*
    * If the scheduler has slipped and we have walked all wheel slots,
@@ -508,6 +639,25 @@ olsr_walk_timers(uint32_t * last_run)
   *last_run = now_times;
 }
 
+/**
+ * Stop and delete all timers.
+ */
+void
+olsr_flush_timers(void)
+{
+  struct list_node *timer_head_node;
+  unsigned int wheel_slot = 0;
+
+  for (wheel_slot = 0; wheel_slot < TIMER_WHEEL_SLOTS; wheel_slot++) {
+    timer_head_node = &timer_wheel[wheel_slot & TIMER_WHEEL_MASK];
+
+    /* Kill all entries hanging off this hash bucket. */
+    while (!list_is_empty(timer_head_node)) {
+      olsr_stop_timer(list2timer(timer_head_node->next));
+    }
+  }
+}
+
 /**
  * Returns the difference between gmt and local time in seconds.
  * Use gmtime() and localtime() to keep things simple.
@@ -518,37 +668,28 @@ static int
 olsr_get_timezone(void)
 {
 #define OLSR_TIMEZONE_UNINITIALIZED -1
-
   static int time_diff = OLSR_TIMEZONE_UNINITIALIZED;
-  int dir;
-  struct tm *gmt, *loc;
-  struct tm sgmt;
-  time_t t;
+  if (time_diff == OLSR_TIMEZONE_UNINITIALIZED) {
+    int dir;
+    const time_t t = time(NULL);
+    const struct tm gmt = *gmtime(&t);
+    const struct tm *loc = localtime(&t);
 
-  if (time_diff != OLSR_TIMEZONE_UNINITIALIZED) {
-    return time_diff;
-  }
+    time_diff = (loc->tm_hour - gmt.tm_hour) * 60 * 60 + (loc->tm_min - gmt.tm_min) * 60;
 
-  t = time(NULL);
-  gmt = &sgmt;
-  *gmt = *gmtime(&t);
-  loc = localtime(&t);
-
-  time_diff = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + (loc->tm_min - gmt->tm_min) * 60;
+    /*
+     * If the year or julian day is different, we span 00:00 GMT
+     * and must add or subtract a day. Check the year first to
+     * avoid problems when the julian day wraps.
+     */
+    dir = loc->tm_year - gmt.tm_year;
+    if (!dir) {
+      dir = loc->tm_yday - gmt.tm_yday;
+    }
 
-  /*
-   * If the year or julian day is different, we span 00:00 GMT
-   * and must add or subtract a day. Check the year first to
-   * avoid problems when the julian day wraps.
-   */
-  dir = loc->tm_year - gmt->tm_year;
-  if (!dir) {
-    dir = loc->tm_yday - gmt->tm_yday;
+    time_diff += dir * 24 * 60 * 60;
   }
-
-  time_diff += dir * 24 * 60 * 60;
-
-  return (time_diff);
+  return time_diff;
 }
 
 /**
@@ -561,23 +702,18 @@ olsr_get_timezone(void)
 const char *
 olsr_wallclock_string(void)
 {
-  static char buf[4][sizeof("00:00:00.000000")];
-  static int idx = 0;
-  char *ret;
+  static char buf[sizeof("00:00:00.000000")];
   struct timeval now;
   int sec, usec;
 
-  ret = buf[idx];
-  idx = (idx + 1) & 3;
-
   gettimeofday(&now, NULL);
 
   sec = (int)now.tv_sec + olsr_get_timezone();
   usec = (int)now.tv_usec;
 
-  snprintf(ret, sizeof(buf) / 4, "%02u:%02u:%02u.%06u", (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60, usec);
+  snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06d", (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60, usec);
 
-  return ret;
+  return buf;
 }
 
 /**
@@ -591,18 +727,15 @@ olsr_wallclock_string(void)
 const char *
 olsr_clock_string(uint32_t clk)
 {
-  static char buf[4][sizeof("00:00:00.000")];
-  static int idx = 0;
-  char *ret;
+  static char buf[sizeof("00:00:00.000")];
+
+  /* On most systems a clocktick is a 10ms quantity. */
   unsigned int msec = clk % 1000;
   unsigned int sec = clk / 1000;
 
-  ret = buf[idx];
-  idx = (idx + 1) & 3;
+  snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u", sec / 3600, (sec % 3600) / 60, (sec % 60), (msec % MSEC_PER_SEC));
 
-  snprintf(ret, sizeof(buf) / 4, "%02u:%02u:%02u.%03u", sec / 3600, (sec % 3600) / 60, (sec % 60), (msec % MSEC_PER_SEC));
-
-  return ret;
+  return buf;
 }
 
 /**
@@ -615,41 +748,46 @@ olsr_clock_string(uint32_t clk)
  * @return a pointer to the created entry
  */
 struct timer_entry *
-olsr_start_timer(unsigned int rel_time, uint8_t jitter_pct, bool periodical, void (*timer_cb_function) (void *),
-                 void *context, olsr_cookie_t cookie)
+olsr_start_timer(unsigned int rel_time,
+                 uint8_t jitter_pct, bool periodical, timer_cb_func cb_func, void *context, struct olsr_cookie_info *ci)
 {
   struct timer_entry *timer;
 
-  timer = olsr_get_timer();
+  if (ci == NULL) {
+    ci = def_timer_ci;
+  }
+  assert(cb_func);
+
+  timer = olsr_cookie_malloc(timer_mem_cookie);
+
+  /*
+   * Compute random numbers only once.
+   */
+  if (!timer->timer_random) {
+    timer->timer_random = random();
+  }
 
   /* Fill entry */
-  timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
-  timer->timer_cb = timer_cb_function;
+  timer->timer_clock = calc_jitter(rel_time, jitter_pct, timer->timer_random);
+  timer->timer_cb = cb_func;
   timer->timer_cb_context = context;
   timer->timer_jitter_pct = jitter_pct;
   timer->timer_flags = OLSR_TIMER_RUNNING;
 
   /* The cookie is used for debugging to traceback the originator */
-  timer->timer_cookie = cookie;
-  olsr_cookie_usage_incr(cookie);
+  timer->timer_cookie = ci;
+  olsr_cookie_usage_incr(ci->ci_id);
 
   /* Singleshot or periodical timer ? */
-  if (periodical) {
-    timer->timer_period = rel_time;
-  } else {
-    timer->timer_period = 0;
-  }
+  timer->timer_period = periodical ? rel_time : 0;
 
   /*
    * Now insert in the respective timer_wheel slot.
    */
   list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK], &timer->timer_list);
-  timers_running++;
 
-#ifdef DEBUG
-  OLSR_PRINTF(3, "TIMER: start %s timer %p firing in %s, ctx %p\n", olsr_cookie_name(timer->timer_cookie), timer,
-              olsr_clock_string(timer->timer_clock), context);
-#endif
+  OLSR_PRINTF(7, "TIMER: start %s timer %p firing in %s, ctx %p\n",
+             ci->ci_name, timer, olsr_clock_string(timer->timer_clock), context);
 
   return timer;
 }
@@ -663,24 +801,25 @@ olsr_start_timer(unsigned int rel_time, uint8_t jitter_pct, bool periodical, voi
 void
 olsr_stop_timer(struct timer_entry *timer)
 {
-
-  /* sanity check */
+  /* It's okay to get a NULL here */
   if (!timer) {
     return;
   }
-#ifdef DEBUG
-  OLSR_PRINTF(3, "TIMER: stop %s timer %p, ctx %p\n", olsr_cookie_name(timer->timer_cookie), timer, timer->timer_cb_context);
-#endif
+
+  assert(timer->timer_cookie);     /* we want timer cookies everywhere */
+
+  OLSR_PRINTF(7, "TIMER: stop %s timer %p, ctx %p\n",
+             timer->timer_cookie->ci_name, timer, timer->timer_cb_context);
+
 
   /*
-   * Carve out of the existing wheel_slot and return to the pool
-   * rather than freeing for later reycling.
+   * Carve out of the existing wheel_slot and free.
    */
   list_remove(&timer->timer_list);
-  list_add_before(&free_timer_list, &timer->timer_list);
   timer->timer_flags &= ~OLSR_TIMER_RUNNING;
-  olsr_cookie_usage_decr(timer->timer_cookie);
-  timers_running--;
+  olsr_cookie_usage_decr(timer->timer_cookie->ci_id);
+
+  olsr_cookie_free(timer_mem_cookie, timer);
 }
 
 /**
@@ -694,20 +833,17 @@ olsr_stop_timer(struct timer_entry *timer)
 void
 olsr_change_timer(struct timer_entry *timer, unsigned int rel_time, uint8_t jitter_pct, bool periodical)
 {
-
   /* Sanity check. */
   if (!timer) {
     return;
   }
 
+  assert(timer->timer_cookie);     /* we want timer cookies everywhere */
+
   /* Singleshot or periodical timer ? */
-  if (periodical) {
-    timer->timer_period = rel_time;
-  } else {
-    timer->timer_period = 0;
-  }
+  timer->timer_period = periodical ? rel_time : 0;
 
-  timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
+  timer->timer_clock = calc_jitter(rel_time, jitter_pct, timer->timer_random);
   timer->timer_jitter_pct = jitter_pct;
 
   /*
@@ -717,10 +853,8 @@ olsr_change_timer(struct timer_entry *timer, unsigned int rel_time, uint8_t jitt
   list_remove(&timer->timer_list);
   list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK], &timer->timer_list);
 
-#ifdef DEBUG
-  OLSR_PRINTF(3, "TIMER: change %s timer %p, firing to %s, ctx %p\n", olsr_cookie_name(timer->timer_cookie), timer,
-              olsr_clock_string(timer->timer_clock), timer->timer_cb_context);
-#endif
+  OLSR_PRINTF(7, "TIMER: change %s timer %p, firing to %s, ctx %p\n",
+             timer->timer_cookie->ci_name, timer, olsr_clock_string(timer->timer_clock), timer->timer_cb_context);
 }
 
 /*
@@ -730,9 +864,14 @@ olsr_change_timer(struct timer_entry *timer, unsigned int rel_time, uint8_t jitt
  * terminated.
  */
 void
-olsr_set_timer(struct timer_entry **timer_ptr, unsigned int rel_time, uint8_t jitter_pct, bool periodical,
-               void (*timer_cb_function) (void *), void *context, olsr_cookie_t cookie)
+olsr_set_timer(struct timer_entry **timer_ptr,
+               unsigned int rel_time,
+               uint8_t jitter_pct, bool periodical, timer_cb_func cb_func, void *context, struct olsr_cookie_info *cookie)
 {
+  if (cookie) {
+    cookie = def_timer_ci;
+  }
+
   if (rel_time == 0) {
     /* No good future time provided, kill it. */
     olsr_stop_timer(*timer_ptr);
@@ -740,7 +879,7 @@ olsr_set_timer(struct timer_entry **timer_ptr, unsigned int rel_time, uint8_t ji
   }
   else if ((*timer_ptr) == NULL) {
     /* No timer running, kick it. */
-    *timer_ptr = olsr_start_timer(rel_time, jitter_pct, periodical, timer_cb_function, context, cookie);
+    *timer_ptr = olsr_start_timer(rel_time, jitter_pct, periodical, cb_func, context, cookie);
   }
   else {
     olsr_change_timer(*timer_ptr, rel_time, jitter_pct, periodical);
index b1c248c..eb2d7e2 100644 (file)
@@ -1,8 +1,7 @@
 
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
- * Timer rewrite (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  */
 
+
 #ifndef _OLSR_SCHEDULER
 #define _OLSR_SCHEDULER
 
 #include "common/list.h"
 
-#define TIMER_WHEEL_SLOTS 256
-#define TIMER_WHEEL_MASK (TIMER_WHEEL_SLOTS - 1)
+#include "olsr_types.h"
+
+#include <time.h>
 
 /* Some defs for juggling with timers */
 #define MSEC_PER_SEC 1000
 #define NSEC_PER_USEC 1000
 #define USEC_PER_MSEC 1000
 
+#define TIMER_WHEEL_SLOTS 1024
+#define TIMER_WHEEL_MASK (TIMER_WHEEL_SLOTS - 1)
+
+typedef void (*timer_cb_func) (void *); /* callback function */
+
 /*
  * Our timer implementation is a based on individual timers arranged in
  * a double linked list hanging of hash containers called a timer wheel slot.
  * which causes the timer to run forever until manually stopped.
  */
 struct timer_entry {
-  struct list_node timer_list;         /* memory pooling, or wheel membership */
-  uint32_t timer_clock;                 /* when timer shall fire (absolute time) */
+  struct list_node timer_list;         /* Wheel membership */
+  uint32_t timer_clock;                /* when timer shall fire (absolute time) */
   unsigned int timer_period;           /* set for periodical timers (relative time) */
-  olsr_cookie_t timer_cookie;          /* used for diag stuff */
+  struct olsr_cookie_info *timer_cookie;       /* used for diag stuff */
   uint8_t timer_jitter_pct;            /* the jitter expressed in percent */
   uint8_t timer_flags;                 /* misc flags */
   unsigned int timer_random;           /* cache random() result for performance reasons */
-  void (*timer_cb) (void *);           /* callback function */
+  timer_cb_func timer_cb;              /* callback function */
   void *timer_cb_context;              /* context pointer */
 };
 
@@ -85,28 +91,87 @@ LISTNODE2STRUCT(list2timer, struct timer_entry, timer_list);
 /* Timer flags */
 #define OLSR_TIMER_RUNNING  ( 1 << 0)   /* this timer is running */
 
-/* Memory pooling */
-#define OLSR_TIMER_MEMORY_CHUNK 100     /* timers per chunk */
-
 /* Timers */
 void olsr_init_timers(void);
-void olsr_walk_timers(uint32_t *);
-void olsr_set_timer(struct timer_entry **, unsigned int, uint8_t, bool, void (*)(void *), void *, olsr_cookie_t);
-struct timer_entry *olsr_start_timer(unsigned int, uint8_t, bool, void (*)(void *), void *, olsr_cookie_t);
+void olsr_flush_timers(void);
+void olsr_set_timer (struct timer_entry **, unsigned int, uint8_t, bool, timer_cb_func, void *, struct olsr_cookie_info *);
+struct timer_entry *olsr_start_timer (unsigned int, uint8_t, bool, timer_cb_func, void *, struct olsr_cookie_info *);
 void olsr_change_timer(struct timer_entry *, unsigned int, uint8_t, bool);
-void olsr_stop_timer(struct timer_entry *);
+void olsr_stop_timer (struct timer_entry *);
 
 /* Printing timestamps */
 const char *olsr_clock_string(uint32_t);
 const char *olsr_wallclock_string(void);
 
 /* Main scheduler loop */
-void olsr_scheduler(void) __attribute__ ((noreturn));
+void olsr_scheduler(void);
+
+/*
+ * Provides a timestamp s1 milliseconds in the future
+ */
+#define GET_TIMESTAMP(s1)      olsr_getTimestamp(s1)
+
+/* Compute the time in milliseconds when a timestamp will expire. */
+#define TIME_DUE(s1)    olsr_getTimeDue(s1)
+
+/* Returns TRUE if a timestamp is expired */
+#define TIMED_OUT(s1)    olsr_isTimedOut(s1)
+
+/* Timer data */
+extern uint32_t now_times;     /* current idea of times(2) reported uptime */
+
+
+#define SP_PR_READ             0x01
+#define SP_PR_WRITE            0x02
+
+#define SP_IMM_READ            0x04
+#define SP_IMM_WRITE           0x08
+
+
+typedef void (*socket_handler_func) (int fd, void *data, unsigned int flags);
+
+
+struct olsr_socket_entry {
+  int fd;
+  socket_handler_func process_immediate;
+  socket_handler_func process_pollrate;
+  void *data;
+  unsigned int flags;
+  struct list_node socket_node;
+};
+
+LISTNODE2STRUCT(list2socket, struct olsr_socket_entry, socket_node);
+
+/* deletion safe macro for socket list traversal */
+#define OLSR_FOR_ALL_SOCKETS(socket) \
+{ \
+  struct list_node *_socket_node, *_next_socket_node; \
+  for (_socket_node = socket_head.next; \
+    _socket_node != &socket_head; \
+    _socket_node = _next_socket_node) { \
+    _next_socket_node = _socket_node->next; \
+    socket = list2socket(_socket_node);
+#define OLSR_FOR_ALL_SOCKETS_END(socket) }}
 
 uint32_t olsr_getTimestamp (uint32_t s);
 int32_t olsr_getTimeDue (uint32_t s);
 bool olsr_isTimedOut (uint32_t s);
 
+void add_olsr_socket (int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, void *data, unsigned int flags);
+int remove_olsr_socket (int fd, socket_handler_func pf_pr, socket_handler_func pf_imm);
+void olsr_flush_sockets(void);
+void enable_olsr_socket (int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, unsigned int flags);
+void disable_olsr_socket (int fd, socket_handler_func pf_pr, socket_handler_func pf_imm, unsigned int flags);
+
+/*
+ * a wrapper around times(2). times(2) has the problem, that it may return -1
+ * in case of an err (e.g. EFAULT on the parameter) or immediately before an
+ * overrun (though it is not en error) just because the jiffies (or whatever
+ * the underlying kernel calls the smallest accountable time unit) are
+ * inherently "unsigned" (and always incremented).
+ */
+
+
 #endif
 
 /*
diff --git a/src/socket_parser.c b/src/socket_parser.c
deleted file mode 100644 (file)
index f833bdb..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-
-/*
- * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of olsr.org, olsrd nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Visit http://www.olsr.org for more information.
- *
- * If you find this software useful feel free to make a donation
- * to the project. For more information see the website or contact
- * the copyright holders.
- *
- */
-
-#include <unistd.h>
-#include "socket_parser.h"
-#include "olsr.h"
-#include "defs.h"
-#include "log.h"
-#include "net_os.h"
-
-#ifdef WIN32
-#undef EINTR
-#define EINTR WSAEINTR
-#undef errno
-#define errno WSAGetLastError()
-#undef strerror
-#define strerror(x) StrError(x)
-#endif
-
-struct olsr_socket_entry *olsr_socket_entries;
-
-static int hfd = 0;
-
-/**
- * Add a socket and handler to the socketset
- * beeing used in the main select(2) loop
- * in listen_loop
- *
- *@param fd the socket
- *@param pf the processing function
- */
-void
-add_olsr_socket(int fd, void (*pf) (int fd))
-{
-  struct olsr_socket_entry *new_entry;
-
-  if ((fd == 0) || (pf == NULL)) {
-    fprintf(stderr, "Bogus socket entry - not registering...\n");
-    return;
-  }
-  OLSR_PRINTF(2, "Adding OLSR socket entry %d\n", fd);
-
-  new_entry = olsr_malloc(sizeof(struct olsr_socket_entry), "Socket entry");
-
-  new_entry->fd = fd;
-  new_entry->process_function = pf;
-
-  /* Queue */
-  new_entry->next = olsr_socket_entries;
-  olsr_socket_entries = new_entry;
-
-  if (fd + 1 > hfd)
-    hfd = fd + 1;
-}
-
-/**
- * Remove a socket and handler to the socketset
- * beeing used in the main select(2) loop
- * in listen_loop
- *
- *@param fd the socket
- *@param pf the processing function
- */
-int
-remove_olsr_socket(int fd, void (*pf) (int))
-{
-  struct olsr_socket_entry *entry, *prev_entry;
-
-  if ((fd == 0) || (pf == NULL)) {
-    olsr_syslog(OLSR_LOG_ERR, "Bogus socket entry - not processing...\n");
-    return 0;
-  }
-  OLSR_PRINTF(1, "Removing OLSR socket entry %d\n", fd);
-
-  entry = olsr_socket_entries;
-  prev_entry = NULL;
-
-  while (entry) {
-    if ((entry->fd == fd) && (entry->process_function == pf)) {
-      if (prev_entry == NULL) {
-        olsr_socket_entries = entry->next;
-        free(entry);
-      } else {
-        prev_entry->next = entry->next;
-        free(entry);
-      }
-
-      if (hfd == fd + 1) {
-        /* Re-calculate highest FD */
-        entry = olsr_socket_entries;
-        hfd = 0;
-        while (entry) {
-          if (entry->fd + 1 > hfd)
-            hfd = entry->fd + 1;
-          entry = entry->next;
-        }
-      }
-      return 1;
-    }
-    prev_entry = entry;
-    entry = entry->next;
-  }
-
-  return 0;
-}
-
-void
-olsr_poll_sockets(void)
-{
-  int n;
-  struct olsr_socket_entry *olsr_sockets;
-  fd_set ibits;
-  struct timeval tvp = { 0, 0 };
-
-  /* If there are no registered sockets we
-   * do not call select(2)
-   */
-  if (hfd == 0)
-    return;
-
-  FD_ZERO(&ibits);
-
-  /* Adding file-descriptors to FD set */
-
-  for (olsr_sockets = olsr_socket_entries; olsr_sockets; olsr_sockets = olsr_sockets->next) {
-    /* And we cast here since we get a warning on Win32 */
-    FD_SET((unsigned int)olsr_sockets->fd, &ibits);
-  }
-
-  /* Runnig select on the FD set */
-  n = olsr_select(hfd, &ibits, NULL, NULL, &tvp);
-
-  if (n == 0)
-    return;
-  /* Did somethig go wrong? */
-  if (n < 0) {
-    if (errno != EINTR) {
-      const char *const err_msg = strerror(errno);
-      olsr_syslog(OLSR_LOG_ERR, "select: %s", err_msg);
-      OLSR_PRINTF(1, "Error select: %s", err_msg);
-    }
-    return;
-  }
-
-  /* Update time since this is much used by the parsing functions */
-  now_times = olsr_times();
-
-  for (olsr_sockets = olsr_socket_entries; olsr_sockets; olsr_sockets = olsr_sockets->next) {
-    if (FD_ISSET(olsr_sockets->fd, &ibits))
-      olsr_sockets->process_function(olsr_sockets->fd);
-  }
-}
-
-/*
- * Local Variables:
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/src/socket_parser.h b/src/socket_parser.h
deleted file mode 100644 (file)
index d2e15d4..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/*
- * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of olsr.org, olsrd nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Visit http://www.olsr.org for more information.
- *
- * If you find this software useful feel free to make a donation
- * to the project. For more information see the website or contact
- * the copyright holders.
- *
- */
-
-#ifndef _OLSR_SOCKET_PARSER
-#define _OLSR_SOCKET_PARSER
-
-struct olsr_socket_entry {
-  int fd;
-  int arp_type;
-  void (*process_function) (int fd);
-  struct olsr_socket_entry *next;
-};
-
-extern struct olsr_socket_entry *olsr_socket_entries;
-void olsr_poll_sockets(void);
-
-void add_olsr_socket(int, void (*)(int));
-int remove_olsr_socket(int, void (*)(int));
-void listen_loop(void);
-
-#endif
-
-/*
- * Local Variables:
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * End:
- */
index ee8af8d..2c076a5 100644 (file)
@@ -923,7 +923,7 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
    * Set or change the expiration timer accordingly.
    */
   olsr_set_timer(&tc->validity_timer, vtime, OLSR_TC_VTIME_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_tc_entry, tc,
-                 tc_validity_timer_cookie->ci_id);
+                 tc_validity_timer_cookie);
 
   if (emptyTC && lower_border == 0xff && upper_border == 0xff) {
     /* handle empty TC with border flags 0xff */
@@ -945,7 +945,7 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
      * all edges belonging to a multipart neighbor set will arrive.
      */
     olsr_set_timer(&tc->edge_gc_timer, OLSR_TC_EDGE_GC_TIME, OLSR_TC_EDGE_GC_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_tc_edge_gc,
-                   tc, tc_edge_gc_timer_cookie->ci_id);
+                   tc, tc_edge_gc_timer_cookie);
   }
 
   if (emptyTC && borderSet) {
index cdfb7e5..06c5d51 100644 (file)
@@ -50,7 +50,6 @@
 #include "olsr.h"
 #include "net_os.h"
 #include "net_olsr.h"
-#include "socket_parser.h"
 #include "parser.h"
 #include "scheduler.h"
 #include "generate_msg.h"
@@ -483,7 +482,7 @@ add_hemu_if(struct olsr_if *iface)
   }
 
   /* Register socket */
-  add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu);
+  add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu, NULL, NULL, SP_PR_READ);
 
   /*
    * Register functions for periodic message generation
@@ -491,16 +490,16 @@ add_hemu_if(struct olsr_if *iface)
 
   ifp->hello_gen_timer =
     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
-                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie->ci_id);
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
   ifp->tc_gen_timer =
     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
-                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie->ci_id);
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
   ifp->mid_gen_timer =
     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
-                     mid_gen_timer_cookie->ci_id);
+                     mid_gen_timer_cookie);
   ifp->hna_gen_timer =
     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
-                     hna_gen_timer_cookie->ci_id);
+                     hna_gen_timer_cookie);
 
   /* Recalculate max topology hold time */
   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
@@ -776,9 +775,9 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
   set_buffer_timer(ifp);
 
   /* Register socket */
-  add_olsr_socket(ifp->olsr_socket, &olsr_input);
+  add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
   if (ifp->olsr_socket != ifp->send_socket) {
-    add_olsr_socket(ifp->send_socket, &olsr_input);
+    add_olsr_socket(ifp->send_socket, &olsr_input, NULL, NULL, SP_PR_READ);
   }
 
 #ifdef linux
@@ -815,16 +814,16 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
    */
   ifp->hello_gen_timer =
     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
-                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie->ci_id);
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
   ifp->tc_gen_timer =
     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
-                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie->ci_id);
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
   ifp->mid_gen_timer =
     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
-                     mid_gen_timer_cookie->ci_id);
+                     mid_gen_timer_cookie);
   ifp->hna_gen_timer =
     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
-                     hna_gen_timer_cookie->ci_id);
+                     hna_gen_timer_cookie);
 
   /* Recalculate max topology hold time */
   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval) {