diff options
-rw-r--r-- | include/origin.h | 1 | ||||
-rw-r--r-- | src/run.c | 29 | ||||
-rw-r--r-- | src/sync-mode.c | 28 |
3 files changed, 55 insertions, 3 deletions
diff --git a/include/origin.h b/include/origin.h index b2d1823..89308f3 100644 --- a/include/origin.h +++ b/include/origin.h @@ -5,6 +5,7 @@ enum { CTD_ORIGIN_NOT_ME = 0, /* this event comes from the kernel or any process, but not conntrackd */ CTD_ORIGIN_COMMIT, /* event comes from committer */ + CTD_ORIGIN_FLUSH, /* event comes from flush */ }; int origin_register(struct nfct_handle *h, int origin_type); @@ -181,6 +181,13 @@ static void dump_stats_runtime(int fd) send(fd, buf, size, 0); } +static void flush_done_cb(void *data) +{ + struct nfct_handle *h = data; + origin_unregister(h); + nfct_close(h); +} + void local_handler(int fd, void *data) { int ret; @@ -195,11 +202,29 @@ void local_handler(int fd, void *data) return; switch(type) { - case FLUSH_MASTER: + case FLUSH_MASTER: { + struct nfct_handle *h; + + /* disposable flusher handler */ + h = nfct_open(CONNTRACK, 0); + if (h == NULL) { + dlog(LOG_ERR, "cannot open flusher handler"); + return; + } + /* register this handler as the origin of a flush operation */ + origin_register(h, CTD_ORIGIN_FLUSH); + STATE(stats).nl_kernel_table_flush++; dlog(LOG_NOTICE, "flushing kernel conntrack table"); - nl_flush_conntrack_table(STATE(request)); + + /* fork a child process that performs the flush operation, + * meanwhile the parent process handles events. */ + if (fork_process_new(flush_done_cb, h) == 0) { + nl_flush_conntrack_table(h); + exit(EXIT_SUCCESS); + } return; + } case RESYNC_MASTER: STATE(stats).nl_kernel_table_resync++; dlog(LOG_NOTICE, "resync with master table"); diff --git a/src/sync-mode.c b/src/sync-mode.c index 91e028e..a0ba830 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -203,11 +203,37 @@ static void interface_handler(void) interface_candidate(); } +/* this is called once the flusher process has finished */ +static void flush_done_cb(void *data) +{ + struct nfct_handle *h = data; + origin_unregister(h); + nfct_close(h); +} + static void do_reset_cache_alarm(struct alarm_block *a, void *data) { + struct nfct_handle *h; + + /* disposable flusher handler */ + h = nfct_open(CONNTRACK, 0); + if (h == NULL) { + dlog(LOG_ERR, "cannot open flusher handler"); + return; + } + /* register this handler as the origin of a flush operation */ + origin_register(h, CTD_ORIGIN_FLUSH); + STATE(stats).nl_kernel_table_flush++; dlog(LOG_NOTICE, "flushing kernel conntrack table (scheduled)"); - nl_flush_conntrack_table(STATE(request)); + + /* fork a child process that performs the flush operation, + * meanwhile the parent process handles events. */ + if (fork_process_new(flush_done_cb, h) == 0) { + nl_flush_conntrack_table(h); + exit(EXIT_SUCCESS); + } + /* this is not required if events don't get lost */ cache_flush(STATE_SYNC(internal)); } |