From bc9f976d7fe70176aac4bc9c87205d6ac1f530cc Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 13 Oct 2012 20:01:48 +0200 Subject: Add timeout queues --- ffd/CMakeLists.txt | 1 + ffd/ffd.c | 74 +++++++++++++++++++++++++++++++----------------------- ffd/ffd.h | 1 - ffd/queue.c | 42 +++++++++++++++++++++++++++++++ ffd/queue.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ ffd/util.h | 8 ++++++ 6 files changed, 162 insertions(+), 33 deletions(-) create mode 100644 ffd/queue.c create mode 100644 ffd/queue.h diff --git a/ffd/CMakeLists.txt b/ffd/CMakeLists.txt index 1571580..432ac61 100644 --- a/ffd/CMakeLists.txt +++ b/ffd/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(ffd ffd.c neigh.c netif.c + queue.c send.c tlv.c util.c diff --git a/ffd/ffd.c b/ffd/ffd.c index 7af9b29..9351476 100644 --- a/ffd/ffd.c +++ b/ffd/ffd.c @@ -28,6 +28,7 @@ #include "neigh.h" #include "netif.h" #include "packet.h" +#include "queue.h" #include "tlv.h" #include "tlv_types.h" @@ -51,10 +52,10 @@ static char *mesh = "bat0"; int sockfd; struct timespec now; -ffd_node_id_t self; +static ffd_queue_head *tasks; +ffd_node_id_t self; ffd_iface_t *iface_list = NULL; - ffd_announce_t *announce_list = NULL; @@ -489,6 +490,8 @@ static void receive_packet(void) { } static void send_updates(void) { + fprintf(stderr, "debug: sending periodic updates.\n"); + ffd_iface_t *iface; for (iface = iface_list; iface; iface = iface->next) { ffd_send_update(iface, NULL, NULL, false); @@ -558,6 +561,36 @@ static void maintenance(void) { } } + +typedef struct _periodic_task_info { + void (*handle)(void); + unsigned delay; + unsigned interval; +} periodic_task_info; + + +static const periodic_task_info periodic_tasks [] = { + {maintenance, 0, FFD_MAINTENANCE_INTERVAL}, + {ffd_send_hellos, FFD_HELLO_INTERVAL, FFD_HELLO_INTERVAL}, + {send_updates, 1, FFD_UPDATE_INTERVAL}, + {NULL} +}; + + +static void handle_periodic_task(const struct timespec *timeout, void *arg) { + const periodic_task_info *info = arg; + + info->handle(); + ffd_queue_put_delayed(&tasks, handle_periodic_task, timeout, info->interval, arg); +} + +static void register_periodic_tasks(void) { + const periodic_task_info *info; + for (info = periodic_tasks; info->handle; info++) + ffd_queue_put_delayed(&tasks, handle_periodic_task, &now, info->delay, (void*)info); +} + + int main() { if (!check_config()) return 1; @@ -569,44 +602,21 @@ int main() { return 1; update_time(); - - struct timespec next_hello = now; - struct timespec next_update = now; - struct timespec next_maintenance = now; + register_periodic_tasks(); while (true) { - int maintenance_timeout = timespec_diff(&next_maintenance, &now); - if (maintenance_timeout <= 0) { - maintenance(); - - add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL); - } - - int hello_timeout = timespec_diff(&next_hello, &now); - if (hello_timeout <= 0) { - ffd_send_hellos(); - - add_interval(&next_hello, FFD_HELLO_INTERVAL); - } - - int update_timeout = timespec_diff(&next_update, &now); - if (update_timeout <= 0) { - fprintf(stderr, "Sending periodic update.\n"); - send_updates(); - - add_interval(&next_update, FFD_UPDATE_INTERVAL); - } - - int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout); - if (timeout <= 0) - continue; + ffd_queue_run(&tasks); struct pollfd fds[1]; + int timeout = 10*ffd_queue_timeout(&tasks); + if (timeout < 0) + timeout = -1; + fds[0].fd = sockfd; fds[0].events = POLLIN; - poll(fds, 1, 10*timeout); + poll(fds, 1, timeout); update_time(); diff --git a/ffd/ffd.h b/ffd/ffd.h index bf00984..edba710 100644 --- a/ffd/ffd.h +++ b/ffd/ffd.h @@ -145,7 +145,6 @@ extern ffd_iface_t *iface_list; extern ffd_announce_t *announce_list; extern int sockfd; -extern struct timespec now; #define FFD_NODE_ID_UNSPEC ((ffd_node_id_t){}) diff --git a/ffd/queue.c b/ffd/queue.c new file mode 100644 index 0000000..3729e50 --- /dev/null +++ b/ffd/queue.c @@ -0,0 +1,42 @@ +/* + Copyright (c) 2012, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. 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. + + 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 HOLDER 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. +*/ + + +#include "queue.h" + + +void ffd_queue_put(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg) { + while (*queue && timespec_after(timeout, &(*queue)->timeout)) + queue = &(*queue)->next; + + ffd_queue_head *entry = malloc(sizeof(ffd_queue_head)); + + entry->cb = cb; + entry->timeout = *timeout; + entry->arg = arg; + + entry->next = *queue; + *queue = entry; +} diff --git a/ffd/queue.h b/ffd/queue.h new file mode 100644 index 0000000..9fae53d --- /dev/null +++ b/ffd/queue.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2012, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. 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. + + 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 HOLDER 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. +*/ + + +#ifndef _FFD_QUEUE_H_ +#define _FFD_QUEUE_H_ + +#include "util.h" + + +typedef void (*ffd_queue_cb)(const struct timespec *timeout, void *arg); + +typedef struct _ffd_queue_head { + struct _ffd_queue_head *next; + ffd_queue_cb cb; + struct timespec timeout; + void *arg; +} ffd_queue_head; + + +void ffd_queue_put(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg); + + +static inline void ffd_queue_put_delayed(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, int delay, void *arg) { + struct timespec timeout_delayed = *timeout; + add_interval(&timeout_delayed, delay); + ffd_queue_put(queue, cb, &timeout_delayed, arg); +} + +static inline void ffd_queue_run(ffd_queue_head **queue) { + while (*queue && timespec_after(&now, &(*queue)->timeout)) { + ffd_queue_head *entry = *queue; + *queue = (*queue)->next; + + entry->cb(&entry->timeout, entry->arg); + free(entry); + } +} + +static inline int ffd_queue_timeout(ffd_queue_head *const *queue) { + if (!*queue) + return -1; + + return max(timespec_diff(&(*queue)->timeout, &now), 0); +} + +#endif /* _FFD_QUEUE_H_ */ diff --git a/ffd/util.h b/ffd/util.h index 9d481cb..0660b94 100644 --- a/ffd/util.h +++ b/ffd/util.h @@ -34,6 +34,9 @@ #include +extern struct timespec now; + + bool file_readv(const char *file, const char *format, va_list ap); void random_bytes(void *buffer, size_t len); @@ -53,6 +56,11 @@ static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_add return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]); } +static inline bool timespec_after(const struct timespec *tp1, const struct timespec *tp2) { + return (tp1->tv_sec > tp2->tv_sec || + (tp1->tv_sec == tp2->tv_sec && tp1->tv_nsec > tp2->tv_nsec)); +} + /* returns (tp1 - tp2) in centiseconds */ static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) { return ((tp1->tv_sec - tp2->tv_sec))*100 + (tp1->tv_nsec - tp2->tv_nsec)/1e7; -- cgit v1.2.3