svn commit: r308993 - projects/ipsec/sys/netipsec
Andrey V. Elsukov
ae at FreeBSD.org
Tue Nov 22 12:23:56 UTC 2016
Author: ae
Date: Tue Nov 22 12:23:55 2016
New Revision: 308993
URL: https://svnweb.freebsd.org/changeset/base/308993
Log:
Update key_newsah() and key_delsah() to reflect changes in SADB.
Now SA head has refcount. Properly initialize refcnt and both
savtree_larval and savtree_alive. Add key_freesah() function to
release refcount and call key_delsah() for last reference.
Modified:
projects/ipsec/sys/netipsec/key.c
Modified: projects/ipsec/sys/netipsec/key.c
==============================================================================
--- projects/ipsec/sys/netipsec/key.c Tue Nov 22 11:56:58 2016 (r308992)
+++ projects/ipsec/sys/netipsec/key.c Tue Nov 22 12:23:55 2016 (r308993)
@@ -2484,74 +2484,59 @@ key_spdexpire(struct secpolicy *sp)
/* %%% SAD management */
/*
- * allocating a memory for new SA head, and copy from the values of mhp.
+ * allocating and initialize new SA head.
* OUT: NULL : failure due to the lack of memory.
* others : pointer to new SA head.
*/
static struct secashead *
key_newsah(struct secasindex *saidx)
{
- struct secashead *newsah;
+ struct secashead *sah;
- IPSEC_ASSERT(saidx != NULL, ("null saidx"));
+ sah = malloc(sizeof(struct secashead), M_IPSEC_SAH,
+ M_NOWAIT | M_ZERO);
+ if (sah == NULL)
+ return (NULL);
+ TAILQ_INIT(&sah->savtree_larval);
+ TAILQ_INIT(&sah->savtree_alive);
+ sah->saidx = *saidx;
+ sah->state = SADB_SASTATE_DEAD;
+ SAH_INITREF(sah);
+
+ KEYDBG(KEY_STAMP,
+ printf("%s: SAH(%p)\n", __func__, sah));
+ KEYDBG(KEY_DATA, kdebug_secash(sah, NULL));
+ return (sah);
+}
+
+static void
+key_freesah(struct secashead **psah)
+{
+ struct secashead *sah = *psah;
- newsah = malloc(sizeof(struct secashead), M_IPSEC_SAH, M_NOWAIT|M_ZERO);
- if (newsah != NULL) {
- int i;
- for (i = 0; i < sizeof(newsah->savtree)/sizeof(newsah->savtree[0]); i++)
- LIST_INIT(&newsah->savtree[i]);
- newsah->saidx = *saidx;
+ if (SAH_DELREF(sah) == 0)
+ return;
- /* add to saidxtree */
- newsah->state = SADB_SASTATE_MATURE;
+ KEYDBG(KEY_STAMP,
+ printf("%s: last reference to SAH(%p)\n", __func__, sah));
+ KEYDBG(KEY_DATA, kdebug_secash(sah, NULL));
- SAHTREE_LOCK();
- LIST_INSERT_HEAD(&V_sahtree, newsah, chain);
- SAHTREE_UNLOCK();
- }
- return(newsah);
+ *psah = NULL;
+ key_delsah(sah);
}
-/*
- * delete SA index and all SA registerd.
- */
static void
key_delsah(struct secashead *sah)
{
- struct secasvar *sav, *nextsav;
- u_int stateidx;
- int zombie = 0;
-
IPSEC_ASSERT(sah != NULL, ("NULL sah"));
- SAHTREE_LOCK_ASSERT();
+ IPSEC_ASSERT(sah->state == SADB_SASTATE_DEAD,
+ ("Attempt to free non DEAD SAH %p", sah));
+ IPSEC_ASSERT(TAILQ_EMPTY(&sah->savtree_larval),
+ ("Attempt to free SAH %p with LARVAL SA", sah));
+ IPSEC_ASSERT(TAILQ_EMPTY(&sah->savtree_alive),
+ ("Attempt to free SAH %p with ALIVE SA", sah));
- /* searching all SA registerd in the secindex. */
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_any);
- stateidx++) {
- u_int state = saorder_state_any[stateidx];
- LIST_FOREACH_SAFE(sav, &sah->savtree[state], chain, nextsav) {
- if (sav->refcnt == 0) {
- /* sanity check */
- KEY_CHKSASTATE(state, sav->state, __func__);
- /*
- * do NOT call KEY_FREESAV here:
- * it will only delete the sav if refcnt == 1,
- * where we already know that refcnt == 0
- */
- key_delsav(sav);
- } else {
- /* give up to delete this sa */
- zombie++;
- }
- }
- }
- if (!zombie) { /* delete only if there are savs */
- /* remove from tree of SA index */
- if (__LIST_CHAINED(sah))
- LIST_REMOVE(sah, chain);
- free(sah, M_IPSEC_SAH);
- }
+ free(sah, M_IPSEC_SAH);
}
/*
More information about the svn-src-projects
mailing list