Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Mar 2005 01:10:38 +0900
From:      Hajimu UMEMOTO <ume@freebsd.org>
To:        Mike Tancsa <mike@sentex.net>
Cc:        freebsd-stable@freebsd.org
Subject:   Re: RELENG_5 and FAST_IPSEC limits
Message-ID:  <ygek6o7inb5.wl%ume@mahoroba.org>
In-Reply-To: <4237523B.7090005@errno.com>
References:  <6.2.1.2.0.20050315112131.054b56f8@64.7.153.2> <4237523B.7090005@errno.com>

next in thread | previous in thread | raw e-mail | index | archive | help
--Multipart_Thu_Mar_17_01:10:38_2005-1
Content-Type: text/plain; charset=US-ASCII

Hi,

>>>>> On Tue, 15 Mar 2005 13:23:07 -0800
>>>>> Sam Leffler <sam@errno.com> said:

> We are running into a case where there are too many SAs, and doing a 
> setkey -D would fail with a
> 
> "recv: Resource temporarily unavailable"
> 
> after displaying most of the associations.
> 
> Is there a way to get around this, or is there a hard limit ?
> 
> # setkey -D | grep ^172 | wc
>      186     372    5096
> 
> When the remotes are renegotiating, and there are a lot of tunnels in 
> the state of mature and dying, this number can go up to 341, but not 
> higher.  This also seems to send racoon into a hung state that we then 
> need to kill off and restart.
> 
> It was suggested in a post that /usr/src/sys/net/raw_cb.h get changed from
> 
> 
> #define RAWSNDQ 8192
> #define RAWRCVQ 8192
> 
> to something larger like
> 
> #define RAWSNDQ 24576
> #define RAWRCVQ 24576
> 
> If this is the underlying issue, will it work on its own, or are there 
> other values that need to be tuned ?  Will I need to recompile any 
> userland apps (e.g. racoon, setkey) and are there any other values I 
> would need to adjust

sam> Looks like you're hitting the limit on returning status information 
sam> through a PF_KEY socket.  FWIW this is not related to FAST_IPSEC; it's 
sam> an issue with PF_KEY and is common to both IPsec implementations.

sam> Upping the raw socket buffer sizes should permit more information to be 
sam> returned but you may always exceed this limit as you can create more 
sam> SA's than can be reported in a single msg.  Some groups have dealt with 
sam> this by changing the PF_KEY api, e.g. to report an incomplete msg so the 
sam> user-mode app can retrieve more data with additional reads.  If upping 
sam> the socket buffer limits doesn't help then you might search for patches.

KAME/NetBSD does it throuth sysctl.  Since sysctl API is slightly
different between NetBSD and FreeBSD, I didn't merge it, yet.
Please try attached patch.  This is mainly taken from NetBSD.
There is corresponding code in racoon, already.  Please make sure to
copy sys/netkey/key_var.h into /usr/include/netkey/ before recompiling
racoon.

Sincerely,


--Multipart_Thu_Mar_17_01:10:38_2005-1
Content-Type: text/plain; type=patch; charset=US-ASCII
Content-Disposition: attachment; filename="keyctl_dump.diff"
Content-Transfer-Encoding: 7bit

Index: sys/netipsec/key.c
diff -u -p sys/netipsec/key.c.orig sys/netipsec/key.c
--- sys/netipsec/key.c.orig	Mon Feb 28 05:34:43 2005
+++ sys/netipsec/key.c	Thu Mar 17 00:44:24 2005
@@ -392,6 +392,7 @@ static int key_spdflush __P((struct sock
 	const struct sadb_msghdr *));
 static int key_spddump __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
+static struct mbuf *key_setspddump __P((int *));
 static struct mbuf *key_setdumpsp __P((struct secpolicy *,
 	u_int8_t, u_int32_t, u_int32_t));
 static u_int key_getspreqmsglen __P((struct secpolicy *));
@@ -483,6 +484,7 @@ static int key_flush __P((struct socket 
 	const struct sadb_msghdr *));
 static int key_dump __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
+static struct mbuf *key_setdump __P((u_int8_t, int *));
 static int key_promisc __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 static int key_senderror __P((struct socket *, struct mbuf *, int));
@@ -2396,6 +2398,52 @@ key_spddump(so, m, mhp)
 }
 
 static struct mbuf *
