Module Name: src Committed By: ozaki-r Date: Thu Aug 3 06:31:58 UTC 2017
Modified Files: src/sys/netipsec: key.c Log Message: MP-ify SAD slightly - Introduce key_sa_mtx and use it for some list operations - Use pserialize for some list iterations To generate a diff of this commit: cvs rdiff -u -r1.204 -r1.205 src/sys/netipsec/key.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netipsec/key.c diff -u src/sys/netipsec/key.c:1.204 src/sys/netipsec/key.c:1.205 --- src/sys/netipsec/key.c:1.204 Thu Aug 3 06:31:16 2017 +++ src/sys/netipsec/key.c Thu Aug 3 06:31:58 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.204 2017/08/03 06:31:16 ozaki-r Exp $ */ +/* $NetBSD: key.c,v 1.205 2017/08/03 06:31:58 ozaki-r Exp $ */ /* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.204 2017/08/03 06:31:16 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.205 2017/08/03 06:31:58 ozaki-r Exp $"); /* * This code is referd to RFC 2367 @@ -323,6 +323,7 @@ static kmutex_t key_mtx __cacheline_alig static pserialize_t key_psz; static kmutex_t key_sp_mtx __cacheline_aligned; static kcondvar_t key_sp_cv __cacheline_aligned; +static kmutex_t key_sa_mtx __cacheline_aligned; /* search order for SAs */ /* @@ -986,14 +987,16 @@ static struct secasvar * key_lookup_sa_bysaidx(const struct secasindex *saidx) { struct secashead *sah; - struct secasvar *sav; + struct secasvar *sav = NULL; u_int stateidx, state; const u_int *saorder_state_valid; int arraysize; + int s; + s = pserialize_read_enter(); sah = key_getsah(saidx, CMP_MODE_REQID); if (sah == NULL) - return NULL; + goto out; /* * search a valid state list for outbound packet. @@ -1029,11 +1032,13 @@ key_lookup_sa_bysaidx(const struct secas KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP, "DP cause refcnt++:%d SA:%p\n", sav->refcnt, sav); - return sav; + break; } } +out: + pserialize_read_exit(s); - return NULL; + return sav; } #if 0 @@ -1166,7 +1171,6 @@ key_lookup_sa( * IPsec tunnel packet is received. But ESP tunnel mode is * encrypted so we can't check internal IP header. */ - s = splsoftnet(); /*called from softclock()*/ if (key_prefered_oldsa) { saorder_state_valid = saorder_state_valid_prefer_old; arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); @@ -1174,6 +1178,7 @@ key_lookup_sa( saorder_state_valid = saorder_state_valid_prefer_new; arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); } + s = pserialize_read_enter(); SAHLIST_READER_FOREACH(sah) { /* search valid state */ for (stateidx = 0; stateidx < arraysize; stateidx++) { @@ -1229,7 +1234,7 @@ key_lookup_sa( } sav = NULL; done: - splx(s); + pserialize_read_exit(s); KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP, "DP return SA:%p; refcnt %u\n", sav, sav ? sav->refcnt : 0); @@ -1241,11 +1246,13 @@ key_validate_savlist(const struct secash { #ifdef DEBUG struct secasvar *sav, *next; + int s; /* * The list should be sorted by lft_c->sadb_lifetime_addtime * in ascending order. */ + s = pserialize_read_enter(); SAVLIST_READER_FOREACH(sav, sah, state) { next = SAVLIST_READER_NEXT(sav); if (next != NULL && @@ -1258,6 +1265,7 @@ key_validate_savlist(const struct secash next->lft_c->sadb_lifetime_addtime); } } + pserialize_read_exit(s); #endif } @@ -2915,7 +2923,9 @@ key_newsah(const struct secasindex *said /* add to saidxtree */ newsah->state = SADB_SASTATE_MATURE; SAHLIST_ENTRY_INIT(newsah); + mutex_enter(&key_sa_mtx); SAHLIST_WRITER_INSERT_HEAD(newsah); + mutex_exit(&key_sa_mtx); return newsah; } @@ -3154,10 +3164,12 @@ key_checkspidup(const struct secasindex static struct secasvar * key_getsavbyspi(struct secashead *sah, u_int32_t spi) { - struct secasvar *sav; + struct secasvar *sav = NULL; u_int state; + int s; /* search all status */ + s = pserialize_read_enter(); SASTATE_ALIVE_FOREACH(state) { SAVLIST_READER_FOREACH(sav, sah, state) { /* sanity check */ @@ -3170,12 +3182,14 @@ key_getsavbyspi(struct secashead *sah, u if (sav->spi == spi) { SA_ADDREF(sav); - return sav; + goto out; } } } +out: + pserialize_read_exit(s); - return NULL; + return sav; } /* @@ -4962,7 +4976,9 @@ key_api_getspi(struct socket *so, struct newsav->sah = sah; newsav->state = SADB_SASTATE_LARVAL; SAVLIST_ENTRY_INIT(newsav); + mutex_enter(&key_sa_mtx); SAVLIST_WRITER_INSERT_TAIL(sah, SADB_SASTATE_LARVAL, newsav); + mutex_exit(&key_sa_mtx); key_validate_savlist(sah, SADB_SASTATE_LARVAL); #ifndef IPSEC_NONBLOCK_ACQUIRE @@ -5440,10 +5456,12 @@ key_getsavbyseq(struct secashead *sah, u { struct secasvar *sav; u_int state; + int s; state = SADB_SASTATE_LARVAL; /* search SAD with sequence number ? */ + s = pserialize_read_enter(); SAVLIST_READER_FOREACH(sav, sah, state) { KEY_CHKSASTATE(state, sav->state); @@ -5452,11 +5470,12 @@ key_getsavbyseq(struct secashead *sah, u KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP, "DP cause refcnt++:%d SA:%p\n", sav->refcnt, sav); - return sav; + break; } } + pserialize_read_exit(s); - return NULL; + return sav; } #endif @@ -7047,6 +7066,8 @@ key_setdump_chain(u_int8_t req_satype, i int cnt; struct mbuf *m, *n, *prev; + KASSERT(mutex_owned(&key_sa_mtx)); + *lenp = 0; /* map satype to proto */ @@ -7058,13 +7079,13 @@ key_setdump_chain(u_int8_t req_satype, i /* count sav entries to be sent to userland. */ cnt = 0; - SAHLIST_READER_FOREACH(sah) { + SAHLIST_WRITER_FOREACH(sah) { if (req_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; SASTATE_ANY_FOREACH(state) { - SAVLIST_READER_FOREACH(sav, sah, state) { + SAVLIST_WRITER_FOREACH(sav, sah, state) { cnt++; } } @@ -7078,7 +7099,7 @@ key_setdump_chain(u_int8_t req_satype, i /* send this to the userland, one at a time. */ m = NULL; prev = m; - SAHLIST_READER_FOREACH(sah) { + SAHLIST_WRITER_FOREACH(sah) { if (req_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; @@ -7092,7 +7113,7 @@ key_setdump_chain(u_int8_t req_satype, i } SASTATE_ANY_FOREACH(state) { - SAVLIST_READER_FOREACH(sav, sah, state) { + SAVLIST_WRITER_FOREACH(sav, sah, state) { n = key_setdumpsa(sav, SADB_DUMP, satype, --cnt, pid); if (!n) { @@ -7144,7 +7165,6 @@ key_api_dump(struct socket *so, struct m u_int16_t proto; u_int8_t satype; struct mbuf *n; - int s; int error, len, ok; /* map satype to proto */ @@ -7166,9 +7186,9 @@ key_api_dump(struct socket *so, struct m return key_senderror(so, m0, ENOBUFS); } - s = splsoftnet(); + mutex_enter(&key_sa_mtx); n = key_setdump_chain(satype, &error, &len, mhp->msg->sadb_msg_pid); - splx(s); + mutex_exit(&key_sa_mtx); if (n == NULL) { return key_senderror(so, m0, ENOENT); @@ -7727,6 +7747,7 @@ key_do_init(void) key_psz = pserialize_create(); mutex_init(&key_sp_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&key_sp_cv, "key_sp"); + mutex_init(&key_sa_mtx, MUTEX_DEFAULT, IPL_NONE); pfkeystat_percpu = percpu_alloc(sizeof(uint64_t) * PFKEY_NSTATS); @@ -8021,6 +8042,8 @@ key_setdump(u_int8_t req_satype, int *er int cnt; struct mbuf *m, *n; + KASSERT(mutex_owned(&key_sa_mtx)); + /* map satype to proto */ proto = key_satype2proto(req_satype); if (proto == 0) { @@ -8030,13 +8053,13 @@ key_setdump(u_int8_t req_satype, int *er /* count sav entries to be sent to the userland. */ cnt = 0; - SAHLIST_READER_FOREACH(sah) { + SAHLIST_WRITER_FOREACH(sah) { if (req_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; SASTATE_ANY_FOREACH(state) { - SAVLIST_READER_FOREACH(sav, sah, state) { + SAVLIST_WRITER_FOREACH(sav, sah, state) { cnt++; } } @@ -8049,7 +8072,7 @@ key_setdump(u_int8_t req_satype, int *er /* send this to the userland, one at a time. */ m = NULL; - SAHLIST_READER_FOREACH(sah) { + SAHLIST_WRITER_FOREACH(sah) { if (req_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) continue; @@ -8063,7 +8086,7 @@ key_setdump(u_int8_t req_satype, int *er } SASTATE_ANY_FOREACH(state) { - SAVLIST_READER_FOREACH(sav, sah, state) { + SAVLIST_WRITER_FOREACH(sav, sah, state) { n = key_setdumpsa(sav, SADB_DUMP, satype, --cnt, pid); if (!n) { @@ -8180,16 +8203,16 @@ sysctl_net_key_dumpsa(SYSCTLFN_ARGS) int err2 = 0; char *p, *ep; size_t len; - int s, error; + int error; if (newp) return (EPERM); if (namelen != 1) return (EINVAL); - s = splsoftnet(); + mutex_enter(&key_sa_mtx); m = key_setdump(name[0], &error, l->l_proc->p_pid); - splx(s); + mutex_exit(&key_sa_mtx); if (!m) return (error); if (!oldp)