Source-Changes-HG archive

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

[src/trunk]: src/sys/netipsec Added a lookup table to find an sav quickly



details:   https://anonhg.NetBSD.org/src/rev/53a12c8d4550
branches:  trunk
changeset: 322062:53a12c8d4550
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Mon Apr 16 08:56:08 2018 +0000

description:
Added a lookup table to find an sav quickly

key_sad.sahlists doesn't work well for inbound packets because
its key includes source address. For the reason, the
look-up-table for the inbound packets is newly added.
The table has all sav whose state is MATURE or DYING and uses a
key calculated by destination address, protocol, and spi instead
of saidx.

reviewd ozaki-r@n.o, thanks.

diffstat:

 sys/netipsec/key.c   |  195 ++++++++++++++++++++++++++++++++++++--------------
 sys/netipsec/keydb.h |    4 +-
 2 files changed, 144 insertions(+), 55 deletions(-)

diffs (truncated from 355 to 300 lines):

diff -r ce991cb2bc0f -r 53a12c8d4550 sys/netipsec/key.c
--- a/sys/netipsec/key.c        Mon Apr 16 08:52:09 2018 +0000
+++ b/sys/netipsec/key.c        Mon Apr 16 08:56:08 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.251 2018/04/16 08:52:09 yamaguchi Exp $      */
+/*     $NetBSD: key.c,v 1.252 2018/04/16 08:56:08 yamaguchi 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.251 2018/04/16 08:52:09 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.252 2018/04/16 08:56:08 yamaguchi Exp $");
 
 /*
  * This code is referred to RFC 2367
@@ -124,6 +124,10 @@
 #define SAHHASH_NHASH          128
 #endif
 
+#ifndef SAVLUT_NHASH
+#define SAVLUT_NHASH           128
+#endif
+
 percpu_t *pfkeystat_percpu;
 
 /*
@@ -213,10 +217,13 @@
  *   - Multiple saves with the same saidx can exist
  *     - Only one entry has MATURE state and others should be DEAD
  *     - DEAD entries are just ignored from searching
- * - Modifications to the key_sad.sahlists and sah.savlist must be done with
- *   holding key_sad.lock which is a adaptive mutex
- * - Read accesses to the key_sad.sahlists and sah.savlist must be in
- *   pserialize(9) read sections
+ *   - All sav whose state is MATURE or DYING are registered to the lookup
+ *     table called key_sad.savlut in addition to the savlists.
+ *     - The table is used to search an sav without use of saidx.
+ * - Modifications to the key_sad.sahlists, sah.savlist and key_sad.savlut
+ *   must be done with holding key_sad.lock which is a adaptive mutex
+ * - Read accesses to the key_sad.sahlists, sah.savlist and key_sad.savlut
+ *   must be in pserialize(9) read sections
  * - sah's lifetime is managed by localcount(9)
  * - Getting an sah entry
  *   - We get an sah from the key_sad.sahlists
@@ -265,6 +272,8 @@
        kcondvar_t cv_lc;
        struct pslist_head *sahlists;
        u_long sahlistmask;
+       struct pslist_head *savlut;
+       u_long savlutmask;
 
        pserialize_t psz;
        kcondvar_t cv_psz;
@@ -408,6 +417,21 @@
 #define SAVLIST_READER_NEXT(sav)                                       \
        PSLIST_READER_NEXT((sav), struct secasvar, pslist_entry)
 
+/* Macros for key_sad.savlut */
+#define SAVLUT_READER_FOREACH(sav, dst, proto, hash_key)               \
+       PSLIST_READER_FOREACH((sav),                                    \
+       &key_sad.savlut[key_savluthash(dst, proto, hash_key,            \
+                         key_sad.savlutmask)],                         \
+       struct secasvar, pslist_entry_savlut)
+#define SAVLUT_WRITER_INSERT_HEAD(sav)                                 \
+       key_savlut_writer_insert_head((sav))
+#define SAVLUT_WRITER_REMOVE(sav)                                      \
+       do {                                                            \
+               if (!(sav)->savlut_added)                               \
+                       break;                                          \
+               PSLIST_WRITER_REMOVE((sav), pslist_entry_savlut);       \
+               (sav)->savlut_added = false;                            \
+       } while(0)
 
 /* search order for SAs */
        /*
@@ -807,8 +831,13 @@
 static struct workqueue        *key_timehandler_wq;
 static struct work     key_timehandler_wk;
 
+static inline void
+    key_savlut_writer_insert_head(struct secasvar *sav);
 static inline uint32_t
     key_saidxhash(const struct secasindex *, u_long);
+static inline uint32_t
+    key_savluthash(const struct sockaddr *,
+    uint32_t, uint32_t, u_long);
 
 /*
  * Utilities for percpu counters for sadb_lifetime_allocations and
@@ -1219,9 +1248,7 @@
        u_int16_t dport,
        const char* where, int tag)
 {
-       struct secashead *sah;
        struct secasvar *sav;
-       u_int state;
        int chkport;
        int s;
 
@@ -1229,6 +1256,7 @@
        int must_check_alg = 0;
        u_int16_t cpi = 0;
        u_int8_t algo = 0;
+       uint32_t hash_key = spi;
 
        if ((sport != 0) && (dport != 0))
                chkport = PORT_STRICT;
@@ -1251,6 +1279,7 @@
                cpi = (u_int16_t) tmp;
                if (cpi < IPCOMP_CPI_NEGOTIATE_MIN) {
                        algo = (u_int8_t) cpi;
+                       hash_key = algo;
                        must_check_spi = 0;
                        must_check_alg = 1;
                }
@@ -1267,57 +1296,51 @@
         * encrypted so we can't check internal IP header.
         */
        s = pserialize_read_enter();
