From 920b90f2b03c60b6940e83cdce8c4b4bfbbc4268 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Wed, 9 Jan 2008 22:52:31 +0000 Subject: wake up the daemon iff there are real events to handle instead of polling (Based on comments from Max Kellerman) --- ChangeLog | 1 + include/Makefile.am | 2 +- include/alarm.h | 2 +- include/conntrackd.h | 2 +- include/sync.h | 2 +- include/timer.h | 17 ------------ src/Makefile.am | 1 - src/alarm.c | 74 ++++++++++++++++++++++----------------------------- src/cache_timer.c | 8 ++++-- src/main.c | 2 +- src/run.c | 47 +++++++++++--------------------- src/sync-alarm.c | 14 +++++++--- src/sync-ftfw.c | 60 +++++++++++++++++++++-------------------- src/sync-mode.c | 4 +-- src/timer.c | 75 ---------------------------------------------------- 15 files changed, 103 insertions(+), 208 deletions(-) delete mode 100644 include/timer.h delete mode 100644 src/timer.c diff --git a/ChangeLog b/ChangeLog index 6d0bdc0..8634c1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,6 +33,7 @@ o obsolete `-S' option: Use information provided by the config file o daemonize conntrackd after initialization o rename class `buffer' to `queue' which is what it really implements o fix logfiles permissions, do not default to umask +o wake up the daemon iff there are real events to handle instead of polling version 0.9.5 (2007/07/29) ------------------------------ diff --git a/include/Makefile.am b/include/Makefile.am index 7eaca35..4322f26 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,5 +2,5 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h \ sync.h conntrackd.h local.h us-conntrack.h \ debug.h log.h hash.h mcast.h buffer.h conntrack.h \ - state_helper.h network.h ignore.h timer.h queue.h + state_helper.h network.h ignore.h queue.h diff --git a/include/alarm.h b/include/alarm.h index 93e6482..82a1612 100644 --- a/include/alarm.h +++ b/include/alarm.h @@ -5,7 +5,7 @@ struct alarm_list { struct list_head head; - unsigned long expires; + struct timeval tv; void *data; void (*function)(struct alarm_list *a, void *data); }; diff --git a/include/conntrackd.h b/include/conntrackd.h index 3bfcf18..e8b90cc 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -159,7 +159,7 @@ extern struct ct_general_state st; struct ct_mode { int (*init)(void); int (*add_fds_to_set)(fd_set *readfds); - void (*run)(fd_set *readfds, int step); + void (*run)(fd_set *readfds); int (*local)(int fd, int type, void *data); void (*kill)(void); void (*dump)(struct nf_conntrack *ct); diff --git a/include/sync.h b/include/sync.h index a27fb93..e6ce327 100644 --- a/include/sync.h +++ b/include/sync.h @@ -15,7 +15,7 @@ struct sync_mode { int (*local)(int fd, int type, void *data); int (*recv)(const struct nethdr *net); void (*send)(struct nethdr *net, struct us_conntrack *u); - void (*run)(int step); + void (*run)(void); }; extern struct sync_mode alarm; diff --git a/include/timer.h b/include/timer.h deleted file mode 100644 index 37b0fc9..0000000 --- a/include/timer.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ - -#include - -struct timer { - long credits; - struct timeval start; - struct timeval stop; - struct timeval diff; -}; - -#define GET_CREDITS(x) x.credits -#define GET_STARTTIME(x) x.start -#define GET_STOPTIME(x) x.stop - -#endif diff --git a/src/Makefile.am b/src/Makefile.am index a7e82cf..c2e684a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,6 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c buffer.c \ traffic_stats.c stats-mode.c \ network.c \ state_helper.c state_helper_tcp.c \ - timer.c \ build.c parse.c \ read_config_yy.y read_config_lex.l diff --git a/src/alarm.c b/src/alarm.c index b4db167..e1d2e24 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -18,6 +18,7 @@ #include #include +#include #include "linux_list.h" #include "conntrackd.h" #include "alarm.h" @@ -25,23 +26,16 @@ #include #include -/* alarm cascade */ -#define ALARM_CASCADE_SIZE STEPS_PER_SECONDS -static struct list_head *alarm_cascade; +static LIST_HEAD(alarm_list); -struct alarm_list *create_alarm() -{ - return (struct alarm_list *) malloc(sizeof(struct alarm_list)); -} - -void destroy_alarm(struct alarm_list *t) +void set_alarm_expiration_secs(struct alarm_list *t, unsigned long expires) { - free(t); + t->tv.tv_sec = expires; } -void set_alarm_expiration(struct alarm_list *t, unsigned long expires) +void set_alarm_expiration_usecs(struct alarm_list *t, unsigned long expires) { - t->expires = expires; + t->tv.tv_usec = expires; } void set_alarm_function(struct alarm_list *t, @@ -59,16 +53,18 @@ void init_alarm(struct alarm_list *t) { INIT_LIST_HEAD(&t->head); - t->expires = 0; + timerclear(&t->tv); t->data = 0; t->function = NULL; } void add_alarm(struct alarm_list *alarm) { - unsigned int pos = jhash(alarm, sizeof(alarm), 0) % ALARM_CASCADE_SIZE; + struct timeval tv; - list_add(&alarm->head, &alarm_cascade[pos]); + gettimeofday(&tv, NULL); + alarm->tv.tv_sec += tv.tv_sec; + list_add_tail(&alarm->head, &alarm_list); } void del_alarm(struct alarm_list *alarm) @@ -76,41 +72,35 @@ void del_alarm(struct alarm_list *alarm) list_del(&alarm->head); } -int mod_alarm(struct alarm_list *alarm, unsigned long expires) +void mod_alarm(struct alarm_list *alarm, unsigned long sc, unsigned long usc) { - alarm->expires = expires; - return 0; + struct timeval tv; + + list_del(&alarm->head); + INIT_LIST_HEAD(&alarm->head); + gettimeofday(&tv, NULL); + alarm->tv.tv_sec = tv.tv_sec + sc; + alarm->tv.tv_usec = tv.tv_usec + usc; + list_add_tail(&alarm->head, &alarm_list); } -void do_alarm_run(int step) +void do_alarm_run(struct timeval *next_alarm) { struct list_head *i, *tmp; struct alarm_list *t; + struct timeval tv; - list_for_each_safe(i, tmp, &alarm_cascade[step]) { - t = (struct alarm_list *) i; - - t->expires--; - if (t->expires == 0) - t->function(t, t->data); - } -} + gettimeofday(&tv, NULL); -int init_alarm_scheduler() -{ - int i; - - alarm_cascade = malloc(sizeof(struct list_head) * ALARM_CASCADE_SIZE); - if (alarm_cascade == NULL) - return -1; + list_for_each_safe(i, tmp, &alarm_list) { + t = (struct alarm_list *) i; - for (i=0; itv, &tv, >)) { + timersub(&t->tv, &tv, next_alarm); + break; + } - return 0; -} - -void destroy_alarm_scheduler() -{ - free(alarm_cascade); + del_alarm(t); + t->function(t, t->data); + } } diff --git a/src/cache_timer.c b/src/cache_timer.c index f3940f3..c0075f5 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -17,6 +17,7 @@ */ #include +#include #include "conntrackd.h" #include "us-conntrack.h" #include "cache.h" @@ -35,7 +36,7 @@ static void timer_add(struct us_conntrack *u, void *data) struct alarm_list *alarm = data; init_alarm(alarm); - set_alarm_expiration(alarm, CONFIG(cache_timeout)); + set_alarm_expiration_secs(alarm, CONFIG(cache_timeout)); set_alarm_data(alarm, u); set_alarm_function(alarm, timeout); add_alarm(alarm); @@ -55,12 +56,15 @@ static void timer_destroy(struct us_conntrack *u, void *data) static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) { + struct timeval tv, tmp; struct alarm_list *alarm = data; if (type == NFCT_O_XML) return 0; - return sprintf(buf, " [expires in %ds]", alarm->expires); + gettimeofday(&tv, NULL); + timersub(&tv, &alarm->tv, &tmp); + return sprintf(buf, " [expires in %ds]", tmp.tv_sec); } struct cache_feature timer_feature = { diff --git a/src/main.c b/src/main.c index 33235e9..19d999a 100644 --- a/src/main.c +++ b/src/main.c @@ -246,7 +246,7 @@ int main(int argc, char *argv[]) /* * Setting up logging */ - if (config_set && init_log() == -1) + if (init_log() == -1) exit(EXIT_FAILURE); if (type == REQUEST) { diff --git a/src/run.c b/src/run.c index 609b454..3dc8ecc 100644 --- a/src/run.c +++ b/src/run.c @@ -25,7 +25,6 @@ #include #include #include -#include "timer.h" void killer(int foo) { @@ -38,7 +37,6 @@ void killer(int foo) ignore_pool_destroy(STATE(ignore_pool)); local_server_destroy(STATE(local)); STATE(mode)->kill(); - destroy_alarm_scheduler(); unlink(CONFIG(lockfile)); dlog(STATE(log), LOG_NOTICE, "---- shutdown received ----"); close_log(); @@ -103,11 +101,6 @@ int init(void) return -1; } - if (init_alarm_scheduler() == -1) { - dlog(STATE(log), LOG_ERR, "can't initialize alarm scheduler"); - return -1; - } - /* local UNIX socket */ STATE(local) = local_server_create(&CONFIG(local)); if (!STATE(local)) { @@ -151,14 +144,10 @@ int init(void) return 0; } -static void __run(long credit, int step) +static int __run(struct timeval *next_alarm) { int max, ret; fd_set readfds; - struct timeval tv = { - .tv_sec = 0, - .tv_usec = credit, - }; FD_ZERO(&readfds); FD_SET(STATE(local), &readfds); @@ -169,7 +158,7 @@ static void __run(long credit, int step) if (STATE(mode)->add_fds_to_set) max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); - ret = select(max+1, &readfds, NULL, NULL, &tv); + ret = select(max+1, &readfds, NULL, NULL, next_alarm); if (ret == -1) { /* interrupted syscall, retry */ if (errno == EINTR) @@ -180,6 +169,10 @@ static void __run(long credit, int step) return; } + /* timeout expired, run the alarm list */ + if (ret == 0) + return 1; + /* signals are racy */ sigprocmask(SIG_BLOCK, &STATE(block), NULL); @@ -221,35 +214,25 @@ static void __run(long credit, int step) } if (STATE(mode)->run) - STATE(mode)->run(&readfds, step); + STATE(mode)->run(&readfds); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); + + return 0; } void run(void) { - int step = 0; - struct timer timer; - - timer_init(&timer); + struct timeval next_alarm = { + .tv_sec = 1, + .tv_usec = 0 + }; while(1) { - timer_start(&timer); - __run(GET_CREDITS(timer), step); - timer_stop(&timer); - - if (timer_adjust_credit(&timer)) { - timer_start(&timer); + if (__run(&next_alarm)) { sigprocmask(SIG_BLOCK, &STATE(block), NULL); - do_alarm_run(step); + do_alarm_run(&next_alarm); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); - timer_stop(&timer); - - if (timer_adjust_credit(&timer)) - dlog(STATE(log), LOG_WARNING, - "alarm run takes too long!"); - - step = (step + 1) < STEPS_PER_SECONDS ? step + 1 : 0; } } } diff --git a/src/sync-alarm.c b/src/sync-alarm.c index a0791ac..632eff2 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -30,7 +30,14 @@ static void refresher(struct alarm_list *a, void *data) debug_ct(u->ct, "persistence update"); - a->expires = random() % CONFIG(refresh) + 1; + init_alarm(a); + set_alarm_expiration_secs(a, random() % CONFIG(refresh) + 1); + set_alarm_expiration_usecs(a, random() % 999999 + 1); + + set_alarm_data(a, u); + set_alarm_function(a, refresher); + add_alarm(a); + net = BUILD_NETMSG(u->ct, NFCT_Q_UPDATE); len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); @@ -41,7 +48,8 @@ static void cache_alarm_add(struct us_conntrack *u, void *data) struct alarm_list *alarm = data; init_alarm(alarm); - set_alarm_expiration(alarm, (random() % conf.refresh) + 1); + set_alarm_expiration_secs(alarm, random() % CONFIG(refresh) + 1); + set_alarm_expiration_usecs(alarm, random() % 999999 + 1); set_alarm_data(alarm, u); set_alarm_function(alarm, refresher); add_alarm(alarm); @@ -50,7 +58,7 @@ static void cache_alarm_add(struct us_conntrack *u, void *data) static void cache_alarm_update(struct us_conntrack *u, void *data) { struct alarm_list *alarm = data; - mod_alarm(alarm, (random() % conf.refresh) + 1); + mod_alarm(alarm, random() % CONFIG(refresh) + 1, random() % 999999 + 1); } static void cache_alarm_destroy(struct us_conntrack *u, void *data) diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index c3b9f61..ac1b8b6 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -70,6 +70,29 @@ static struct cache_extra cache_ftfw_extra = { .destroy = cache_ftfw_del }; +static void tx_queue_add_ctlmsg(u_int32_t flags, u_int32_t from, u_int32_t to) +{ + struct nethdr_ack ack = { + .flags = flags, + .from = from, + .to = to, + }; + + queue_add(tx_queue, &ack, NETHDR_ACK_SIZ); +} + +static struct alarm_list alive_alarm; + +static void do_alive_alarm(struct alarm_list *a, void *data) +{ + tx_queue_add_ctlmsg(NET_F_ALIVE, 0, 0); + + init_alarm(&alive_alarm); + set_alarm_expiration_secs(&alive_alarm, 1); + set_alarm_function(&alive_alarm, do_alive_alarm); + add_alarm(&alive_alarm); +} + static int ftfw_init() { tx_queue = queue_create(CONFIG(resend_queue_size)); @@ -87,6 +110,12 @@ static int ftfw_init() INIT_LIST_HEAD(&tx_list); INIT_LIST_HEAD(&rs_list); + /* XXX: alive message expiration configurable */ + init_alarm(&alive_alarm); + set_alarm_expiration_secs(&alive_alarm, 1); + set_alarm_function(&alive_alarm, do_alive_alarm); + add_alarm(&alive_alarm); + return 0; } @@ -96,17 +125,6 @@ static void ftfw_kill() queue_destroy(tx_queue); } -static void tx_queue_add_ctlmsg(u_int32_t flags, u_int32_t from, u_int32_t to) -{ - struct nethdr_ack ack = { - .flags = flags, - .from = from, - .to = to, - }; - - queue_add(tx_queue, &ack, NETHDR_ACK_SIZ); -} - static int do_cache_to_tx(void *data1, void *data2) { struct us_conntrack *u = data2; @@ -317,15 +335,7 @@ static int tx_list_xmit(struct list_head *i, struct us_conntrack *u) return ret; } -static struct alarm_list alive_alarm; - -static void do_alive_alarm(struct alarm_list *a, void *data) -{ - del_alarm(a); - tx_queue_add_ctlmsg(NET_F_ALIVE, 0, 0); -} - -static void ftfw_run(int step) +static void ftfw_run() { struct list_head *i, *tmp; @@ -342,15 +352,7 @@ static void ftfw_run(int step) tx_list_xmit(i, u); } - if (alive_alarm.expires > 0) - mod_alarm(&alive_alarm, 1); - else { - init_alarm(&alive_alarm); - /* XXX: alive message expiration configurable */ - set_alarm_expiration(&alive_alarm, 1); - set_alarm_function(&alive_alarm, do_alive_alarm); - add_alarm(&alive_alarm); - } + mod_alarm(&alive_alarm, 1, 0); } struct sync_mode ftfw = { diff --git a/src/sync-mode.c b/src/sync-mode.c index a90e529..3bd6f59 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -198,14 +198,14 @@ static int add_fds_to_set_sync(fd_set *readfds) return STATE_SYNC(mcast_server->fd); } -static void run_sync(fd_set *readfds, int step) +static void run_sync(fd_set *readfds) { /* multicast packet has been received */ if (FD_ISSET(STATE_SYNC(mcast_server->fd), readfds)) mcast_handler(); if (STATE_SYNC(sync)->run) - STATE_SYNC(sync)->run(step); + STATE_SYNC(sync)->run(); /* flush pending messages */ mcast_buffered_pending_netmsg(STATE_SYNC(mcast_client)); diff --git a/src/timer.c b/src/timer.c deleted file mode 100644 index b85c286..0000000 --- a/src/timer.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * (C) 2006-2007 by Pablo Neira Ayuso - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include "conntrackd.h" -#include "timer.h" - -#define TIMESLICE_CREDIT (1000000 / STEPS_PER_SECONDS) /* 200 ms timeslice */ - -void timer_init(struct timer *timer) -{ - memset(timer, 0, sizeof(struct timer)); - timer->credits = TIMESLICE_CREDIT; -} - -void timer_start(struct timer *timer) -{ - gettimeofday(&timer->start, NULL); -} - -static int timeval_subtract(struct timeval *diff, - struct timeval *start, - struct timeval *stop) -{ - diff->tv_sec = stop->tv_sec - start->tv_sec; - diff->tv_usec = stop->tv_usec - start->tv_usec; - - if (diff->tv_usec < 0) { - diff->tv_usec += 1000000; - diff->tv_sec--; - } - - /* Return 1 if result is negative. */ - return diff->tv_sec < 0; -} - -void timer_stop(struct timer *timer) -{ - gettimeofday(&timer->stop, NULL); - timeval_subtract(&timer->diff, &timer->start, &timer->stop); -} - -int timer_adjust_credit(struct timer *timer) -{ - if (timer->diff.tv_sec != 0) { - timer->credits = TIMESLICE_CREDIT; - return 1; - } - - timer->credits -= timer->diff.tv_usec; - - if (timer->credits < 0) { - timer->credits += TIMESLICE_CREDIT; - if (timer->credits < 0) - timer->credits = TIMESLICE_CREDIT; - return 1; - } - return 0; -} -- cgit v1.2.3