From 746f7031f4d1e3bccdd6db3c53835d8b85b73c90 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 17 Jan 2009 18:03:53 +0100 Subject: src: add state polling support (oppossed to current event-driven) This patch adds the clause PollSecs that changes the normal behaviour of conntrackd. With PollSecs set to > 0, conntrackd polls every N seconds the entries. This is the opposed behaviour of an event-driven behaviour but may be useful for those that have really strong limitations in terms of CPU consumption and want to perform a relaxed replication. Signed-off-by: Pablo Neira Ayuso --- doc/stats/conntrackd.conf | 12 ++++++++++++ doc/sync/alarm/conntrackd.conf | 12 ++++++++++++ doc/sync/ftfw/conntrackd.conf | 12 ++++++++++++ doc/sync/notrack/conntrackd.conf | 12 ++++++++++++ include/conntrackd.h | 2 ++ src/read_config_lex.l | 1 + src/read_config_yy.y | 13 ++++++++++++- src/run.c | 41 ++++++++++++++++++++++++++++------------ 8 files changed, 92 insertions(+), 13 deletions(-) diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf index 1fc21af..889d387 100644 --- a/doc/stats/conntrackd.conf +++ b/doc/stats/conntrackd.conf @@ -91,6 +91,18 @@ Stats { # LogFile on + # + # By default, the daemon receives state updates following an + # event-driven model. You can modify this behaviour by switching to + # polling mode with the PollSecs clause. This clause tells conntrackd + # to dump the states in the kernel every N seconds. With regards to + # synchronization mode, the polling mode can only guarantee that + # long-lifetime states are recovered. The main advantage of this method + # is the reduction in the state replication at the cost of reducing the + # chances of recovering connections. + # + # PollSecs 15 + # # Enable connection logging via Syslog. Default is off. # Syslog: on, off or a facility name (daemon (default) or local0..7) diff --git a/doc/sync/alarm/conntrackd.conf b/doc/sync/alarm/conntrackd.conf index 528ff8f..3479a83 100644 --- a/doc/sync/alarm/conntrackd.conf +++ b/doc/sync/alarm/conntrackd.conf @@ -183,6 +183,18 @@ General { # SocketBufferSizeMaxGrowth 8388608 + # + # By default, the daemon receives state updates following an + # event-driven model. You can modify this behaviour by switching to + # polling mode with the PollSecs clause. This clause tells conntrackd + # to dump the states in the kernel every N seconds. With regards to + # synchronization mode, the polling mode can only guarantee that + # long-lifetime states are recovered. The main advantage of this method + # is the reduction in the state replication at the cost of reducing the + # chances of recovering connections. + # + # PollSecs 15 + # # The daemon prioritizes the handling of state-change events coming # from the core. With this clause, you can set the maximum number of diff --git a/doc/sync/ftfw/conntrackd.conf b/doc/sync/ftfw/conntrackd.conf index 2e60f2c..77ef76c 100644 --- a/doc/sync/ftfw/conntrackd.conf +++ b/doc/sync/ftfw/conntrackd.conf @@ -191,6 +191,18 @@ General { # SocketBufferSizeMaxGrowth 8388608 + # + # By default, the daemon receives state updates following an + # event-driven model. You can modify this behaviour by switching to + # polling mode with the PollSecs clause. This clause tells conntrackd + # to dump the states in the kernel every N seconds. With regards to + # synchronization mode, the polling mode can only guarantee that + # long-lifetime states are recovered. The main advantage of this method + # is the reduction in the state replication at the cost of reducing the + # chances of recovering connections. + # + # PollSecs 15 + # # The daemon prioritizes the handling of state-change events coming # from the core. With this clause, you can set the maximum number of diff --git a/doc/sync/notrack/conntrackd.conf b/doc/sync/notrack/conntrackd.conf index 7f8c8a3..5abf589 100644 --- a/doc/sync/notrack/conntrackd.conf +++ b/doc/sync/notrack/conntrackd.conf @@ -173,6 +173,18 @@ General { # SocketBufferSizeMaxGrowth 8388608 + # + # By default, the daemon receives state updates following an + # event-driven model. You can modify this behaviour by switching to + # polling mode with the PollSecs clause. This clause tells conntrackd + # to dump the states in the kernel every N seconds. With regards to + # synchronization mode, the polling mode can only guarantee that + # long-lifetime states are recovered. The main advantage of this method + # is the reduction in the state replication at the cost of reducing the + # chances of recovering connections. + # + # PollSecs 15 + # # The daemon prioritizes the handling of state-change events coming # from the core. With this clause, you can set the maximum number of diff --git a/include/conntrackd.h b/include/conntrackd.h index fbf126a..acf907c 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -48,6 +48,7 @@ #define CTD_SYNC_FTFW (1UL << 2) #define CTD_SYNC_ALARM (1UL << 3) #define CTD_SYNC_NOTRACK (1UL << 4) +#define CTD_POLL (1UL << 5) /* FILENAME_MAX is 4096 on my system, perhaps too much? */ #ifndef FILENAME_MAXLEN @@ -85,6 +86,7 @@ struct ct_conf { int family; /* protocol family */ unsigned int resend_queue_size; /* FTFW protocol */ unsigned int window_size; + int poll_kernel_secs; int cache_write_through; int filter_from_kernelspace; int event_iterations_limit; diff --git a/src/read_config_lex.l b/src/read_config_lex.l index e9e5d43..4953974 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -119,6 +119,7 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k] "Kernelspace" { return T_KERNELSPACE; } "EventIterationLimit" { return T_EVENT_ITER_LIMIT; } "Default" { return T_DEFAULT; } +"PollSecs" { return T_POLL_SECS; } {is_on} { return T_ON; } {is_off} { return T_OFF; } diff --git a/src/read_config_yy.y b/src/read_config_yy.y index de6cef3..ce604d9 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -58,7 +58,7 @@ static void __max_mcast_dedicated_links_reached(void); %token T_ESTABLISHED T_SYN_SENT T_SYN_RECV T_FIN_WAIT %token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN %token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE T_DESTROY_TIMEOUT -%token T_MCAST_RCVBUFF T_MCAST_SNDBUFF T_NOTRACK +%token T_MCAST_RCVBUFF T_MCAST_SNDBUFF T_NOTRACK T_POLL_SECS %token T_FILTER T_ADDRESS T_PROTOCOL T_STATE T_ACCEPT T_IGNORE %token T_FROM T_USERSPACE T_KERNELSPACE T_EVENT_ITER_LIMIT T_DEFAULT @@ -715,6 +715,7 @@ general_line: hashsize | netlink_buffer_size_max_grown | family | event_iterations_limit + | poll_secs | filter ; @@ -741,6 +742,16 @@ event_iterations_limit : T_EVENT_ITER_LIMIT T_NUMBER CONFIG(event_iterations_limit) = $2; }; +poll_secs: T_POLL_SECS T_NUMBER +{ + conf.flags |= CTD_POLL; + conf.poll_kernel_secs = $2; + if (conf.poll_kernel_secs == 0) { + fprintf(stderr, "ERROR: `PollSecs' clause must be > 0\n"); + exit(EXIT_FAILURE); + } +}; + filter : T_FILTER '{' filter_list '}' { CONFIG(filter_from_kernelspace) = 0; diff --git a/src/run.c b/src/run.c index a6dfe15..a483ab3 100644 --- a/src/run.c +++ b/src/run.c @@ -39,7 +39,8 @@ void killer(int foo) /* no signals while handling signals */ sigprocmask(SIG_BLOCK, &STATE(block), NULL); - nfct_close(STATE(event)); + if (!(CONFIG(flags) & CTD_POLL)) + nfct_close(STATE(event)); nfct_close(STATE(request)); if (STATE(us_filter)) @@ -204,12 +205,18 @@ void local_handler(int fd, void *data) STATE(stats).local_unknown_request++; } -static void do_resync_alarm(struct alarm_block *a, void *data) +static void do_overrun_resync_alarm(struct alarm_block *a, void *data) { nl_send_resync(STATE(resync)); STATE(stats).nl_kernel_table_resync++; } +static void do_poll_resync_alarm(struct alarm_block *a, void *data) +{ + nl_send_resync(STATE(resync)); + add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0); +} + static int event_handler(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) @@ -297,15 +304,18 @@ init(void) } register_fd(STATE(local).fd, STATE(fds)); - STATE(event) = nl_init_event_handler(); - if (STATE(event) == NULL) { - dlog(LOG_ERR, "can't open netlink handler: %s", - strerror(errno)); - dlog(LOG_ERR, "no ctnetlink kernel support?"); - return -1; + if (!(CONFIG(flags) & CTD_POLL)) { + STATE(event) = nl_init_event_handler(); + if (STATE(event) == 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(event), NFCT_T_ALL, + event_handler, NULL); + register_fd(nfct_fd(STATE(event)), STATE(fds)); } - nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); - register_fd(nfct_fd(STATE(event)), STATE(fds)); STATE(dump) = nl_init_dump_handler(); if (STATE(dump) == NULL) { @@ -343,7 +353,13 @@ init(void) return -1; } - init_alarm(&STATE(resync_alarm), NULL, do_resync_alarm); + 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); + dlog(LOG_NOTICE, "running in polling mode"); + } else { + init_alarm(&STATE(resync_alarm), NULL, do_overrun_resync_alarm); + } /* Signals handling */ sigemptyset(&STATE(block)); @@ -397,7 +413,8 @@ static void __run(struct timeval *next_alarm) do_local_server_step(&STATE(local), NULL, local_handler); /* conntrack event has happened */ - if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) { + if (!(CONFIG(flags) & CTD_POLL) && + FD_ISSET(nfct_fd(STATE(event)), &readfds)) { ret = nfct_catch(STATE(event)); if (ret == -1) { switch(errno) { -- cgit v1.2.3