Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netipsec Avoid examining freshness of sav on packet proc...



details:   https://anonhg.NetBSD.org/src/rev/e1866015868a
branches:  trunk
changeset: 825428:e1866015868a
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Jul 14 01:30:08 2017 +0000

description:
Avoid examining freshness of sav on packet processing

If a sav list is sorted (by lft_c->sadb_lifetime_addtime) in advance,
we don't need to examine each sav and also don't need to delete one
on the fly and send up a message. Fortunately every sav lists are sorted
as we need.

Added key_validate_savlist validates that each sav list is surely sorted
(run only if DEBUG because it's not cheap).

diffstat:

 sys/netipsec/key.c |  124 ++++++++++++++++++++--------------------------------
 1 files changed, 48 insertions(+), 76 deletions(-)

diffs (200 lines):

diff -r 67f918e8b4e2 -r e1866015868a sys/netipsec/key.c
--- a/sys/netipsec/key.c        Fri Jul 14 01:24:23 2017 +0000
+++ b/sys/netipsec/key.c        Fri Jul 14 01:30:08 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.182 2017/07/14 01:24:23 ozaki-r Exp $        */
+/*     $NetBSD: key.c,v 1.183 2017/07/14 01:30:08 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.182 2017/07/14 01:24:23 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.183 2017/07/14 01:30:08 ozaki-r Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -391,7 +391,6 @@
 static void key_freeso(struct socket *);
 static void key_freesp_so(struct secpolicy **);
 #endif
-static struct secasvar *key_do_allocsa_policy (struct secashead *, u_int);
 static void key_delsp (struct secpolicy *);
 static struct secpolicy *key_getsp (const struct secpolicyindex *);
 static struct secpolicy *key_getspbyid (u_int32_t);
@@ -958,14 +957,29 @@
 
                state = saorder_state_valid[stateidx];
 
-               sav = key_do_allocsa_policy(sah, state);
-               if (sav != NULL)
+               if (key_prefered_oldsa)
+                       sav = LIST_FIRST(&sah->savtree[state]);
+               else {
+                       /* XXX need O(1) lookup */
+                       struct secasvar *last = NULL;
+
+                       LIST_FOREACH(sav, &sah->savtree[state], chain)
+                               last = sav;
+                       sav = last;
+               }
+               if (sav != NULL) {
+                       SA_ADDREF(sav);
+                       KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP,
+                           "DP cause refcnt++:%d SA:%p\n",
+                           sav->refcnt, sav);
                        return sav;
+               }
        }
 
        return NULL;
 }
 
+#if 0
 static void
 key_sendup_message_delete(struct secasvar *sav)
 {
@@ -1019,77 +1033,7 @@
        if (result)
                m_freem(result);
 }
-
-/*
- * searching SAD with direction, protocol, mode and state.
- * called by key_allocsa_policy().
- * OUT:
- *     NULL    : not found
- *     others  : found, pointer to a SA.
- */
-static struct secasvar *
-key_do_allocsa_policy(struct secashead *sah, u_int state)
-{
-       struct secasvar *sav, *candidate, *d;
-
-       /* initilize */
-       candidate = NULL;
-
-       LIST_FOREACH(sav, &sah->savtree[state], chain) {
-               /* sanity check */
-               KEY_CHKSASTATE(sav->state, state);
-
-               /* initialize */
-               if (candidate == NULL) {
-                       candidate = sav;
-                       continue;
-               }
-
-               /* Which SA is the better ? */
-
-               /* sanity check 2 */
-               KASSERT(candidate->lft_c != NULL);
-               KASSERT(sav->lft_c != NULL);
-
-               /* What the best method is to compare ? */
-               if (key_prefered_oldsa) {
-                       if (candidate->lft_c->sadb_lifetime_addtime >
-                           sav->lft_c->sadb_lifetime_addtime) {
-                               candidate = sav;
-                       }
-                       continue;
-                       /*NOTREACHED*/
-               }
-
-               /* prefered new sa rather than old sa */
-               if (candidate->lft_c->sadb_lifetime_addtime <
-                   sav->lft_c->sadb_lifetime_addtime) {
-                       d = candidate;
-                       candidate = sav;
-               } else
-                       d = sav;
-
-               /*
-                * prepared to delete the SA when there is more
-                * suitable candidate and the lifetime of the SA is not
-                * permanent.
-                */
-               if (d->lft_c->sadb_lifetime_addtime != 0) {
-                       key_sa_chgstate(d, SADB_SASTATE_DEAD);
-                       KASSERT(d->refcnt > 0);
-                       key_sendup_message_delete(d);
-                       KEY_FREESAV(&d);
-               }
-       }
-
-       if (candidate) {
-               SA_ADDREF(candidate);
-               KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP,
-                   "DP cause refcnt++:%d SA:%p\n",
-                   candidate->refcnt, candidate);
-       }
-       return candidate;
-}
+#endif
 
 /*
  * allocating a usable SA entry for a *INBOUND* packet.
@@ -1235,6 +1179,30 @@
        return sav;
 }
 
+static void
+key_validate_savlist(const struct secashead *sah, const u_int state)
+{
+#ifdef DEBUG
+       struct secasvar *sav, *next;
+
+       /*
+        * The list should be sorted by lft_c->sadb_lifetime_addtime
+        * in ascending order.
+        */
+       LIST_FOREACH_SAFE(sav, &sah->savtree[state], chain, next) {
+               if (next != NULL &&
+                   sav->lft_c != NULL && next->lft_c != NULL) {
+                       KDASSERTMSG(sav->lft_c->sadb_lifetime_addtime <=
+                           next->lft_c->sadb_lifetime_addtime,
+                           "savlist is not sorted: sah=%p, state=%d, "
+                           "sav=%lu, next=%lu", sah, state,
+                           sav->lft_c->sadb_lifetime_addtime,
+                           next->lft_c->sadb_lifetime_addtime);
+               }
+       }
+#endif
+}
+
 void
 key_sp_ref(struct secpolicy *sp, const char* where, int tag)
 {
@@ -4868,6 +4836,7 @@
        newsav->state = SADB_SASTATE_LARVAL;
        LIST_INSERT_TAIL(&newsah->savtree[SADB_SASTATE_LARVAL], newsav,
            secasvar, chain);
+       key_validate_savlist(newsah, SADB_SASTATE_LARVAL);
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
        /* delete the entry in acqtree */
@@ -5307,6 +5276,7 @@
        newsav->state = SADB_SASTATE_MATURE;
        LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_MATURE], newsav,
            secasvar, chain);
+       key_validate_savlist(sah, SADB_SASTATE_MATURE);
 
        key_sa_chgstate(sav, SADB_SASTATE_DEAD);
        KEY_FREESAV(&sav);
@@ -5495,6 +5465,7 @@
        newsav->state = SADB_SASTATE_MATURE;
        LIST_INSERT_TAIL(&newsah->savtree[SADB_SASTATE_MATURE], newsav,
            secasvar, chain);
+       key_validate_savlist(newsah, SADB_SASTATE_MATURE);
 
        /*
         * don't call key_freesav() here, as we would like to keep the SA
@@ -7841,6 +7812,7 @@
 
        sav->state = state;
        LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain);
+       key_validate_savlist(sav->sah, state);
 }
 
 /* XXX too much? */



Home | Main Index | Thread Index | Old Index