RELENG_5 and FAST_IPSEC limits
Hajimu UMEMOTO
ume at freebsd.org
Wed Mar 16 08:11:04 PST 2005
Hi,
>>>>> On Tue, 15 Mar 2005 13:23:07 -0800
>>>>> Sam Leffler <sam at 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,
-------------- next part --------------
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);
}
/*------------------------------------------------------------*/
-------------- next part --------------
--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume at mahoroba.org ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/
More information about the freebsd-stable
mailing list