[netfilter-cvslog] r7517 - in trunk/conntrack-tools: include src

pablo at netfilter.org pablo at netfilter.org
Tue Apr 29 16:18:17 CEST 2008


Author: pablo at netfilter.org
Date: 2008-04-29 16:18:17 +0200 (Tue, 29 Apr 2008)
New Revision: 7517

Modified:
   trunk/conntrack-tools/include/cache.h
   trunk/conntrack-tools/include/conntrackd.h
   trunk/conntrack-tools/include/us-conntrack.h
   trunk/conntrack-tools/src/alarm.c
   trunk/conntrack-tools/src/cache.c
   trunk/conntrack-tools/src/cache_lifetime.c
   trunk/conntrack-tools/src/read_config_lex.l
   trunk/conntrack-tools/src/read_config_yy.y
   trunk/conntrack-tools/src/sync-ftfw.c
   trunk/conntrack-tools/src/sync-mode.c
Log:
Fix reorder possible reordering of destroy messages under message omission. This patch introduces the TimeoutDestroy clause to determine how long a conntrack remains in the internal cache once it has been destroy from the kernel table.


Modified: trunk/conntrack-tools/include/cache.h
===================================================================
--- trunk/conntrack-tools/include/cache.h	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/include/cache.h	2008-04-29 14:18:17 UTC (rev 7517)
@@ -82,6 +82,7 @@
 struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct);
 struct us_conntrack *cache_update_force(struct cache *c, struct nf_conntrack *ct);
 int cache_del(struct cache *c, struct nf_conntrack *ct);
+struct us_conntrack *cache_del_timeout(struct cache *c, struct nf_conntrack *ct, int timeout);
 int cache_test(struct cache *c, struct nf_conntrack *ct);
 void cache_stats(const struct cache *c, int fd);
 struct us_conntrack *cache_get_conntrack(struct cache *, void *);

Modified: trunk/conntrack-tools/include/conntrackd.h
===================================================================
--- trunk/conntrack-tools/include/conntrackd.h	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/include/conntrackd.h	2008-04-29 14:18:17 UTC (rev 7517)
@@ -76,6 +76,7 @@
 	int refresh;
 	int cache_timeout;		/* cache entries timeout */
 	int commit_timeout;		/* committed entries timeout */
+	int del_timeout;
 	unsigned int netlink_buffer_size;
 	unsigned int netlink_buffer_size_max_grown;
 	unsigned char ignore_protocol[IPPROTO_MAX];

Modified: trunk/conntrack-tools/include/us-conntrack.h
===================================================================
--- trunk/conntrack-tools/include/us-conntrack.h	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/include/us-conntrack.h	2008-04-29 14:18:17 UTC (rev 7517)
@@ -1,12 +1,13 @@
 #ifndef _US_CONNTRACK_H_
 #define _US_CONNTRACK_H_
 
+#include "alarm.h"
 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
 
-/* be careful, do not modify the layout */
 struct us_conntrack {
 	struct 	nf_conntrack *ct;
-	struct  cache *cache;          /* add new attributes here */
+	struct  cache *cache; 
+	struct	alarm_block alarm;
 	char 	data[0];
 };
 

Modified: trunk/conntrack-tools/src/alarm.c
===================================================================
--- trunk/conntrack-tools/src/alarm.c	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/alarm.c	2008-04-29 14:18:17 UTC (rev 7517)
@@ -123,7 +123,7 @@
 {
 	struct list_head alarm_run_queue;
 	struct rb_node *node;
-	struct alarm_block *this;
+	struct alarm_block *this, *tmp;
 	struct timeval tv;
 
 	gettimeofday(&tv, NULL);
@@ -138,7 +138,8 @@
 		list_add(&this->list, &alarm_run_queue);
 	}
 
