[ULOGD RFC 23/30] NFCT: make sequence cache bigger, make handling smarter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Increase sequence cache and therefore make cache handling smarter for
it too.

Signed-off-by: Holger Eitzenberger <holger@xxxxxxxxxxxxxxxx>

Index: ulogd-netfilter/input/flow/ulogd_inpflow_NFCT.c
===================================================================
--- ulogd-netfilter.orig/input/flow/ulogd_inpflow_NFCT.c
+++ ulogd-netfilter/input/flow/ulogd_inpflow_NFCT.c
@@ -42,10 +42,13 @@
 						 | NF_NETLINK_CONNTRACK_DESTROY)
 
 /* configuration defaults */
-#define TCACHE_SIZE       8192
-#define SCACHE_SIZE       64
-#define SCACHE_REQ_MAX    100
-#define TIMEOUT           30 SEC
+#define TCACHE_SIZE		8192
+#define SCACHE_SIZE		512
+#define TCACHE_REQ_MAX	100
+#define TIMEOUT			30 SEC
+
+#define RCVBUF_LEN		(1 << 18)
+#define SNDBUF_LEN		RCVBUF_LEN
 
 typedef enum TIMES_ { START, UPDATE, STOP, __TIME_MAX } TIMES;
 typedef unsigned conntrack_hash_t;
@@ -429,7 +432,7 @@ nfct_get_conntrack_x(struct nfct_handle 
 {
 	static char buf[NFNL_BUFFSIZE];
 	struct nfnlhdr *req = (void *)buf;
-	int cta_dir, nbytes;
+	int cta_dir;
 
 	memset(buf, 0, sizeof(buf));
 
@@ -445,9 +448,17 @@ nfct_get_conntrack_x(struct nfct_handle 
 
 	nfct_build_tuple(req, sizeof(buf), t, cta_dir);
 
-	nbytes = nfnl_send(nfct_nfnlh(cth), &req->nlh);
+	return nfnl_send(nfct_nfnlh(cth), &req->nlh);
+}
+
+/* time diff with second resolution */
+static inline unsigned
+tv_diff_sec(const struct timeval *tv1, const struct timeval *tv2)
+{
+	if (tv2->tv_sec >= tv1->tv_sec)
+		return max(tv2->tv_sec - tv1->tv_sec, 1);
 
-	return nbytes;
+	return tv1->tv_sec - tv2->tv_sec;
 }
 
 struct conntrack *
@@ -483,6 +494,85 @@ ct_put(struct conntrack *ct)
 	}
 }
 
+static struct cache *
+cache_alloc(int cache_size)
+{
+	struct cache *c;
+	int i;
+
+	c = malloc(sizeof(*c) + sizeof(struct cache_head) * cache_size);
+	if (c == NULL)
+		return NULL;
+
+	c->c_head = (void *)c + sizeof(*c);
+	c->c_num_heads = cache_size;
+	c->c_curr_head = 0;
+	c->c_cnt = 0;
+
+	for (i = 0; i < c->c_num_heads; i++) {
+		INIT_LLIST_HEAD(&c->c_head[i].link);
+		c->c_head[i].cnt = 0;
+	}
+
+	return c;
+}
+
+static void
+cache_free(struct cache *c)
+{
+	int i;
+
+	for (i = 0; i < c->c_num_heads; i++) {
+		struct llist_head *ptr, *ptr2;
+
+		llist_for_each_safe(ptr, ptr2, &c->c_head[i].link)
+			free(container_of(ptr, struct conntrack, list));
+	}
+
+	free(c);
+}
+
+int
+cache_add(struct cache *c, struct conntrack *ct)
+{
+	ct_get(ct);
+
+	ct->time[UPDATE].tv_sec = ct->time[START].tv_sec = t_now_local;
+
+	/* order of these two is important for debugging purposes */
+	c->c_cnt++;
+	c->c_add(c, ct);
+
+	return 0;
+}
+
+int
+cache_del(struct cache *c, struct conntrack *ct)
+{
+	assert(c->c_cnt > 0);
+	assert(ct->used > 0);
+
+	/* order of these two is important for debugging purposes */
+	c->c_del(c, ct);
+	c->c_cnt--;
+
+	ct_put(ct);
+
+	return 0;
+}
+
+static inline conntrack_hash_t
+cache_head_next(const struct cache *c)
+{
+	return (c->c_curr_head + 1) % c->c_num_heads;
+}
+
+static inline conntrack_hash_t
+cache_slice_end(const struct cache *c, unsigned n)
+{
+	return (c->c_curr_head + n) % c->c_num_heads;
+}
+
 /* tuple cache */
 static struct conntrack ct_search;		/* used by scache too */
 