+key_setspddump(errorp)
+	int *errorp;
+{
+	struct secpolicy *sp;
+	int cnt;
+	u_int dir;
+	struct mbuf *m, *n;
+
+	/* search SPD entry and get buffer size. */
+	cnt = 0;
+	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+		LIST_FOREACH(sp, &sptree[dir], chain) {
+			cnt++;
+		}
+	}
+
+	if (cnt == 0) {
+		*errorp = ENOENT;
+		return (NULL);
+	}
+
+	m = NULL;
+	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+		LIST_FOREACH(sp, &sptree[dir], chain) {
+			--cnt;
+			n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, 0);
+
+			if (!n) {
+				*errorp = ENOBUFS;
+				m_freem(m);
+				return (NULL);
+			}
+			if (!m)
+				m = n;
+			else {
+				m->m_pkthdr.len += n->m_pkthdr.len;
+				m_cat(m, n);
+			}
+		}
+	}
+
+	*errorp = 0;
+	return (m);
+}
+
+static struct mbuf *
 key_setdumpsp(sp, type, seq, pid)
 	struct secpolicy *sp;
 	u_int8_t type;
@@ -6502,6 +6550,98 @@ key_dump(so, m, mhp)
 	return 0;
 }
 
+static struct mbuf *
+key_setdump(req_satype, errorp)
+	u_int8_t req_satype;
+	int *errorp;
+{
+	struct secashead *sah;
+	struct secasvar *sav;
+	u_int16_t proto;
+	u_int stateidx;
+	u_int8_t satype;
+	u_int8_t state;
+	int cnt;
+	struct mbuf *m, *n;
+
+	/* map satype to proto */
+	if ((proto = key_satype2proto(req_satype)) == 0) {
+		*errorp = EINVAL;
+		return (NULL);
+	}
+
+	/* count sav entries to be sent to the userland. */
+	cnt = 0;
+	LIST_FOREACH(sah, &sahtree, chain) {
+		if (req_satype != SADB_SATYPE_UNSPEC &&
+		    proto != sah->saidx.proto)
+			continue;
+
+		for (stateidx = 0;
+		     stateidx < _ARRAYLEN(saorder_state_any);
+		     stateidx++) {
+			state = saorder_state_any[stateidx];
+			LIST_FOREACH(sav, &sah->savtree[state], chain) {
+				cnt++;
+			}
+		}
+	}
+
+	if (cnt == 0) {
+		*errorp = ENOENT;
+		return (NULL);
+	}
+
+	/* send this to the userland, one at a time. */
+	m = NULL;
+	LIST_FOREACH(sah, &sahtree, chain) {
+		if (req_satype != SADB_SATYPE_UNSPEC &&
+		    proto != sah->saidx.proto)
+			continue;
+
+		/* map proto to satype */
+		if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
+			m_freem(m);
+			*errorp = EINVAL;
+			return (NULL);
+		}
+
+		for (stateidx = 0;
+		     stateidx < _ARRAYLEN(saorder_state_any);
+		     stateidx++) {
+			state = saorder_state_any[stateidx];
+			LIST_FOREACH(sav, &sah->savtree[state], chain) {
+				n = key_setdumpsa(sav, SADB_DUMP, satype,
+				    --cnt, 0);
+				if (!n) {
+					m_freem(m);
+					*errorp = ENOBUFS;
+					return (NULL);
+				}
+
+				if (!m)
+					m = n;
+				else
+					m_cat(m, n);
+			}
+		}
+	}
+
+	if (!m) {
+		*errorp = EINVAL;
+		return (NULL);
+	}
+
+	if ((m->m_flags & M_PKTHDR) != 0) {
+		m->m_pkthdr.len = 0;
+		for (n = m; n; n = n->m_next)
+			m->m_pkthdr.len += n->m_len;
+	}
+
+	*errorp = 0;
+	return (m);
+}
+
 /*
  * SADB_X_PROMISC processing
  *
@@ -7175,6 +7315,75 @@ key_sa_stir_iv(sav)
 	IPSEC_ASSERT(sav->iv != NULL, ("null IV"));
 	key_randomfill(sav->iv, sav->ivlen);
 }
+
+static int
+sysctl_net_key_dumpsa(SYSCTL_HANDLER_ARGS)
+{
+	int *name = (int *)arg1;
+	struct mbuf *m, *n;
+	int s, error;
+
+	if (req->newptr)
+		return (EPERM);
+	if (arg2 != 1)
+		return (EINVAL);
+
+	s = splnet();
+	m = key_setdump(name[0], &error);
+	splx(s);
+	if (!m)
+		return (error);
+	if (!req->oldptr)
+		req->oldidx = m->m_pkthdr.len;
+	else {
+		for (n = m; n; n = n->m_next) {
+			error = SYSCTL_OUT(req, mtod(n, const void *),
+			    n->m_len);
+			if (error)
+				break;
+		}
+	}
+	m_freem(m);
+
+	return (error);
+}
+
+static int
+sysctl_net_key_dumpsp(SYSCTL_HANDLER_ARGS)
+{
+	struct mbuf *m, *n;
+	int s, error;
+
+	if (req->newptr)
+		return (EPERM);
+	if (arg2 != 0)
+		return (EINVAL);
+
+	s = splnet();
+	m = key_setspddump(&error);
+	splx(s);
+	if (!m)
+		return (error);
+	if (!req->oldptr)
+		req->oldidx = m->m_pkthdr.len;
+	else {
+		for (n = m; n; n = n->m_next) {
+			error = SYSCTL_OUT(req, mtod(n, const void *),
+			    n->m_len);
+			if (error)
+				break;
+		}
+	}
+	m_freem(m);
+
+	return (error);
+}
+
+SYSCTL_NODE(_net_key, KEYCTL_DUMPSA, dumpsa, CTLFLAG_RD | CTLFLAG_SKIP,
+	sysctl_net_key_dumpsa, "");
+
+SYSCTL_NODE(_net_key, KEYCTL_DUMPSP, dumpsp, CTLFLAG_RD | CTLFLAG_SKIP,
+	sysctl_net_key_dumpsp, "");
 
 /* XXX too much? */
 static struct mbuf *
