From a7c245bafd98a04414903787448ac17bb0922b70 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 20 Oct 2008 14:13:51 +0200 Subject: cache-iterators: improve committing This patches fixes two problems: - If we failt to update an entry, we remove it and try again. This happens when we still have an entry in a final state like TIME_WAIT while we see a new connection (SYN_SENT) with the same tuple. In this particular case, we fail to update since some status bits are only settable, but not unsettable. - If we hit ETIME in an update, we have to go over the creation patch, otherwise we hit ENOENT in the next run. Signed-off-by: Pablo Neira Ayuso --- src/cache_iterators.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 8811fc4..fd7aed6 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -106,6 +106,7 @@ static void __do_commit_step(struct cache *c, struct us_conntrack *u) */ nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); +try_again: ret = nl_exist_conntrack(ct); switch (ret) { case -1: @@ -113,13 +114,12 @@ static void __do_commit_step(struct cache *c, struct us_conntrack *u) dlog_ct(STATE(log), ct, NFCT_O_PLAIN); break; case 0: -try_again_create: if (nl_create_conntrack(ct) == -1) { if (errno == ENOMEM) { if (retry) { retry = 0; sched_yield(); - goto try_again_create; + goto try_again; } } dlog(LOG_ERR, "commit-create: %s", strerror(errno)); @@ -130,15 +130,27 @@ try_again_create: break; case 1: c->commit_exist++; -try_again_update: if (nl_update_conntrack(ct) == -1) { if (errno == ENOMEM || errno == ETIME) { if (retry) { retry = 0; sched_yield(); - goto try_again_update; + goto try_again; } } + /* try harder, delete the entry and retry */ + if (retry) { + ret = nl_destroy_conntrack(ct); + if (ret == 0 || + (ret == -1 && errno == ENOENT)) { + retry = 0; + goto try_again; + } + dlog(LOG_ERR, "commit-rm: %s", strerror(errno)); + dlog_ct(STATE(log), ct, NFCT_O_PLAIN); + c->commit_fail++; + break; + } dlog(LOG_ERR, "commit-update: %s", strerror(errno)); dlog_ct(STATE(log), ct, NFCT_O_PLAIN); c->commit_fail++; -- cgit v1.2.3