@@ -549,6 +639,55 @@ tcache_find(const struct ulogd_pluginsta
 	return NULL;
 }
 
+/* check entries in tuple cache */
+static int
+tcache_cleanup(struct ulogd_pluginstance *pi)
+{
+	struct nfct_pluginstance *priv = (void *)pi->private;
+	struct cache *c = priv->tcache;
+	conntrack_hash_t end = cache_slice_end(c, 32);
+	struct conntrack *ct;
+	int ret, req = 0;
+
+	do {
+		llist_for_each_entry_reverse(ct, &c->c_head[c->c_curr_head].link,
+									 list) {
+			if (tv_diff_sec(&ct->time[UPDATE], &tv_now) < timeout_ce(pi))
+				continue;
+
+			/* check if its still there */
+			ret = nfct_get_conntrack_x(priv->cth, &ct->tuple,
+									   NFCT_DIR_ORIGINAL, &ct->last_seq);
+			if (ret < 0) {
+				if (errno == EWOULDBLOCK)
+					break;
+
+				ulogd_log(ULOGD_ERROR, "nfct_get_conntrack: ct=%p: %m\n",
+						  ct);
+				break;
+			}
+
+			if (&ct->last_seq != 0) {
+				ct->t_req = t_now;
+
+				assert(scache_find(pi, ct->last_seq) == NULL);
+
+				cache_add(priv->scache, ct);
+			}
+
+			if (++req > TCACHE_REQ_MAX)
+				break;
+		}
+
+		c->c_curr_head = cache_head_next(c);
+
+		if (req > TCACHE_REQ_MAX)
+			break;
+	} while (c->c_curr_head != end);
+
+	return req;
+}
+
 /* sequence cache */
 static conntrack_hash_t
 scache_hash(struct cache *c, struct conntrack *ct)
@@ -612,81 +751,39 @@ scache_find(const struct ulogd_pluginsta
 	return NULL;
 }
 
-static struct cache *
-cache_alloc(int cache_size)
-{
-	struct cache *c;
-	int i;
-
-	c = malloc(sizeof(*c) + sizeof(struct cache_head) * cache_size);
-	if (c == NULL)
-		return NULL;
-
-	c->c_head = (void *)c + sizeof(*c);
-	c->c_num_heads = cache_size;
-	c->c_curr_head = 0;
-	c->c_cnt = 0;
-
-	for (i = 0; i < c->c_num_heads; i++) {
-		INIT_LLIST_HEAD(&c->c_head[i].link);
-		c->c_head[i].cnt = 0;
-	}
-	
-	return c;
-}
-
-static void
-cache_free(struct cache *c)
-{
-	int i;
-
-	for (i = 0; i < c->c_num_heads; i++) {
-		struct llist_head *ptr, *ptr2;
-
-		llist_for_each_safe(ptr, ptr2, &c->c_head[i].link)
-			free(container_of(ptr, struct conntrack, list));
-	}
-
-	free(c);
-}
-
-int
-cache_add(struct cache *c, struct conntrack *ct)
+static int
+scache_cleanup(struct ulogd_pluginstance *pi)
 {
-	ct_get(ct);
+	struct nfct_pluginstance *priv = (void *)pi->private;
+	struct cache *c = priv->scache;
+	conntrack_hash_t end = cache_slice_end(c, 16);
+	struct conntrack *ct;
+	int del = 0;
 
-	ct->time[UPDATE].tv_sec = ct->time[START].tv_sec = t_now_local;
+	if (c->c_cnt == 0)
+		return 0;
 
-	/* order of these two is important for debugging purposes */
-	c->c_cnt++;
-	c->c_add(c, ct);
+	do {
+		struct llist_head *curr, *tmp;
 
-	return 0;
-}
+		assert(c->c_curr_head < c->c_num_heads);
 
-int
-cache_del(struct cache *c, struct conntrack *ct)
-{
-	assert(c->c_cnt > 0);
-	assert(ct->used > 0);
+		llist_for_each_prev_safe(curr, tmp, &c->c_head[c->c_curr_head].link) {
+			ct = container_of(curr, struct conntrack, seq_link);
 
-	/* order of these two is important for debugging purposes */
-	c->c_del(c, ct);
-	c->c_cnt--;
+			assert(ct->t_req != 0);
 
-	ct_put(ct);
+			if ((t_now - ct->t_req) < 5 SEC)
+				break;
 
-	return 0;
-}
+			cache_del(priv->scache, ct);
+			del++;
+		}
 
-/* time diff with second resolution */
-static inline unsigned
-tv_diff_sec(const struct timeval *tv1, const struct timeval *tv2)
-{
-	if (tv2->tv_sec >= tv1->tv_sec)
-		return max(tv2->tv_sec - tv1->tv_sec, 1);
+		c->c_curr_head = cache_head_next(c);
+	} while (c->c_curr_head != end);
 
-	return tv1->tv_sec - tv2->tv_sec;
+	return del;
 }
 
 static int
