Module Name: src Committed By: knakahara Date: Mon Jul 4 04:31:04 UTC 2016
Modified Files: src/sys/netinet: ip_encap.c Log Message: use pserialize(9) and psref(9) (2/2) : ip_encap radix tree care To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.57 src/sys/netinet/ip_encap.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/netinet/ip_encap.c diff -u src/sys/netinet/ip_encap.c:1.56 src/sys/netinet/ip_encap.c:1.57 --- src/sys/netinet/ip_encap.c:1.56 Mon Jul 4 04:29:11 2016 +++ src/sys/netinet/ip_encap.c Mon Jul 4 04:31:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_encap.c,v 1.56 2016/07/04 04:29:11 knakahara Exp $ */ +/* $NetBSD: ip_encap.c,v 1.57 2016/07/04 04:31:04 knakahara Exp $ */ /* $KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $ */ /* @@ -68,7 +68,7 @@ #define USE_RADIX #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.56 2016/07/04 04:29:11 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.57 2016/07/04 04:31:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_mrouting.h" @@ -147,6 +147,7 @@ static struct { #ifdef USE_RADIX struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */ +static bool encap_head_updating = false; #endif static ONCE_DECL(encap_init_control); @@ -221,6 +222,14 @@ encap4_lookup(struct mbuf *m, int off, i s = pserialize_read_enter(); #ifdef USE_RADIX + if (encap_head_updating) { + /* + * Update in progress. Do nothing. + */ + pserialize_read_exit(s); + return NULL; + } + rn = rnh->rnh_matchaddr((void *)&pack, rnh); if (rn && (rn->rn_flags & RNF_ROOT) == 0) { struct encaptab *encapp = (struct encaptab *)rn; @@ -381,6 +390,14 @@ encap6_lookup(struct mbuf *m, int off, i s = pserialize_read_enter(); #ifdef USE_RADIX + if (encap_head_updating) { + /* + * Update in progress. Do nothing. + */ + pserialize_read_exit(s); + return NULL; + } + rn = rnh->rnh_matchaddr((void *)&pack, rnh); if (rn && (rn->rn_flags & RNF_ROOT) == 0) { struct encaptab *encapp = (struct encaptab *)rn; @@ -498,13 +515,25 @@ encap_add(struct encaptab *ep) #ifdef USE_RADIX if (!ep->func && rnh) { + /* Disable access to the radix tree for reader. */ + encap_head_updating = true; /* Wait for all readers to drain. */ pserialize_perform(encaptab.psz); if (!rnh->rnh_addaddr((void *)ep->addrpack, (void *)ep->maskpack, rnh, ep->nodes)) { + encap_head_updating = false; return EEXIST; } + + /* + * The ep added to the radix tree must be skipped while + * encap[46]_lookup walks encaptab list. In other words, + * encap_add() does not need to care whether the ep has + * been added encaptab list or not yet. + * So, we can re-enable access to the radix tree for now. + */ + encap_head_updating = false; } #endif PSLIST_WRITER_INSERT_HEAD(&encap_table, ep, chain); @@ -528,12 +557,23 @@ encap_remove(struct encaptab *ep) #ifdef USE_RADIX if (!ep->func && rnh) { + /* Disable access to the radix tree for reader. */ + encap_head_updating = true; /* Wait for all readers to drain. */ pserialize_perform(encaptab.psz); if (!rnh->rnh_deladdr((void *)ep->addrpack, (void *)ep->maskpack, rnh)) error = ESRCH; + + /* + * The ep added to the radix tree must be skipped while + * encap[46]_lookup walks encaptab list. In other words, + * encap_add() does not need to care whether the ep has + * been added encaptab list or not yet. + * So, we can re-enable access to the radix tree for now. + */ + encap_head_updating = false; } #endif PSLIST_WRITER_REMOVE(ep, chain);