Index: sys/netipsec/key_var.h
diff -u sys/netipsec/key_var.h.orig sys/netipsec/key_var.h
--- sys/netipsec/key_var.h.orig	Mon Feb 28 05:34:43 2005
+++ sys/netipsec/key_var.h	Wed Mar 16 22:26:16 2005
@@ -46,7 +46,9 @@
 #define KEYCTL_ESP_AUTH			10
 #define KEYCTL_AH_KEYMIN		11
 #define KEYCTL_PREFERED_OLDSA		12
-#define KEYCTL_MAXID			13
+#define KEYCTL_DUMPSA			13
+#define KEYCTL_DUMPSP			14
+#define KEYCTL_MAXID			15
 
 #define KEYCTL_NAMES { \
 	{ 0, 0 }, \
Index: sys/netkey/key.c
diff -u -p sys/netkey/key.c.orig sys/netkey/key.c
--- sys/netkey/key.c.orig	Mon Feb 28 05:34:46 2005
+++ sys/netkey/key.c	Thu Mar 17 00:43:42 2005
@@ -383,6 +383,7 @@ static int key_spdflush(struct socket *,
 	const struct sadb_msghdr *);
 static int key_spddump(struct socket *, struct mbuf *,
 	const struct sadb_msghdr *);
+static struct mbuf *key_setspddump(int *);
 static struct mbuf *key_setdumpsp(struct secpolicy *,
 	u_int8_t, u_int32_t, u_int32_t);
 static u_int key_getspreqmsglen(struct secpolicy *);
@@ -478,6 +479,7 @@ static int key_flush(struct socket *, st
 	const struct sadb_msghdr *);
 static int key_dump(struct socket *, struct mbuf *,
 	const struct sadb_msghdr *);
+static struct mbuf *key_setdump(u_int8_t, int *);
 static int key_promisc(struct socket *, struct mbuf *,
 	const struct sadb_msghdr *);
 static int key_senderror(struct socket *, struct mbuf *, int);
@@ -2480,6 +2482,52 @@ key_spddump(so, m, mhp)
 }
 
 static struct mbuf *
+key_setspddump(errorp)
+	int *errorp;
+{
+	struct secpolicy *sp;
+	int cnt;
+	u_int dir;
+	struct mbuf *m, *n;
+
+	/* search SPD entry and get buffer size. */
+	cnt = 0;
+	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+		LIST_FOREACH(sp, &sptree[dir], chain) {
+			cnt++;
+		}
+	}
+
+	if (cnt == 0) {
+		*errorp = ENOENT;
+		return (NULL);
+	}
+
+	m = NULL;
+	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+		LIST_FOREACH(sp, &sptree[dir], chain) {
+			--cnt;
+			n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, 0);
+
+			if (!n) {
+				*errorp = ENOBUFS;
+				m_freem(m);
+				return (NULL);
+			}
+			if (!m)
+				m = n;
+			else {
+				m->m_pkthdr.len += n->m_pkthdr.len;
+				m_cat(m, n);
+			}
+		}
+	}
+
+	*errorp = 0;
+	return (m);
+}
+
+static struct mbuf *
 key_setdumpsp(sp, type, seq, pid)
 	struct secpolicy *sp;
 	u_int8_t type;
@@ -6796,6 +6844,98 @@ key_dump(so, m, mhp)
 	return 0;
 }
 
+static struct mbuf *
+key_setdump(req_satype, errorp)
+	u_int8_t req_satype;
+	int *errorp;
+{
+	struct secashead *sah;
+	struct secasvar *sav;
+	u_int16_t proto;
+	u_int stateidx;
+	u_int8_t satype;
+	u_int8_t state;
+	int cnt;
+	struct mbuf *m, *n;
+
+	/* map satype to proto */
+	if ((proto = key_satype2proto(req_satype)) == 0) {
+		*errorp = EINVAL;
+		return (NULL);
+	}
+
+	/* count sav entries to be sent to the userland. */
+	cnt = 0;
+	LIST_FOREACH(sah, &sahtree, chain) {
+		if (req_satype != SADB_SATYPE_UNSPEC &&
+		    proto != sah->saidx.proto)
+			continue;
+
+		for (stateidx = 0;
+		     stateidx < _ARRAYLEN(saorder_state_any);
+		     stateidx++) {
+			state = saorder_state_any[stateidx];
+			LIST_FOREACH(sav, &sah->savtree[state], chain) {
+				cnt++;
+			}
+		}
+	}
+
+	if (cnt == 0) {
+		*errorp = ENOENT;
+		return (NULL);
+	}
+
+	/* send this to the userland, one at a time. */
+	m = NULL;
+	LIST_FOREACH(sah, &sahtree, chain) {
+		if (req_satype != SADB_SATYPE_UNSPEC &&
+		    proto != sah->saidx.proto)
+			continue;
+
+		/* map proto to satype */
+		if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
+			m_freem(m);
+			*errorp = EINVAL;
+			return (NULL);
+		}
+
+		for (stateidx = 0;
+		     stateidx < _ARRAYLEN(saorder_state_any);
+		     stateidx++) {
+			state = saorder_state_any[stateidx];
+			LIST_FOREACH(sav, &sah->savtree[state], chain) {
+				n = key_setdumpsa(sav, SADB_DUMP, satype,
+				    --cnt, 0);
+				if (!n) {
+					m_freem(m);
+					*errorp = ENOBUFS;
+					return (NULL);
+				}
+
+				if (!m)
+					m = n;
+				else
+					m_cat(m, n);
+			}
+		}
+	}
+
+	if (!m) {
+		*errorp = EINVAL;
+		return (NULL);
+	}
+
+	if ((m->m_flags & M_PKTHDR) != 0) {
+		m->m_pkthdr.len = 0;
+		for (n = m; n; n = n->m_next)
+			m->m_pkthdr.len += n->m_len;
+	}
+
+	*errorp = 0;
+	return (m);
+}
+
 /*
  * SADB_X_PROMISC processing
  *
@@ -7593,6 +7733,75 @@ key_sp_unlink(sp)
 		key_freesp(sp);
 	}
 }
+
+static int
+sysctl_net_key_dumpsa(SYSCTL_HANDLER_ARGS)
+{
+	int *name = (int *)arg1;
+	struct mbuf *m, *n;
+	int s, error;
+
+	if (req->newptr)
+		return (EPERM);
+	if (arg2 != 1)
+		return (EINVAL);
+
+	s = splnet();
+	m = key_setdump(name[0], &error);
+	splx(s);
+	if (!m)
+		return (error);
+	if (!req->oldptr)
+		req->oldidx = m->m_pkthdr.len;
+	else {
+		for (n = m; n; n = n->m_next) {
+			error = SYSCTL_OUT(req, mtod(n, const void *),
+			    n->m_len);
+			if (error)
+				break;
+		}
+	}
+	m_freem(m);
+
+	return (error);
+}
+
+static int
+sysctl_net_key_dumpsp(SYSCTL_HANDLER_ARGS)
+{
+	struct mbuf *m, *n;
+	int s, error;
+
+	if (req->newptr)
+		return (EPERM);
+	if (arg2 != 0)
+		return (EINVAL);
+
+	s = splnet();
+	m = key_setspddump(&error);
+	splx(s);
+	if (!m)
+		return (error);
+	if (!req->oldptr)
+		req->oldidx = m->m_pkthdr.len;
+	else {
+		for (n = m; n; n = n->m_next) {
+			error = SYSCTL_OUT(req, mtod(n, const void *),
+			    n->m_len);
+			if (error)
+				break;
+		}
+	}
+	m_freem(m);
+
+	return (error);
+}
+
+SYSCTL_NODE(_net_key, KEYCTL_DUMPSA, dumpsa, CTLFLAG_RD | CTLFLAG_SKIP,
+	sysctl_net_key_dumpsa, "");
+
+SYSCTL_NODE(_net_key, KEYCTL_DUMPSP, dumpsp, CTLFLAG_RD | CTLFLAG_SKIP,
+	sysctl_net_key_dumpsp, "");
 
 /* XXX too much? */
 static struct mbuf *
