From 1102a95296e39f671efe51bb6bd9b30e5c14c91e Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 5 Jan 2008 16:41:15 +0000 Subject: implement buffered connection logging to improve performance --- src/Makefile.am | 2 +- src/buffer.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/log.c | 28 ++++++++++++++++++--- src/read_config_lex.l | 1 + src/read_config_yy.y | 8 +++++- src/stats-mode.c | 12 ++++++++- 6 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 src/buffer.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 62a7467..a7e82cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ conntrack_SOURCES = conntrack.c conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_icmp.la conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ -conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c \ +conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c buffer.c \ local.c log.c mcast.c netlink.c \ ignore_pool.c \ cache.c cache_iterators.c \ diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..3283c15 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,67 @@ +/* + * (C) 2006-2008 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 "buffer.h" + +struct buffer *buffer_create(unsigned int size) +{ + struct buffer *b; + + b = malloc(sizeof(struct buffer)); + if (b == NULL) + return NULL; + memset(b, 0, sizeof(struct buffer)); + + b->size = size; + + b->data = malloc(size); + if (b->data == NULL) { + free(b); + return NULL; + } + memset(b->data, 0, size); + + return b; +} + +int buffer_add(struct buffer *b, void *data, unsigned int size) +{ + if (b->size - b->cur_size < size) { + errno = ENOSPC; + return -1; + } + + memcpy(b->data + b->cur_size, data, size); + b->cur_size += size; +} + +void buffer_flush(struct buffer *b, + void (*cb)(void *buffer_data, void *data), + void *data) +{ + cb(b->data, data); + b->cur_size = 0; + memset(b->data, 0, b->size); +} + +unsigned int buffer_size(struct buffer *b) +{ + return b->size; +} diff --git a/src/log.c b/src/log.c index a4d51ec..3e3dd12 100644 --- a/src/log.c +++ b/src/log.c @@ -22,6 +22,7 @@ #include #include #include +#include "buffer.h" #include "conntrackd.h" int init_log(void) @@ -94,7 +95,15 @@ void dlog(FILE *fd, int priority, char *format, ...) } } -void dlog_ct(FILE *fd, struct nf_conntrack *ct) +void dlog_buffered_ct_flush(void *buffer_data, void *data) +{ + FILE *fd = data; + + fprintf(fd, "%s", buffer_data); + fflush(fd); +} + +void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct) { time_t t; char buf[1024]; @@ -107,8 +116,21 @@ void dlog_ct(FILE *fd, struct nf_conntrack *ct) nfct_snprintf(buf+strlen(buf), 1024-strlen(buf), ct, 0, 0, 0); if (fd) { - fprintf(fd, "%s\n", buf); - fflush(fd); + snprintf(buf+strlen(buf), 1024-strlen(buf), "\n"); + /* zero size buffer: force fflush */ + if (buffer_size(b) == 0) { + fprintf(fd, "%s", buf); + fflush(fd); + } + + if (buffer_add(b, buf, strlen(buf)) == -1) { + buffer_flush(b, dlog_buffered_ct_flush, fd); + if (buffer_add(b, buf, strlen(buf)) == -1) { + /* buffer too small, catacrocket! */ + fprintf(fd, "%s", buf); + fflush(fd); + } + } } if (CONFIG(stats).syslog_facility != -1) diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 847ec74..0acd98c 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -102,6 +102,7 @@ ftfw [F|f][T|t][F|f][W|w] "TIME_WAIT" { return T_TIME_WAIT; } "CLOSE" { return T_CLOSE; } "LISTEN" { return T_LISTEN; } +"LogFileBufferSize" { return T_STAT_BUFFER_SIZE; } {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 9cb304a..bbc5115 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -49,7 +49,7 @@ struct ct_conf conf; %token T_REPLICATE T_FOR T_IFACE %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 +%token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE %token T_IP T_PATH_VAL @@ -580,6 +580,7 @@ stat_line: stat_logfile_bool | stat_logfile_path | stat_syslog_bool | stat_syslog_facility + | buffer_size ; stat_logfile_bool : T_LOG T_ON @@ -638,6 +639,11 @@ stat_syslog_facility : T_SYSLOG T_STRING "values, defaulting to General.\n"); }; +buffer_size: T_STAT_BUFFER_SIZE T_NUMBER +{ + conf.stats.buffer_size = $2; +}; + %% int diff --git a/src/stats-mode.c b/src/stats-mode.c index e817c4e..05a1b2c 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -18,6 +18,7 @@ #include #include "cache.h" +#include "log.h" #include "conntrackd.h" #include #include @@ -37,6 +38,12 @@ static int init_stats(void) } memset(state.stats, 0, sizeof(struct ct_stats_state)); + STATE_STATS(buffer_log) = buffer_create(CONFIG(stats).buffer_size); + if (!STATE_STATS(buffer_log)) { + dlog(STATE(log), LOG_ERR, "can't allocate stats buffer"); + return -1; + } + STATE_STATS(cache) = cache_create("stats", LIFETIME, CONFIG(family), @@ -53,6 +60,9 @@ static int init_stats(void) static void kill_stats() { cache_destroy(STATE_STATS(cache)); + buffer_flush(STATE_STATS(buffer_log), + dlog_buffered_ct_flush, + STATE(stats_log)); } /* handler for requests coming via UNIX socket */ @@ -172,7 +182,7 @@ static int event_destroy_stats(struct nf_conntrack *ct) if (cache_del(STATE_STATS(cache), ct)) { debug_ct(ct, "cache destroy"); - dlog_ct(STATE(stats_log), ct); + dlog_buffered_ct(STATE(stats_log), STATE_STATS(buffer_log), ct); return 1; } else { debug_ct(ct, "can't destroy!"); -- cgit v1.2.3