summaryrefslogtreecommitdiffstats
path: root/sys/netipsec/key.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2006-05-20 15:35:36 +0000
committerpjd <pjd@FreeBSD.org>2006-05-20 15:35:36 +0000
commitc1590119a64caa45fdd2f78f22fd55031b1ac64b (patch)
tree1843c949666f6d776df903c4d5e852c70db329d5 /sys/netipsec/key.c
parent5c6fb2961cb40a7613265d1860f68c02aff60dae (diff)
downloadFreeBSD-src-c1590119a64caa45fdd2f78f22fd55031b1ac64b.zip
FreeBSD-src-c1590119a64caa45fdd2f78f22fd55031b1ac64b.tar.gz
Prevent disappearing SAD entries by implementing MPsafe refcounting.
"Why didn't he use SECASVAR_LOCK()/SECASVAR_UNLOCK() macros to synchronize access to the secasvar structure's fields?" one may ask. There were two reasons: 1. refcount(9) is faster then mutex(9) synchronization (one atomic operation instead of two). 2. Those macros are not used now at all, so at some point we may decide to remove them entirely. OK'ed by: gnn MFC after: 2 weeks
Diffstat (limited to 'sys/netipsec/key.c')
-rw-r--r--sys/netipsec/key.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 843e71c..be77509 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -54,6 +54,7 @@
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/refcount.h>
#include <sys/syslog.h>
#include <net/if.h>
@@ -502,14 +503,26 @@ static const char *key_getuserfqdn __P((void));
static void key_sa_chgstate __P((struct secasvar *, u_int8_t));
static struct mbuf *key_alloc_mbuf __P((int));
-#define SA_ADDREF(p) do { \
- (p)->refcnt++; \
- IPSEC_ASSERT((p)->refcnt != 0, ("SA refcnt overflow")); \
-} while (0)
-#define SA_DELREF(p) do { \
- IPSEC_ASSERT((p)->refcnt > 0, ("SA refcnt underflow")); \
- (p)->refcnt--; \
-} while (0)
+static __inline void
+sa_initref(struct secasvar *sav)
+{
+
+ refcount_init(&sav->refcnt, 1);
+}
+static __inline void
+sa_addref(struct secasvar *sav)
+{
+
+ refcount_acquire(&sav->refcnt);
+ IPSEC_ASSERT(sav->refcnt != 0, ("SA refcnt overflow"));
+}
+static __inline int
+sa_delref(struct secasvar *sav)
+{
+
+ IPSEC_ASSERT(sav->refcnt > 0, ("SA refcnt underflow"));
+ return (refcount_release(&sav->refcnt));
+}
#define SP_ADDREF(p) do { \
(p)->refcnt++; \
@@ -1000,7 +1013,7 @@ key_do_allocsa_policy(struct secashead *sah, u_int state)
}
}
if (candidate) {
- SA_ADDREF(candidate);
+ sa_addref(candidate);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, candidate->refcnt, candidate));
@@ -1079,7 +1092,7 @@ key_allocsa(
/* check dst address */
if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, 0) != 0)
continue;
- SA_ADDREF(sav);
+ sa_addref(sav);
goto done;
}
}
@@ -1198,16 +1211,16 @@ key_freesav(struct secasvar **psav, const char* where, int tag)
IPSEC_ASSERT(sav != NULL, ("null sav"));
- /* XXX unguarded? */
- SA_DELREF(sav);
-
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
- __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
-
- if (sav->refcnt == 0) {
+ if (sa_delref(sav)) {
+ KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+ printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
+ __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
*psav = NULL;
key_delsav(sav);
+ } else {
+ KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+ printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
+ __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
}
}
@@ -2764,7 +2777,7 @@ key_newsav(m, mhp, sah, errp, where, tag)
/* add to satree */
newsav->sah = sah;
- newsav->refcnt = 1;
+ sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
/* XXX locking??? */
@@ -4822,7 +4835,7 @@ key_getsavbyseq(sah, seq)
KEY_CHKSASTATE(state, sav->state, __func__);
if (sav->seq == seq) {
- SA_ADDREF(sav);
+ sa_addref(sav);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, sav->refcnt, sav));
OpenPOWER on IntegriCloud