Add timeout queues
This commit is contained in:
parent
8e810f5fd8
commit
bc9f976d7f
6 changed files with 162 additions and 33 deletions
|
@ -5,6 +5,7 @@ add_executable(ffd
|
||||||
ffd.c
|
ffd.c
|
||||||
neigh.c
|
neigh.c
|
||||||
netif.c
|
netif.c
|
||||||
|
queue.c
|
||||||
send.c
|
send.c
|
||||||
tlv.c
|
tlv.c
|
||||||
util.c
|
util.c
|
||||||
|
|
74
ffd/ffd.c
74
ffd/ffd.c
|
@ -28,6 +28,7 @@
|
||||||
#include "neigh.h"
|
#include "neigh.h"
|
||||||
#include "netif.h"
|
#include "netif.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
#include "queue.h"
|
||||||
#include "tlv.h"
|
#include "tlv.h"
|
||||||
#include "tlv_types.h"
|
#include "tlv_types.h"
|
||||||
|
|
||||||
|
@ -51,10 +52,10 @@ static char *mesh = "bat0";
|
||||||
int sockfd;
|
int sockfd;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
|
|
||||||
|
static ffd_queue_head *tasks;
|
||||||
|
|
||||||
ffd_node_id_t self;
|
ffd_node_id_t self;
|
||||||
|
|
||||||
ffd_iface_t *iface_list = NULL;
|
ffd_iface_t *iface_list = NULL;
|
||||||
|
|
||||||
ffd_announce_t *announce_list = NULL;
|
ffd_announce_t *announce_list = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -489,6 +490,8 @@ static void receive_packet(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_updates(void) {
|
static void send_updates(void) {
|
||||||
|
fprintf(stderr, "debug: sending periodic updates.\n");
|
||||||
|
|
||||||
ffd_iface_t *iface;
|
ffd_iface_t *iface;
|
||||||
for (iface = iface_list; iface; iface = iface->next) {
|
for (iface = iface_list; iface; iface = iface->next) {
|
||||||
ffd_send_update(iface, NULL, NULL, false);
|
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() {
|
int main() {
|
||||||
if (!check_config())
|
if (!check_config())
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -569,44 +602,21 @@ int main() {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
update_time();
|
update_time();
|
||||||
|
register_periodic_tasks();
|
||||||
struct timespec next_hello = now;
|
|
||||||
struct timespec next_update = now;
|
|
||||||
struct timespec next_maintenance = now;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int maintenance_timeout = timespec_diff(&next_maintenance, &now);
|
ffd_queue_run(&tasks);
|
||||||
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;
|
|
||||||
|
|
||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
|
|
||||||
|
int timeout = 10*ffd_queue_timeout(&tasks);
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = -1;
|
||||||
|
|
||||||
fds[0].fd = sockfd;
|
fds[0].fd = sockfd;
|
||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
|
|
||||||
poll(fds, 1, 10*timeout);
|
poll(fds, 1, timeout);
|
||||||
|
|
||||||
update_time();
|
update_time();
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,6 @@ extern ffd_iface_t *iface_list;
|
||||||
extern ffd_announce_t *announce_list;
|
extern ffd_announce_t *announce_list;
|
||||||
|
|
||||||
extern int sockfd;
|
extern int sockfd;
|
||||||
extern struct timespec now;
|
|
||||||
|
|
||||||
|
|
||||||
#define FFD_NODE_ID_UNSPEC ((ffd_node_id_t){})
|
#define FFD_NODE_ID_UNSPEC ((ffd_node_id_t){})
|
||||||
|
|
42
ffd/queue.c
Normal file
42
ffd/queue.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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;
|
||||||
|
}
|
69
ffd/queue.h
Normal file
69
ffd/queue.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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_ */
|
|
@ -34,6 +34,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern struct timespec now;
|
||||||
|
|
||||||
|
|
||||||
bool file_readv(const char *file, const char *format, va_list ap);
|
bool file_readv(const char *file, const char *format, va_list ap);
|
||||||
void random_bytes(void *buffer, size_t len);
|
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]);
|
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 */
|
/* returns (tp1 - tp2) in centiseconds */
|
||||||
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
|
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;
|
return ((tp1->tv_sec - tp2->tv_sec))*100 + (tp1->tv_nsec - tp2->tv_nsec)/1e7;
|
||||||
|
|
Reference in a new issue