-       SAHLIST_READER_FOREACH(sah) {
-               /* search valid state */
-               SASTATE_USABLE_FOREACH(state) {
-                       SAVLIST_READER_FOREACH(sav, sah, state) {
-                               KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
-                                   "try match spi %#x, %#x\n",
-                                   ntohl(spi), ntohl(sav->spi));
-                               /* sanity check */
-                               KEY_CHKSASTATE(sav->state, state);
-                               /* do not return entries w/ unusable state */
-                               if (!SADB_SASTATE_USABLE_P(sav)) {
-                                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
-                                           "bad state %d\n", sav->state);
-                                       continue;
-                               }
-                               if (proto != sav->sah->saidx.proto) {
-                                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
-                                           "proto fail %d != %d\n",
-                                           proto, sav->sah->saidx.proto);
-                                       continue;
-                               }
-                               if (must_check_spi && spi != sav->spi) {
-                                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
-                                           "spi fail %#x != %#x\n",
-                                           ntohl(spi), ntohl(sav->spi));
-                                       continue;
-                               }
-                               /* XXX only on the ipcomp case */
-                               if (must_check_alg && algo != sav->alg_comp) {
-                                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
-                                           "algo fail %d != %d\n",
-                                           algo, sav->alg_comp);
-                                       continue;
-                               }
+       SAVLUT_READER_FOREACH(sav, &dst->sa, proto, hash_key) {
+               KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
+                   "try match spi %#x, %#x\n",
+                   ntohl(spi), ntohl(sav->spi));
+
+               /* do not return entries w/ unusable state */
+               if (!SADB_SASTATE_USABLE_P(sav)) {
+                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
+                           "bad state %d\n", sav->state);
+                       continue;
+               }
+               if (proto != sav->sah->saidx.proto) {
+                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
+                           "proto fail %d != %d\n",
+                           proto, sav->sah->saidx.proto);
+                       continue;
+               }
+               if (must_check_spi && spi != sav->spi) {
+                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
+                           "spi fail %#x != %#x\n",
+                           ntohl(spi), ntohl(sav->spi));
+                       continue;
+               }
+               /* XXX only on the ipcomp case */
+               if (must_check_alg && algo != sav->alg_comp) {
+                       KEYDEBUG_PRINTF(KEYDEBUG_MATCH,
+                           "algo fail %d != %d\n",
+                           algo, sav->alg_comp);
+                       continue;
+               }
 
 #if 0  /* don't check src */
        /* Fix port in src->sa */
 
-                               /* check src address */
-                               if (!key_sockaddr_match(&src->sa, &sav->sah->saidx.src.sa, PORT_NONE))
-                                       continue;
+               /* check src address */
+               if (!key_sockaddr_match(&src->sa, &sav->sah->saidx.src.sa, PORT_NONE))
+                       continue;
 #endif
