Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys/netipsec Pull up following revision(s) (requested by ...
details: https://anonhg.NetBSD.org/src/rev/fc99c8e17e5b
branches: netbsd-8
changeset: 434936:fc99c8e17e5b
user: martin <martin%NetBSD.org@localhost>
date: Wed Apr 18 14:06:24 2018 +0000
description:
Pull up following revision(s) (requested by yamaguchi in ticket #776):
sys/netipsec/key.c: revision 1.251-1.253
sys/netipsec/keydb.h: revision 1.22
Introduced a hash table to sahlist
An saidx of sah included in the list is unique so that
the search can use a hash list whose hash is calculated by
the saidx to find an sah quickly.
The hash list of the sahlits is used in FreeBSD, too.
reviewed by ozaki-r@n.o, thanks.
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.
Fix panic of SADB when the state of sav is changed in timeout
pointed out by ozaki-r@n.o, thanks
diffstat:
sys/netipsec/key.c | 280 ++++++++++++++++++++++++++++++++++++++------------
sys/netipsec/keydb.h | 4 +-
2 files changed, 217 insertions(+), 67 deletions(-)
diffs (truncated from 467 to 300 lines):
diff -r 0ff6c8fca527 -r fc99c8e17e5b sys/netipsec/key.c
--- a/sys/netipsec/key.c Wed Apr 18 14:01:16 2018 +0000
+++ b/sys/netipsec/key.c Wed Apr 18 14:06:24 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: key.c,v 1.163.2.8 2018/04/16 14:31:44 martin Exp $ */
+/* $NetBSD: key.c,v 1.163.2.9 2018/04/18 14:06:24 martin 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.163.2.8 2018/04/16 14:31:44 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.9 2018/04/18 14:06:24 martin Exp $");
/*
* This code is referred to RFC 2367
@@ -72,6 +72,7 @@
#include <sys/condvar.h>
#include <sys/localcount.h>
#include <sys/pserialize.h>
+#include <sys/hash.h>
#include <net/if.h>
#include <net/route.h>
@@ -122,6 +123,14 @@
#define PORT_LOOSE 1
#define PORT_STRICT 2
+#ifndef SAHHASH_NHASH
+#define SAHHASH_NHASH 128
+#endif
+
+#ifndef SAVLUT_NHASH
+#define SAVLUT_NHASH 128
+#endif
+
percpu_t *pfkeystat_percpu;
/*
@@ -204,20 +213,23 @@
/*
* Locking notes on SAD:
* - Data structures
- * - SAs are managed by the list called key_sad.sahlist and sav lists of sah
- * entries
+ * - SAs are managed by the list called key_sad.sahlists and sav lists of
+ * sah entries
* - An sav is supposed to be an SA from a viewpoint of users
* - A sah has sav lists for each SA state
- * - Multiple sahs with the same saidx can exist
+ * - 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.sahlist and sah.savlist must be done with
- * holding key_sad.lock which is a adaptive mutex
- * - Read accesses to the key_sad.sahlist 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.sahlist
+ * - We get an sah from the key_sad.sahlists
* - Must iterate the list and increment the reference count of a found sah
* (by key_sah_ref) in a pserialize read section
* - A gotten sah must be released after use by key_sah_unref
@@ -261,7 +273,10 @@
static struct {
kmutex_t lock;
kcondvar_t cv_lc;
- struct pslist_head sahlist;
+ struct pslist_head *sahlists;
+ u_long sahlistmask;
+ struct pslist_head *savlut;
+ u_long savlutmask;
pserialize_t psz;
kcondvar_t cv_psz;
@@ -341,13 +356,23 @@
#define SAHLIST_WRITER_REMOVE(sah) \
PSLIST_WRITER_REMOVE((sah), pslist_entry)
#define SAHLIST_READER_FOREACH(sah) \
- PSLIST_READER_FOREACH((sah), &key_sad.sahlist, struct secashead,\
- pslist_entry)
+ for(int _i_sah = 0; _i_sah <= key_sad.sahlistmask; _i_sah++) \
+ PSLIST_READER_FOREACH((sah), &key_sad.sahlists[_i_sah], \
+ struct secashead, pslist_entry)
+#define SAHLIST_READER_FOREACH_SAIDX(sah, saidx) \
+ PSLIST_READER_FOREACH((sah), \
+ &key_sad.sahlists[key_saidxhash((saidx), \
+ key_sad.sahlistmask)], \
+ struct secashead, pslist_entry)
#define SAHLIST_WRITER_FOREACH(sah) \
- PSLIST_WRITER_FOREACH((sah), &key_sad.sahlist, struct secashead,\
- pslist_entry)
+ for(int _i_sah = 0; _i_sah <= key_sad.sahlistmask; _i_sah++) \
+ PSLIST_WRITER_FOREACH((sah), &key_sad.sahlists[_i_sah], \
+ struct secashead, pslist_entry)
#define SAHLIST_WRITER_INSERT_HEAD(sah) \
- PSLIST_WRITER_INSERT_HEAD(&key_sad.sahlist, (sah), pslist_entry)
+ PSLIST_WRITER_INSERT_HEAD( \
+ &key_sad.sahlists[key_saidxhash(&(sah)->saidx, \
+ key_sad.sahlistmask)], \
+ (sah), pslist_entry)
/* Macros for key_sad.sahlist#savlist */
#define SAVLIST_ENTRY_INIT(sav) \
@@ -395,6 +420,23 @@
#define SAVLIST_READER_NEXT(sav) \
PSLIST_READER_NEXT((sav), struct secasvar, pslist_entry)
+/* Macros for key_sad.savlut */
+#define SAVLUT_ENTRY_INIT(sav) \
+ PSLIST_ENTRY_INIT((sav), pslist_entry_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 */
/*
@@ -794,6 +836,14 @@
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
* sadb_lifetime_bytes.
@@ -1203,9 +1253,7 @@
u_int16_t dport,
const char* where, int tag)
{
- struct secashead *sah;
struct secasvar *sav;
- u_int state;
int chkport;
int s;
@@ -1213,6 +1261,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;
@@ -1235,6 +1284,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;
}
@@ -1251,57 +1301,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:
@@ -1393,6 +1437,7 @@
localcount_init(&sav->localcount);
SAVLIST_ENTRY_INIT(sav);
+ SAVLUT_ENTRY_INIT(sav);
}
u_int
@@ -1531,6 +1576,7 @@
KASSERT(mutex_owned(&key_sad.lock));
SAVLIST_WRITER_REMOVE(sav);
+ SAVLUT_WRITER_REMOVE(sav);
KDASSERT(mutex_ownable(softnet_lock));
key_sad_pserialize_perform();
@@ -1566,6 +1612,7 @@
mutex_enter(&key_sad.lock);
sav->state = SADB_SASTATE_DEAD;
SAVLIST_WRITER_REMOVE(sav);
+ SAVLUT_WRITER_REMOVE(sav);
mutex_exit(&key_sad.lock);
Home |
Main Index |
Thread Index |
Old Index