-	list_for_each_entry(this, &alarm_run_queue, list) {
+	/* must be safe as entries can vanish from the callback */
+	list_for_each_entry_safe(this, tmp, &alarm_run_queue, list) {
 		rb_erase(&this->node, &alarm_root);
 		RB_CLEAR_NODE(&this->node);
 		this->function(this, this->data);

Modified: trunk/conntrack-tools/src/cache.c
===================================================================
--- trunk/conntrack-tools/src/cache.c	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/cache.c	2008-04-29 14:18:17 UTC (rev 7517)
@@ -237,6 +237,8 @@
 	free(c);
 }
 
+static void __del_timeout(struct alarm_block *a, void *data);
+
 static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct)
 {
 	unsigned i;
@@ -258,6 +260,8 @@
 	if (u) {
 		char *data = u->data;
 
+		init_alarm(&u->alarm, u, __del_timeout);
+
         	for (i = 0; i < c->num_features; i++) {
 			c->features[i]->add(u, data);
 			data += c->features[i]->size;
@@ -324,8 +328,7 @@
 	return NULL;
 }
 
-static struct us_conntrack *
-__cache_update(struct cache *c, struct nf_conntrack *ct)
+struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct)
 {
 	struct us_conntrack *u;
 
@@ -339,15 +342,6 @@
 	return NULL;
 }
 
-struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct)
-{
-	struct us_conntrack *u;
-
-	u = __cache_update(c, ct);
-
-	return u;
-}
-
 struct us_conntrack *cache_update_force(struct cache *c,
 					struct nf_conntrack *ct)
 {
@@ -379,6 +373,24 @@
 	return ret != NULL;
 }
 
+static void __del2(struct cache *c, struct us_conntrack *u)
+{
+	unsigned i;
+	char *data = u->data;
+	struct nf_conntrack *p = u->ct;
+
+	for (i = 0; i < c->num_features; i++) {
+		c->features[i]->destroy(u, data);
+		data += c->features[i]->size;
+	}
+
+	if (c->extra && c->extra->destroy)
+		c->extra->destroy(u, ((char *) u) + c->extra_offset);
+
+	hashtable_del(c->h, u);
+	free(p);
+}
+
 static int __del(struct cache *c, struct nf_conntrack *ct)
 {
 	size_t size = c->h->datasize;
@@ -389,20 +401,8 @@
 
 	u = (struct us_conntrack *) hashtable_test(c->h, u);
 	if (u) {
-		unsigned i;
-		char *data = u->data;
-		struct nf_conntrack *p = u->ct;
-
-		for (i = 0; i < c->num_features; i++) {
-			c->features[i]->destroy(u, data);
-			data += c->features[i]->size;
-		}
-
-		if (c->extra && c->extra->destroy)
-			c->extra->destroy(u, ((char *) u) + c->extra_offset);
-
-		hashtable_del(c->h, u);
-		free(p);
+		del_alarm(&u->alarm);
+		__del2(c, u);
 		return 1;
 	}
 	return 0;
@@ -419,6 +419,37 @@
 	return 0;
 }
 
