summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--include/Makefile.am2
-rw-r--r--include/conntrackd.h4
-rw-r--r--include/fds.h16
-rw-r--r--src/Makefile.am2
-rw-r--r--src/fds.c74
-rw-r--r--src/run.c31
-rw-r--r--src/stats-mode.c2
-rw-r--r--src/sync-mode.c9
9 files changed, 120 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index aa485a1..411118e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -47,6 +47,7 @@ o remove unix socket file on exit
o use umask() to set up file permissions
o add support for NAT sequence adjustment (requires Linux kernel >= 2.6.25)
o remove TODO file from release tarballs
+o compose the file descriptor set at initialization stage to save some cycles
Max Kellermann <max@duempel.org>:
diff --git a/include/Makefile.am b/include/Makefile.am
index d7f27a9..92ebbcc 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -3,5 +3,5 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h linux_rbtree.h \
sync.h conntrackd.h local.h us-conntrack.h \
debug.h log.h hash.h mcast.h conntrack.h \
state_helper.h network.h ignore.h queue.h \
- traffic_stats.h netlink.h
+ traffic_stats.h netlink.h fds.h
diff --git a/include/conntrackd.h b/include/conntrackd.h
index 47898e2..69c1303 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -105,6 +105,8 @@ struct ct_general_state {
struct nfct_handle *event; /* event handler */
struct nfct_handle *dump; /* dump handler */
+ struct fds *fds;
+
/* statistics */
uint64_t malformed;
uint64_t bytes[NFCT_DIR_MAX];
@@ -151,7 +153,7 @@ extern struct ct_general_state st;
struct ct_mode {
int (*init)(void);
- int (*add_fds_to_set)(fd_set *readfds);
+ int (*register_fds)(struct fds *fds);
void (*run)(fd_set *readfds);
int (*local)(int fd, int type, void *data);
void (*kill)(void);
diff --git a/include/fds.h b/include/fds.h
new file mode 100644
index 0000000..cc213fe
--- /dev/null
+++ b/include/fds.h
@@ -0,0 +1,16 @@
+#ifndef _FDS_H_
+#define _FDS_H_
+
+struct fds {
+ int maxfd;
+ int fd_array_len;
+ int fd_array_cur;
+ int *fd_array;
+ fd_set readfds;
+};
+
+struct fds *create_fds(void);
+void destroy_fds(struct fds *);
+int register_fd(int fd, struct fds *fds);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 7274a14..494da4f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,7 +12,7 @@ conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
local.c log.c mcast.c netlink.c \
- ignore_pool.c \
+ ignore_pool.c fds.c \
cache.c cache_iterators.c \
cache_lifetime.c cache_timer.c cache_wt.c \
sync-mode.c sync-alarm.c sync-ftfw.c \
diff --git a/src/fds.c b/src/fds.c
new file mode 100644
index 0000000..908f048
--- /dev/null
+++ b/src/fds.c
@@ -0,0 +1,74 @@
+/*
+ * (C) 2006-2008 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
+ * 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 <stdlib.h>
+#include <string.h>
+#include "fds.h"
+
+/* we don't handle that many descriptors so eight is just fine */
+#define FDS_ARRAY_LEN 8
+#define FDS_ARRAY_SIZE (sizeof(int) * FDS_ARRAY_LEN)
+
+struct fds *create_fds(void)
+{
+ struct fds *fds;
+
+ fds = (struct fds *) malloc(sizeof(struct fds));
+ if (fds == NULL)
+ return NULL;
+
+ memset(fds, 0, sizeof(struct fds));
+
+ fds->fd_array = (int *) malloc(FDS_ARRAY_SIZE);
+ if (fds->fd_array == NULL) {
+ free(fds);
+ return NULL;
+ }
+
+ memset(fds->fd_array, 0, FDS_ARRAY_SIZE);
+ fds->fd_array_len = FDS_ARRAY_LEN;
+
+ return fds;
+}
+
+void destroy_fds(struct fds *fds)
+{
+ free(fds->fd_array);
+ free(fds);
+}
+
+int register_fd(int fd, struct fds *fds)
+{
+ FD_SET(fd, &fds->readfds);
+
+ if (fd > fds->maxfd)
+ fds->maxfd = fd;
+
+ if (fds->fd_array_cur >= fds->fd_array_len) {
+ fds->fd_array_len += FDS_ARRAY_LEN;
+ fds->fd_array = realloc(fds->fd_array,
+ fds->fd_array_len * sizeof(int));
+ if (fds->fd_array == NULL) {
+ fds->fd_array_len -= FDS_ARRAY_LEN;
+ return -1;
+ }
+ }
+
+ fds->fd_array[fds->fd_array_cur++] = fd;
+
+ return 0;
+}
diff --git a/src/run.c b/src/run.c
index 6cf259d..b259f2e 100644
--- a/src/run.c
+++ b/src/run.c
@@ -23,6 +23,7 @@
#include "ignore.h"
#include "log.h"
#include "alarm.h"
+#include "fds.h"
#include <errno.h>
#include <signal.h>
@@ -128,6 +129,21 @@ init(void)
return -1;
}
+ STATE(fds) = create_fds();
+ if (STATE(fds) == NULL) {
+ dlog(LOG_ERR, "can't create file descriptor pool");
+ return -1;
+ }
+
+ register_fd(STATE(local).fd, STATE(fds));
+ register_fd(nfct_fd(STATE(event)), STATE(fds));
+
+ if (STATE(mode)->register_fds &&
+ STATE(mode)->register_fds(STATE(fds)) == -1) {
+ dlog(LOG_ERR, "fds registration failed");
+ return -1;
+ }
+
/* Signals handling */
sigemptyset(&STATE(block));
sigaddset(&STATE(block), SIGTERM);
@@ -154,19 +170,10 @@ init(void)
static void __run(struct timeval *next_alarm)
{
- int max, ret;
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(STATE(local).fd, &readfds);
- FD_SET(nfct_fd(STATE(event)), &readfds);
-
- max = MAX(STATE(local).fd, nfct_fd(STATE(event)));
-
- if (STATE(mode)->add_fds_to_set)
- max = MAX(max, STATE(mode)->add_fds_to_set(&readfds));
+ int ret;
+ fd_set readfds = STATE(fds)->readfds;
- ret = select(max+1, &readfds, NULL, NULL, next_alarm);
+ ret = select(STATE(fds)->maxfd + 1, &readfds, NULL, NULL, next_alarm);
if (ret == -1) {
/* interrupted syscall, retry */
if (errno == EINTR)
diff --git a/src/stats-mode.c b/src/stats-mode.c
index b6ae2bd..42fa35a 100644
--- a/src/stats-mode.c
+++ b/src/stats-mode.c
@@ -181,7 +181,7 @@ static int event_destroy_stats(struct nf_conntrack *ct)
struct ct_mode stats_mode = {
.init = init_stats,
- .add_fds_to_set = NULL,
+ .register_fds = NULL,
.run = NULL,
.local = local_handler_stats,
.kill = kill_stats,
diff --git a/src/sync-mode.c b/src/sync-mode.c
index a81309f..79afcdf 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -25,6 +25,7 @@
#include "conntrackd.h"
#include "us-conntrack.h"
#include "network.h"
+#include "fds.h"
#include "debug.h"
#include <errno.h>
@@ -202,11 +203,9 @@ static int init_sync(void)
return 0;
}
-static int add_fds_to_set_sync(fd_set *readfds)
+static int register_fds_sync(struct fds *fds)
{
- FD_SET(STATE_SYNC(mcast_server->fd), readfds);
-
- return STATE_SYNC(mcast_server->fd);
+ return register_fd(STATE_SYNC(mcast_server->fd), fds);
}
static void run_sync(fd_set *readfds)
@@ -500,7 +499,7 @@ static int event_destroy_sync(struct nf_conntrack *ct)
struct ct_mode sync_mode = {
.init = init_sync,
- .add_fds_to_set = add_fds_to_set_sync,
+ .register_fds = register_fds_sync,
.run = run_sync,
.local = local_handler_sync,
.kill = kill_sync,