summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-02-06 17:43:40 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2009-02-06 17:43:40 +0100
commitba2f8458ecfa0827e09a1c40c9e29868239fafa1 (patch)
tree1e9446c0b3dd93a570af2a2a9fec678ca14ab05d
parentc3ef4d9b32ca653571f0976f73aaa99218a36db0 (diff)
src: re-work polling strategy
This patch improves the polling support included in 0.9.10. The polling now consists of getting the state table, wait for PollSecs, then purge obsolete entries, and so on. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/conntrackd.h4
-rw-r--r--src/run.c85
-rw-r--r--src/stats-mode.c6
-rw-r--r--src/sync-mode.c28
4 files changed, 83 insertions, 40 deletions
diff --git a/include/conntrackd.h b/include/conntrackd.h
index 3e10a2f..34c7629 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -114,7 +114,11 @@ struct ct_general_state {
struct nfct_handle *dump; /* dump handler */
struct nfct_handle *request; /* request handler */
struct nfct_handle *resync; /* resync handler */
+ struct nfct_handle *get; /* get handler */
+ int get_retval; /* hackish */
+
struct alarm_block resync_alarm;
+ struct alarm_block polling_alarm;
struct fds *fds;
diff --git a/src/run.c b/src/run.c
index 7d48865..81f2590 100644
--- a/src/run.c
+++ b/src/run.c
@@ -1,5 +1,5 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* 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
@@ -40,8 +40,11 @@ void killer(int foo)
/* no signals while handling signals */
sigprocmask(SIG_BLOCK, &STATE(block), NULL);
- if (!(CONFIG(flags) & CTD_POLL))
+ if (!(CONFIG(flags) & CTD_POLL)) {
nfct_close(STATE(event));
+ nfct_close(STATE(resync));
+ }
+ nfct_close(STATE(get));
nfct_close(STATE(request));
if (STATE(us_filter))
@@ -212,10 +215,13 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data)
STATE(stats).nl_kernel_table_resync++;
}
-static void do_poll_resync_alarm(struct alarm_block *a, void *data)
+static void do_polling_alarm(struct alarm_block *a, void *data)
{
- nl_send_resync(STATE(resync));
- add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0);
+ if (STATE(mode)->purge)
+ STATE(mode)->purge();
+
+ nl_send_resync(STATE(dump));
+ add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
}
static int event_handler(enum nf_conntrack_msg_type type,
@@ -272,6 +278,17 @@ static int dump_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int get_handler(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ if (ct_filter_conntrack(ct, 1))
+ return NFCT_CB_CONTINUE;
+
+ STATE(get_retval) = 1;
+ return NFCT_CB_CONTINUE;
+}
+
int
init(void)
{
@@ -316,6 +333,20 @@ init(void)
nfct_callback_register(STATE(event), NFCT_T_ALL,
event_handler, NULL);
register_fd(nfct_fd(STATE(event)), STATE(fds));
+
+ STATE(resync) = nfct_open(CONNTRACK, 0);
+ if (STATE(resync)== NULL) {
+ dlog(LOG_ERR, "can't open netlink handler: %s",
+ strerror(errno));
+ dlog(LOG_ERR, "no ctnetlink kernel support?");
+ return -1;
+ }
+ nfct_callback_register(STATE(resync),
+ NFCT_T_ALL,
+ STATE(mode)->resync,
+ NULL);
+ register_fd(nfct_fd(STATE(resync)), STATE(fds));
+ fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
}
STATE(dump) = nfct_open(CONNTRACK, 0);
@@ -326,25 +357,22 @@ init(void)
return -1;
}
nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL);
+ if (CONFIG(flags) & CTD_POLL)
+ register_fd(nfct_fd(STATE(dump)), STATE(fds));
if (nl_dump_conntrack_table(STATE(dump)) == -1) {
dlog(LOG_ERR, "can't get kernel conntrack table");
return -1;
}
- STATE(resync) = nfct_open(CONNTRACK, 0);
- if (STATE(resync)== NULL) {
+ STATE(get) = nfct_open(CONNTRACK, 0);
+ if (STATE(get) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
dlog(LOG_ERR, "no ctnetlink kernel support?");
return -1;
}
- nfct_callback_register(STATE(resync),
- NFCT_T_ALL,
- STATE(mode)->resync,
- NULL);
- register_fd(nfct_fd(STATE(resync)), STATE(fds));
- fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
+ nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL);
/* no callback, it does not do anything with the output */
STATE(request) = nfct_open(CONNTRACK, 0);
@@ -356,8 +384,8 @@ init(void)
}
if (CONFIG(flags) & CTD_POLL) {
- init_alarm(&STATE(resync_alarm), NULL, do_poll_resync_alarm);
- add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0);
+ init_alarm(&STATE(polling_alarm), NULL, do_polling_alarm);
+ add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
dlog(LOG_NOTICE, "running in polling mode");
} else {
init_alarm(&STATE(resync_alarm), NULL, do_overrun_resync_alarm);
@@ -414,11 +442,11 @@ static void __run(struct timeval *next_alarm)
if (FD_ISSET(STATE(local).fd, &readfds))
do_local_server_step(&STATE(local), NULL, local_handler);
- /* conntrack event has happened */
- if (!(CONFIG(flags) & CTD_POLL) &&
- FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
- ret = nfct_catch(STATE(event));
- if (ret == -1) {
+ if (!(CONFIG(flags) & CTD_POLL)) {
+ /* conntrack event has happened */
+ if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
+ ret = nfct_catch(STATE(event));
+ if (ret == -1) {
switch(errno) {
case ENOBUFS:
/* We have hit ENOBUFS, it's likely that we are
@@ -464,13 +492,18 @@ static void __run(struct timeval *next_alarm)
STATE(stats).nl_catch_event_failed++;
break;
}
+ }
+ }
+ if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
+ nfct_catch(STATE(resync));
+ if (STATE(mode)->purge)
+ STATE(mode)->purge();
+ }
+ } else {
+ /* using polling mode */
+ if (FD_ISSET(nfct_fd(STATE(dump)), &readfds)) {
+ nfct_catch(STATE(dump));
}
- }
-
- if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
- nfct_catch(STATE(resync));
- if (STATE(mode)->purge)
- STATE(mode)->purge();
}
if (STATE(mode)->run)
diff --git a/src/stats-mode.c b/src/stats-mode.c
index 226a6b8..bd20253 100644
--- a/src/stats-mode.c
+++ b/src/stats-mode.c
@@ -123,11 +123,11 @@ static int resync_stats(enum nf_conntrack_msg_type type,
static int purge_step(void *data1, void *data2)
{
- int ret;
struct cache_object *obj = data2;
- ret = nfct_query(STATE(dump), NFCT_Q_GET, obj->ct);
- if (ret == -1 && errno == ENOENT) {
+ STATE(get_retval) = 0;
+ nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */
+ if (!STATE(get_retval)) {
debug_ct(obj->ct, "purge stats");
cache_del(STATE_STATS(cache), obj);
cache_object_free(obj);
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 84a4de0..8174681 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -499,8 +499,15 @@ static int local_handler_sync(int fd, int type, void *data)
return ret;
}
+static void mcast_send_sync(struct cache_object *obj, int query)
+{
+ STATE_SYNC(sync)->enqueue(obj, query);
+}
+
static void dump_sync(struct nf_conntrack *ct)
{
+ struct cache_object *obj;
+
/* This is required by kernels < 2.6.20 */
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
@@ -508,23 +515,22 @@ static void dump_sync(struct nf_conntrack *ct)
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_USE);
- if (cache_update_force(STATE_SYNC(internal), ct))
- debug_ct(ct, "resync");
-}
-
-static void mcast_send_sync(struct cache_object *obj, int query)
-{
- STATE_SYNC(sync)->enqueue(obj, query);
+ obj = cache_update_force(STATE_SYNC(internal), ct);
+ if ((CONFIG(flags) & CTD_POLL)) {
+ if (obj != NULL && obj->status == C_OBJ_NEW) {
+ debug_ct(ct, "poll");
+ mcast_send_sync(obj, NET_T_STATE_NEW);
+ }
+ }
}
static int purge_step(void *data1, void *data2)
{
- int ret;
- struct nfct_handle *h = STATE(dump);
struct cache_object *obj = data2;
- ret = nfct_query(h, NFCT_Q_GET, obj->ct);
- if (ret == -1 && errno == ENOENT) {
+ STATE(get_retval) = 0;
+ nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */
+ if (!STATE(get_retval)) {
debug_ct(obj->ct, "purge resync");
if (obj->status != C_OBJ_DEAD) {
cache_object_set_status(obj, C_OBJ_DEAD);