+static void __del_timeout(struct alarm_block *a, void *data)
+{
+	struct us_conntrack *u = (struct us_conntrack *) data;
+	struct cache *c = u->cache;
+
+	__del2(u->cache, u);
+	c->del_ok++;
+}
+
+struct us_conntrack *
+cache_del_timeout(struct cache *c, struct nf_conntrack *ct, int timeout)
+{
+	size_t size = c->h->datasize;
+	char buf[size];
+	struct us_conntrack *u = (struct us_conntrack *) buf;
+
+	if (timeout <= 0)
+		cache_del(c, ct);
+
+	u->ct = ct;
+
+	u = (struct us_conntrack *) hashtable_test(c->h, u);
+	if (u) {
+		if (!alarm_pending(&u->alarm)) {
+			add_alarm(&u->alarm, timeout, 0);
+			return u;
+		}
+	}
+	return NULL;
+}
+
 struct us_conntrack *cache_get_conntrack(struct cache *c, void *data)
 {
 	return (struct us_conntrack *)((char*)data - c->extra_offset);

Modified: trunk/conntrack-tools/src/cache_lifetime.c
===================================================================
--- trunk/conntrack-tools/src/cache_lifetime.c	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/cache_lifetime.c	2008-04-29 14:18:17 UTC (rev 7517)
@@ -53,7 +53,13 @@
 
 	gettimeofday(&tv, NULL);
 
-	return sprintf(buf, " [active since %lds]", tv.tv_sec - *lifetime);
+	if (alarm_pending(&u->alarm))
+		return sprintf(buf, " [active since %lds] [expires in %lds]",
+			       tv.tv_sec - *lifetime, 
+			       u->alarm.tv.tv_sec - tv.tv_sec);
+	else
+		return sprintf(buf, " [active since %lds]", 
+			       tv.tv_sec - *lifetime);
 }
 
 struct cache_feature lifetime_feature = {

Modified: trunk/conntrack-tools/src/read_config_lex.l
===================================================================
--- trunk/conntrack-tools/src/read_config_lex.l	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/read_config_lex.l	2008-04-29 14:18:17 UTC (rev 7517)
@@ -103,6 +103,7 @@
 "CLOSE"				{ return T_CLOSE; }
 "LISTEN"			{ return T_LISTEN; }
 "LogFileBufferSize"		{ return T_STAT_BUFFER_SIZE; }
+"DestroyTimeout"		{ return T_DESTROY_TIMEOUT; }
 
 {is_on}			{ return T_ON; }
 {is_off}		{ return T_OFF; }

Modified: trunk/conntrack-tools/src/read_config_yy.y
===================================================================
--- trunk/conntrack-tools/src/read_config_yy.y	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/read_config_yy.y	2008-04-29 14:18:17 UTC (rev 7517)
@@ -52,7 +52,7 @@
 %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 T_STAT_BUFFER_SIZE
+%token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE T_DESTROY_TIMEOUT
 
 
 %token <string> T_IP T_PATH_VAL
@@ -429,6 +429,7 @@
 	 | listen_to
 	 | state_replication
 	 | cache_writethrough
+	 | destroy_timeout
 	 ;
 
 sync_mode_alarm: T_SYNC_MODE T_ALARM '{' sync_mode_alarm_list '}'
@@ -469,6 +470,11 @@
 	conf.window_size = $2;
 };
 
+destroy_timeout: T_DESTROY_TIMEOUT T_NUMBER
+{
+	conf.del_timeout = $2;
+};
+
 relax_transitions: T_RELAX_TRANSITIONS
 {
 	fprintf(stderr, "Notice: RelaxTransitions clause is obsolete. "
@@ -746,5 +752,9 @@
 	if (CONFIG(window_size) == 0)
 		CONFIG(window_size) = 20;
 
+	/* double of 120 seconds which is common timeout of a final state */
+	if (conf.flags & CTD_SYNC_FTFW && CONFIG(del_timeout) == 0)
+		CONFIG(del_timeout) = 240;
+
 	return 0;
 }

Modified: trunk/conntrack-tools/src/sync-ftfw.c
===================================================================
--- trunk/conntrack-tools/src/sync-ftfw.c	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/sync-ftfw.c	2008-04-29 14:18:17 UTC (rev 7517)
@@ -390,6 +390,7 @@
 	switch(ntohs(pld->query)) {
 	case NFCT_Q_CREATE:
 	case NFCT_Q_UPDATE:
+	case NFCT_Q_DESTROY:
 		cn = (struct cache_ftfw *) 
 			cache_get_extra(STATE_SYNC(internal), u);
 
@@ -402,9 +403,6 @@
 		list_add_tail(&cn->rs_list, &rs_list);
 		rs_list_len++;
 		break;
-	case NFCT_Q_DESTROY:
-		queue_add(rs_queue, net, net->len);
-		break;
 	}
 }
 
@@ -429,10 +427,10 @@
 	return 0;
 }
 