-                               /* fix port of dst address XXX*/
-                               key_porttosaddr(__UNCONST(dst), dport);
-                               /* check dst address */
-                               if (!key_sockaddr_match(&dst->sa, &sav->sah->saidx.dst.sa, chkport))
-                                       continue;
-                               key_sa_ref(sav, where, tag);
-                               goto done;
-                       }
-               }
+               /* fix port of dst address XXX*/
+               key_porttosaddr(__UNCONST(dst), dport);
+               /* check dst address */
+               if (!key_sockaddr_match(&dst->sa, &sav->sah->saidx.dst.sa, chkport))
+                       continue;
+               key_sa_ref(sav, where, tag);
+               goto done;
        }
        sav = NULL;
 done:
@@ -1547,6 +1570,7 @@
        KASSERT(mutex_owned(&key_sad.lock));
 
        SAVLIST_WRITER_REMOVE(sav);
+       SAVLUT_WRITER_REMOVE(sav);
 
        KDASSERT(mutex_ownable(softnet_lock));
        key_sad_pserialize_perform();
@@ -1582,6 +1606,7 @@
        mutex_enter(&key_sad.lock);
        sav->state = SADB_SASTATE_DEAD;
        SAVLIST_WRITER_REMOVE(sav);
+       SAVLUT_WRITER_REMOVE(sav);
        mutex_exit(&key_sad.lock);
 
        /* We cannot unref with holding key_sad.lock */
@@ -5716,6 +5741,7 @@
        newsav->state = SADB_SASTATE_MATURE;
        mutex_enter(&key_sad.lock);
        SAVLIST_WRITER_INSERT_TAIL(sah, SADB_SASTATE_MATURE, newsav);
+       SAVLUT_WRITER_INSERT_HEAD(newsav);
        mutex_exit(&key_sad.lock);
        key_validate_savlist(sah, SADB_SASTATE_MATURE);
 
@@ -5913,6 +5939,7 @@
        newsav->state = SADB_SASTATE_MATURE;
        mutex_enter(&key_sad.lock);
        SAVLIST_WRITER_INSERT_TAIL(sah, SADB_SASTATE_MATURE, newsav);
+       SAVLUT_WRITER_INSERT_HEAD(newsav);
        mutex_exit(&key_sad.lock);
        key_validate_savlist(sah, SADB_SASTATE_MATURE);
 
@@ -8109,6 +8136,8 @@
 
        key_sad.sahlists = hashinit(SAHHASH_NHASH, HASH_PSLIST, true,
            &key_sad.sahlistmask);
+       key_sad.savlut = hashinit(SAVLUT_NHASH, HASH_PSLIST, true,
+           &key_sad.savlutmask);
 
        for (i = 0; i <= SADB_SATYPE_MAX; i++) {
                LIST_INIT(&key_misc.reglist[i]);
@@ -8352,6 +8381,9 @@
        if (_sav == NULL) {
                SAVLIST_WRITER_INSERT_TAIL(sav->sah, state, sav);
        }
+
+       SAVLUT_WRITER_INSERT_HEAD(sav);
+
        key_validate_savlist(sav->sah, state);
 }
 
@@ -8554,6 +8586,28 @@
        }
 }
 
+static inline void
+key_savlut_writer_insert_head(struct secasvar *sav)
+{
+       uint32_t hash_key;
+       uint32_t hash;
+
+       KASSERT(mutex_owned(&key_sad.lock));
+       KASSERT(!sav->savlut_added);
+
+       if (sav->sah->saidx.proto == IPPROTO_IPCOMP)
+               hash_key = sav->alg_comp;
+       else
+               hash_key = sav->spi;
+
+       hash = key_savluthash(&sav->sah->saidx.dst.sa,
+           sav->sah->saidx.proto, hash_key, key_sad.savlutmask);
+
+       PSLIST_WRITER_INSERT_HEAD(&key_sad.savlut[hash], sav,
+           pslist_entry_savlut);
+       sav->savlut_added = true;
+}
+
 /*
  * Calculate hash using protocol, source address,
  * and destination address included in saidx.
@@ -8592,6 +8646,39 @@
        return hash32 & mask;
 }
 



Home | Main Index | Thread Index | Old Index