Module Name: src Committed By: martin Date: Thu Nov 14 15:32:32 UTC 2019
Modified Files: src/sys/netipsec [netbsd-9]: key.c Log Message: Pull up following revision(s) (requested by knakahara in ticket #423): sys/netipsec/key.c: revision 1.268 sys/netipsec/key.c: revision 1.269 Fix SA can be expaired wrongly when there are many SPs. When key_timehandler_spd() spent over one second, the "now" argument of key_timehandler_sad() could be older than sav->created. That caused SA was expired immediately. - Reduce load for IKE negotiations when the system has many IPv6 addresses. e.g. the system has many vlan(4), gif(4) or ipsecif(4) with link local address. To generate a diff of this commit: cvs rdiff -u -r1.265.2.1 -r1.265.2.2 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.265.2.1 src/sys/netipsec/key.c:1.265.2.2 --- src/sys/netipsec/key.c:1.265.2.1 Sun Sep 1 10:49:37 2019 +++ src/sys/netipsec/key.c Thu Nov 14 15:32:32 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.265.2.1 2019/09/01 10:49:37 martin Exp $ */ +/* $NetBSD: key.c,v 1.265.2.2 2019/11/14 15:32:32 martin Exp $ */ /* $FreeBSD: 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.265.2.1 2019/09/01 10:49:37 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.265.2.2 2019/11/14 15:32:32 martin Exp $"); /* * This code is referred to RFC 2367 @@ -4495,30 +4495,34 @@ key_ismyaddr6(const struct sockaddr_in6 bound = curlwp_bind(); s = pserialize_read_enter(); IN6_ADDRLIST_READER_FOREACH(ia) { - bool ingroup; - if (key_sockaddr_match((const struct sockaddr *)&sin6, (const struct sockaddr *)&ia->ia_addr, 0)) { pserialize_read_exit(s); goto ours; } - ia6_acquire(ia, &psref); - pserialize_read_exit(s); - /* - * XXX Multicast - * XXX why do we care about multlicast here while we don't care - * about IPv4 multicast?? - * XXX scope - */ - ingroup = in6_multi_group(&sin6->sin6_addr, ia->ia_ifp); - if (ingroup) { + if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { + bool ingroup; + + ia6_acquire(ia, &psref); + pserialize_read_exit(s); + + /* + * XXX Multicast + * XXX why do we care about multlicast here while we don't care + * about IPv4 multicast?? + * XXX scope + */ + ingroup = in6_multi_group(&sin6->sin6_addr, ia->ia_ifp); + if (ingroup) { + ia6_release(ia, &psref); + goto ours; + } + + s = pserialize_read_enter(); ia6_release(ia, &psref); - goto ours; } - s = pserialize_read_enter(); - ia6_release(ia, &psref); } pserialize_read_exit(s); @@ -4876,14 +4880,20 @@ key_bb_match_withmask(const void *a1, co } static void -key_timehandler_spd(time_t now) +key_timehandler_spd(void) { u_int dir; struct secpolicy *sp; + volatile time_t now; for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { retry: mutex_enter(&key_spd.lock); + /* + * To avoid for sp->created to overtake "now" because of + * wating mutex, set time_uptime here. + */ + now = time_uptime; SPLIST_WRITER_FOREACH(sp, dir) { KASSERT(sp->state != IPSEC_SPSTATE_DEAD); @@ -4917,10 +4927,11 @@ key_timehandler_spd(time_t now) } static void -key_timehandler_sad(time_t now) +key_timehandler_sad(void) { struct secashead *sah; int s; + volatile time_t now; restart: mutex_enter(&key_sad.lock); @@ -4946,6 +4957,10 @@ restart: /* if LARVAL entry doesn't become MATURE, delete it. */ mutex_enter(&key_sad.lock); restart_sav_LARVAL: + /* + * Same as key_timehandler_spd(), set time_uptime here. + */ + now = time_uptime; SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_LARVAL) { if (now - sav->created > key_larval_lifetime) { key_sa_chgstate(sav, SADB_SASTATE_DEAD); @@ -4960,6 +4975,10 @@ restart: */ restart_sav_MATURE: mutex_enter(&key_sad.lock); + /* + * ditto + */ + now = time_uptime; SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_MATURE) { /* we don't need to check. */ if (sav->lft_s == NULL) @@ -5024,6 +5043,10 @@ restart: /* check DYING entry to change status to DEAD. */ mutex_enter(&key_sad.lock); restart_sav_DYING: + /* + * ditto + */ + now = time_uptime; SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_DYING) { /* we don't need to check. */ if (sav->lft_h == NULL) @@ -5090,13 +5113,18 @@ restart: } static void -key_timehandler_acq(time_t now) +key_timehandler_acq(void) { #ifndef IPSEC_NONBLOCK_ACQUIRE struct secacq *acq, *nextacq; + volatile time_t now; restart: mutex_enter(&key_misc.lock); + /* + * Same as key_timehandler_spd(), set time_uptime here. + */ + now = time_uptime; LIST_FOREACH_SAFE(acq, &key_misc.acqlist, chain, nextacq) { if (now - acq->created > key_blockacq_lifetime) { LIST_REMOVE(acq, chain); @@ -5110,10 +5138,11 @@ key_timehandler_acq(time_t now) } static void -key_timehandler_spacq(time_t now) +key_timehandler_spacq(void) { #ifdef notyet struct secspacq *acq, *nextacq; + time_t now = time_uptime; LIST_FOREACH_SAFE(acq, &key_misc.spacqlist, chain, nextacq) { if (now - acq->created > key_blockacq_lifetime) { @@ -5135,15 +5164,14 @@ static unsigned int key_timehandler_work static void key_timehandler_work(struct work *wk, void *arg) { - time_t now = time_uptime; /* We can allow enqueuing another work at this point */ atomic_swap_uint(&key_timehandler_work_enqueued, 0); - key_timehandler_spd(now); - key_timehandler_sad(now); - key_timehandler_acq(now); - key_timehandler_spacq(now); + key_timehandler_spd(); + key_timehandler_sad(); + key_timehandler_acq(); + key_timehandler_spacq(); key_acquire_sendup_pending_mbuf();