Index: sys/netkey/key_var.h
diff -u sys/netkey/key_var.h.orig sys/netkey/key_var.h
--- sys/netkey/key_var.h.orig	Wed Mar 16 19:05:17 2005
+++ sys/netkey/key_var.h	Wed Mar 16 19:05:26 2005
@@ -46,7 +46,9 @@
 #define KEYCTL_ESP_AUTH			10
 #define KEYCTL_AH_KEYMIN		11
 #define KEYCTL_PREFERED_OLDSA		12
-#define KEYCTL_MAXID			13
+#define KEYCTL_DUMPSA			13
+#define KEYCTL_DUMPSP			14
+#define KEYCTL_MAXID			15
 
 #ifdef _KERNEL
 #define _ARRAYLEN(p) (sizeof(p)/sizeof(p[0]))
Index: usr.sbin/setkey/setkey.c
diff -u -p usr.sbin/setkey/setkey.c.orig usr.sbin/setkey/setkey.c
--- usr.sbin/setkey/setkey.c.orig	Wed Nov  5 18:47:54 2003
+++ usr.sbin/setkey/setkey.c	Thu Mar 17 00:39:46 2005
@@ -34,11 +34,13 @@
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/sysctl.h>
 #include <err.h>
 #include <net/route.h>
 #include <netinet/in.h>
 #include <net/pfkeyv2.h>
 #include <netkey/keydb.h>
+#include <netkey/key_var.h>
 #include <netkey/key_debug.h>
 #include <netinet6/ipsec.h>
 
@@ -60,6 +62,7 @@ void sendkeyshort __P((u_int));
 void promisc __P((void));
 int sendkeymsg __P((char *, size_t));
 int postproc __P((struct sadb_msg *, int));
+int sysctldump __P((u_int, u_int8_t));
 const char *numstr __P((int));
 void shortdump_hdr __P((void));
 void shortdump __P((struct sadb_msg *));
@@ -106,6 +109,7 @@ main(ac, av)
 {
 	FILE *fp = stdin;
 	int c;
+	int error;
 
 	if (ac == 1) {
 		usage();
@@ -166,6 +170,18 @@ main(ac, av)
 
 	switch (f_mode) {
 	case MODE_CMDDUMP:
+		error = sysctldump(f_policy ? SADB_X_SPDDUMP : SADB_DUMP,
+		    SADB_SATYPE_UNSPEC);
+		if (error == 0)
+			break;
+		if (error < 0) {
+			if (errno == ENOENT) {
+				printf("No S%cD entries.\n",
+				    f_policy ? 'P' : 'A');
+				break;
+			} else if (errno != 0)
+				err(1, "sysctl");
+		}
 		sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP);
 		break;
 	case MODE_CMDFLUSH:
@@ -443,6 +459,49 @@ postproc(msg, len)
 	}
 
 	return(0);
+}
+
+int
+sysctldump(type, satype)
+	u_int type;
+	u_int8_t satype;
+{
+	int mib[] = { CTL_NET, PF_KEY, KEYCTL_DUMPSA, 0 };
+	size_t len, l;
+	char *buf, *p, *ep;
+	struct sadb_msg *msg;
+
+	if (type == SADB_DUMP) {
+		mib[2] = KEYCTL_DUMPSA;
+		mib[3] = satype;
+		l = 4;
+	} else if (type == SADB_X_SPDDUMP) {
+		mib[2] = KEYCTL_DUMPSP;
+		l = 3;
+	} else
+		return (EINVAL);
+
+	if (sysctl(mib, l, NULL, &len, NULL, 0) < 0)
+		return (-1);
+	buf = malloc(len);
+	if (!buf)
+		return (ENOBUFS);
+	if (sysctl(mib, l, buf, &len, NULL, 0) < 0) {
+		free(buf);
+		return (-1);
+	}
+
+	p = buf;
+	ep = buf + len;
+	while (p < ep) {
+		msg = (struct sadb_msg *)p;
+		l = PFKEY_UNUNIT64(msg->sadb_msg_len);
+		postproc(msg, l);
+		p += l;
+	}
+
+	free(buf);
+	return (0);
 }
 
 /*------------------------------------------------------------*/

--Multipart_Thu_Mar_17_01:10:38_2005-1
Content-Type: text/plain; charset=US-ASCII

--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume@mahoroba.org  ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/

--Multipart_Thu_Mar_17_01:10:38_2005-1--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ygek6o7inb5.wl%ume>