-static int tx_list_xmit(struct list_head *i, struct us_conntrack *u)
+static int tx_list_xmit(struct list_head *i, struct us_conntrack *u, int type)
 {
 	int ret;
-	struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_UPDATE);
+	struct nethdr *net = BUILD_NETMSG(u->ct, type);
 	size_t len = prepare_send_netmsg(STATE_SYNC(mcast_client), net);
 
 	dp("tx_list sq: %u fl:%u len:%u\n",
@@ -460,7 +458,10 @@
 		struct us_conntrack *u;
 
 		u = cache_get_conntrack(STATE_SYNC(internal), cn);
-		tx_list_xmit(&cn->tx_list, u);
+		if (alarm_pending(&u->alarm))
+			tx_list_xmit(&cn->tx_list, u, NFCT_Q_DESTROY);
+		else
+			tx_list_xmit(&cn->tx_list, u, NFCT_Q_UPDATE);
 	}
 
 	/* reset alive alarm */

Modified: trunk/conntrack-tools/src/sync-mode.c
===================================================================
--- trunk/conntrack-tools/src/sync-mode.c	2008-04-29 12:56:23 UTC (rev 7516)
+++ trunk/conntrack-tools/src/sync-mode.c	2008-04-29 14:18:17 UTC (rev 7517)
@@ -344,17 +344,15 @@
 		debug_ct(ct, "resync");
 }
 
-static void mcast_send_sync(struct us_conntrack *u,
-			    struct nf_conntrack *ct,
-			    int query)
+static void mcast_send_sync(struct us_conntrack *u, int query)
 {
 	size_t len;
 	struct nethdr *net;
 
-	if (!state_helper_verdict(query, ct))
+	if (!state_helper_verdict(query, u->ct))
 		return;
 
-	net = BUILD_NETMSG(ct, query);
+	net = BUILD_NETMSG(u->ct, query);
 	len = prepare_send_netmsg(STATE_SYNC(mcast_client), net);
 	mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len);
 	if (STATE_SYNC(sync)->send)
@@ -370,8 +368,10 @@
 	ret = nfct_query(h, NFCT_Q_GET, u->ct);
 	if (ret == -1 && errno == ENOENT) {
 		debug_ct(u->ct, "overrun purge resync");
-		mcast_send_sync(u, u->ct, NFCT_Q_DESTROY);
-		cache_del(STATE_SYNC(internal), u->ct);
+		if (cache_del_timeout(STATE_SYNC(internal),
+				      u->ct, 
+				      CONFIG(del_timeout)))
+			mcast_send_sync(u, NFCT_Q_DESTROY);
 	}
 
 	return 0;
@@ -406,7 +406,7 @@
 	if (!cache_test(STATE_SYNC(internal), ct)) {
 		if ((u = cache_update_force(STATE_SYNC(internal), ct))) {
 			debug_ct(u->ct, "overrun resync");
-			mcast_send_sync(u, u->ct, NFCT_Q_UPDATE);
+			mcast_send_sync(u, NFCT_Q_UPDATE);
 		}
 	}
 
@@ -427,7 +427,7 @@
 	nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
 retry:
 	if ((u = cache_add(STATE_SYNC(internal), ct))) {
-		mcast_send_sync(u, ct, NFCT_Q_CREATE);
+		mcast_send_sync(u, NFCT_Q_CREATE);
 		debug_ct(u->ct, "internal new");
 	} else {
 		if (errno == EEXIST) {
@@ -453,16 +453,19 @@
 		return;
 	}
 	debug_ct(u->ct, "internal update");
-	mcast_send_sync(u, ct, NFCT_Q_UPDATE);
+	mcast_send_sync(u, NFCT_Q_UPDATE);
 }
 
 static int event_destroy_sync(struct nf_conntrack *ct)
 {
+	struct us_conntrack *u;
+
 	if (!CONFIG(cache_write_through))
 		nfct_attr_unset(ct, ATTR_TIMEOUT);
 
-	if (cache_del(STATE_SYNC(internal), ct)) {
-		mcast_send_sync(NULL, ct, NFCT_Q_DESTROY);
+	u = cache_del_timeout(STATE_SYNC(internal), ct, CONFIG(del_timeout));
+	if (u != NULL) {
+		mcast_send_sync(u, NFCT_Q_DESTROY);
 		debug_ct(ct, "internal destroy");
 		return 1;
 	} else {




More information about the netfilter-cvslog mailing list