@@ -874,9 +971,6 @@ read_cb_nfct(int fd, unsigned what, void
 	return nfnl_recv_msgs(nfct_nfnlh(priv->cth), do_nfct_msg, pi);
 }
 
-
-#define STOP_HERE(h)	(((h)->c_curr_head + 32) % (h)->c_num_heads)
-
 /*
   nfct_timer_cb()
 
@@ -887,56 +981,21 @@ nfct_timer_cb(struct ulogd_timer *t)
 {
 	struct ulogd_pluginstance *pi = t->data;
 	struct nfct_pluginstance *priv = (void *)pi->private;
-	struct cache *ht = priv->tcache;
-	int i, req = 0, end = STOP_HERE(ht);
-	struct conntrack *ct;
-
-	/* cleanup stale entries from sequence cache */
-	for (i = 0; i < priv->scache->c_num_heads; i++) {
-		if (llist_empty(&priv->scache->c_head[i].link))
-			continue;
-
-		ct = container_of(priv->scache->c_head[i].link.prev,
-						  struct conntrack, seq_link);
-
-		assert(ct->t_req != 0);
-
-		if (ct->t_req > 0 && (t_now - ct->t_req) > 5 SEC)
-			cache_del(priv->scache, ct);
-	}
-
-	/* check entries in tuple cache */
-	do {
-		assert(ht->c_curr_head < ht->c_num_heads);
-
-		llist_for_each_entry(ct, &ht->c_head[ht->c_curr_head].link, list) {
-			if (tv_diff_sec(&ct->time[UPDATE], &tv_now) < timeout_ce(pi))
-				continue;
+	unsigned sc_start, sc_end, tc_start, tc_end;
 
-			/* check if its still there */
-			nfct_get_conntrack_x(priv->cth, &ct->tuple, NFCT_DIR_ORIGINAL,
-								 &ct->last_seq);
+	sc_start = priv->scache->c_curr_head;
+	tc_start = priv->tcache->c_curr_head;
 
-			if (&ct->last_seq != 0) {
-				ct->t_req = t_now;
+	scache_cleanup(pi);
+	tcache_cleanup(pi);
 
-				assert(scache_find(pi, ct->last_seq) == NULL);
-
-				cache_add(priv->scache, ct);
-			}
-
-			if (++req > SCACHE_REQ_MAX)
-				break;
-		}
-
-		ht->c_curr_head = (ht->c_curr_head + 1) % ht->c_num_heads;
-
-		if (req > SCACHE_REQ_MAX)
-			break;
-	} while (ht->c_curr_head != end);
+	sc_end = priv->scache->c_curr_head;
+	tc_end = priv->tcache->c_curr_head;
 
-	ulogd_log(ULOGD_DEBUG, "%s: ct:%u t:%u s:%u\n", pi->id,
-			  num_conntrack, priv->tcache->c_cnt, priv->scache->c_cnt);
+	ulogd_log(ULOGD_DEBUG, "%s: ct=%u t=%u [%u,%u[ s=%u [%u,%u[\n",
+			  pi->id, num_conntrack,
+			  priv->tcache->c_cnt, tc_start, tc_end,
+			  priv->scache->c_cnt, sc_start, sc_end);
 }
 
 static int

-- 
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux