Module Name: src
Committed By: snj
Date: Tue Oct 24 08:47:24 UTC 2017
Modified Files:
src/sys/net [netbsd-8]: if_gif.c if_gif.h
src/sys/netinet [netbsd-8]: in_gif.c
src/sys/netinet6 [netbsd-8]: in6_gif.c
Log Message:
Pull up following revision(s) (requested by knahakara in ticket #303):
sys/net/if_gif.c: 1.129-1.130
sys/net/if_gif.h: 1.26-1.27
sys/netinet/in_gif.c: 1.88
sys/netinet6/in6_gif.c: 1.86
add lock for percpu route like l2tp(4).
--
add lock for sclist to exclude ifconfig gifX add/delete and ifconfig gifX tunnel
--
update locking notes.
To generate a diff of this commit:
cvs rdiff -u -r1.126.2.2 -r1.126.2.3 src/sys/net/if_gif.c
cvs rdiff -u -r1.25 -r1.25.8.1 src/sys/net/if_gif.h
cvs rdiff -u -r1.87 -r1.87.8.1 src/sys/netinet/in_gif.c
cvs rdiff -u -r1.85 -r1.85.6.1 src/sys/netinet6/in6_gif.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/net/if_gif.c
diff -u src/sys/net/if_gif.c:1.126.2.2 src/sys/net/if_gif.c:1.126.2.3
--- src/sys/net/if_gif.c:1.126.2.2 Wed Aug 9 05:51:50 2017
+++ src/sys/net/if_gif.c Tue Oct 24 08:47:24 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gif.c,v 1.126.2.2 2017/08/09 05:51:50 snj Exp $ */
+/* $NetBSD: if_gif.c,v 1.126.2.3 2017/10/24 08:47:24 snj Exp $ */
/* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.126.2.2 2017/08/09 05:51:50 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.126.2.3 2017/10/24 08:47:24 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -96,7 +96,14 @@ __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1
/*
* gif global variable definitions
*/
-static LIST_HEAD(, gif_softc) gif_softc_list;
+LIST_HEAD(gif_sclist, gif_softc);
+static struct {
+ struct gif_sclist list;
+ kmutex_t lock;
+} gif_softcs __cacheline_aligned;
+
+static void gif_ro_init_pc(void *, void *, struct cpu_info *);
+static void gif_ro_fini_pc(void *, void *, struct cpu_info *);
static void gifattach0(struct gif_softc *);
static int gif_output(struct ifnet *, struct mbuf *,
@@ -205,7 +212,8 @@ static void
gifinit(void)
{
- LIST_INIT(&gif_softc_list);
+ mutex_init(&gif_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
+ LIST_INIT(&gif_softcs.list);
if_clone_attach(&gif_cloner);
gif_sysctl_setup();
@@ -216,8 +224,11 @@ gifdetach(void)
{
int error = 0;
- if (!LIST_EMPTY(&gif_softc_list))
+ mutex_enter(&gif_softcs.lock);
+ if (!LIST_EMPTY(&gif_softcs.list)) {
+ mutex_exit(&gif_softcs.lock);
error = EBUSY;
+ }
if (error == 0) {
if_clone_detach(&gif_cloner);
@@ -238,8 +249,12 @@ gif_clone_create(struct if_clone *ifc, i
gifattach0(sc);
- sc->gif_ro_percpu = percpu_alloc(sizeof(struct route));
- LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
+ sc->gif_ro_percpu = percpu_alloc(sizeof(struct gif_ro));
+ percpu_foreach(sc->gif_ro_percpu, gif_ro_init_pc, NULL);
+
+ mutex_enter(&gif_softcs.lock);
+ LIST_INSERT_HEAD(&gif_softcs.list, sc, gif_list);
+ mutex_exit(&gif_softcs.lock);
return (0);
}
@@ -270,12 +285,30 @@ gifattach0(struct gif_softc *sc)
bpf_attach(&sc->gif_if, DLT_NULL, sizeof(u_int));
}
+static void
+gif_ro_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
+{
+ struct gif_ro *gro = p;
+
+ mutex_init(&gro->gr_lock, MUTEX_DEFAULT, IPL_NONE);
+}
+
+static void
+gif_ro_fini_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
+{
+ struct gif_ro *gro = p;
+
+ rtcache_free(&gro->gr_ro);
+
+ mutex_destroy(&gro->gr_lock);
+}
+
void
gif_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
{
- struct route *ro = p;
+ struct gif_ro *gro = p;
- rtcache_free(ro);
+ rtcache_free(&gro->gr_ro);
}
static int
@@ -288,8 +321,10 @@ gif_clone_destroy(struct ifnet *ifp)
gif_delete_tunnel(&sc->gif_if);
bpf_detach(ifp);
if_detach(ifp);
- percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
- percpu_free(sc->gif_ro_percpu, sizeof(struct route));
+
+ percpu_foreach(sc->gif_ro_percpu, gif_ro_fini_pc, NULL);
+ percpu_free(sc->gif_ro_percpu, sizeof(struct gif_ro));
+
kmem_free(sc, sizeof(struct gif_softc));
return (0);
@@ -969,7 +1004,8 @@ gif_set_tunnel(struct ifnet *ifp, struct
return error;
}
- LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
+ mutex_enter(&gif_softcs.lock);
+ LIST_FOREACH(sc2, &gif_softcs.list, gif_list) {
if (sc2 == sc)
continue;
if (!sc2->gif_pdst || !sc2->gif_psrc)
@@ -978,12 +1014,14 @@ gif_set_tunnel(struct ifnet *ifp, struct
if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 &&
sockaddr_cmp(sc2->gif_psrc, src) == 0) {
/* continue to use the old configureation. */
+ mutex_exit(&gif_softcs.lock);
error = EADDRNOTAVAIL;
goto out;
}
/* XXX both end must be valid? (I mean, not 0.0.0.0) */
}
+ mutex_exit(&gif_softcs.lock);
nsrc = sockaddr_dup(src, M_WAITOK);
ndst = sockaddr_dup(dst, M_WAITOK);
Index: src/sys/net/if_gif.h
diff -u src/sys/net/if_gif.h:1.25 src/sys/net/if_gif.h:1.25.8.1
--- src/sys/net/if_gif.h:1.25 Wed Dec 14 11:19:15 2016
+++ src/sys/net/if_gif.h Tue Oct 24 08:47:24 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gif.h,v 1.25 2016/12/14 11:19:15 knakahara Exp $ */
+/* $NetBSD: if_gif.h,v 1.25.8.1 2017/10/24 08:47:24 snj Exp $ */
/* $KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $ */
/*
@@ -49,11 +49,16 @@
struct encaptab;
+struct gif_ro {
+ struct route gr_ro;
+ kmutex_t gr_lock;
+};
+
struct gif_softc {
struct ifnet gif_if; /* common area - must be at the top */
struct sockaddr *gif_psrc; /* Physical src addr */
struct sockaddr *gif_pdst; /* Physical dst addr */
- percpu_t *gif_ro_percpu;
+ percpu_t *gif_ro_percpu; /* struct gif_ro */
int gif_flags;
const struct encaptab *encap_cookie4;
const struct encaptab *encap_cookie6;
@@ -76,6 +81,17 @@ int gif_encapcheck(struct mbuf *, int, i
/*
* Locking notes:
- * - All members of struct si_sync are protected by si_lock (an adaptive mutex)
+ * + gif_softc_list is protected by gif_softcs.lock (an adaptive mutex)
+ * gif_softc_list is list of all gif_softcs. It is used by ioctl
+ * context only.
+ * + Members of struct gif_softc except for gif_ro_percpu are protected by
+ * - encap_lock for writer
+ * - stopping processing when writer begin to run
+ * for reader(Tx and Rx processing)
+ * + Each CPU's gif_ro.gr_ro of gif_ro_percpu are protected by
+ * percpu'ed gif_ro.gr_lock.
+ *
+ * Locking order:
+ * - encap_lock => gif_softcs.lock
*/
#endif /* !_NET_IF_GIF_H_ */
Index: src/sys/netinet/in_gif.c
diff -u src/sys/netinet/in_gif.c:1.87 src/sys/netinet/in_gif.c:1.87.8.1
--- src/sys/netinet/in_gif.c:1.87 Fri Jan 6 03:25:13 2017
+++ src/sys/netinet/in_gif.c Tue Oct 24 08:47:24 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in_gif.c,v 1.87 2017/01/06 03:25:13 knakahara Exp $ */
+/* $NetBSD: in_gif.c,v 1.87.8.1 2017/10/24 08:47:24 snj Exp $ */
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.87 2017/01/06 03:25:13 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.87.8.1 2017/10/24 08:47:24 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -84,6 +84,7 @@ in_gif_output(struct ifnet *ifp, int fam
{
struct rtentry *rt;
struct route *ro;
+ struct gif_ro *gro;
struct gif_softc *sc = ifp->if_softc;
struct sockaddr_in *sin_src = satosin(sc->gif_psrc);
struct sockaddr_in *sin_dst = satosin(sc->gif_pdst);
@@ -166,8 +167,11 @@ in_gif_output(struct ifnet *ifp, int fam
return ENOBUFS;
bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip));
- ro = percpu_getref(sc->gif_ro_percpu);
+ gro = percpu_getref(sc->gif_ro_percpu);
+ mutex_enter(&gro->gr_lock);
+ ro = &gro->gr_ro;
if ((rt = rtcache_lookup(ro, sc->gif_pdst)) == NULL) {
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH;
@@ -177,6 +181,7 @@ in_gif_output(struct ifnet *ifp, int fam
if (rt->rt_ifp == ifp) {
rtcache_unref(rt, ro);
rtcache_free(ro);
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH; /*XXX*/
@@ -184,6 +189,7 @@ in_gif_output(struct ifnet *ifp, int fam
rtcache_unref(rt, ro);
error = ip_output(m, NULL, ro, 0, NULL, NULL);
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
return (error);
}
Index: src/sys/netinet6/in6_gif.c
diff -u src/sys/netinet6/in6_gif.c:1.85 src/sys/netinet6/in6_gif.c:1.85.6.1
--- src/sys/netinet6/in6_gif.c:1.85 Mon Jan 16 15:44:47 2017
+++ src/sys/netinet6/in6_gif.c Tue Oct 24 08:47:24 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_gif.c,v 1.85 2017/01/16 15:44:47 christos Exp $ */
+/* $NetBSD: in6_gif.c,v 1.85.6.1 2017/10/24 08:47:24 snj Exp $ */
/* $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.85 2017/01/16 15:44:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.85.6.1 2017/10/24 08:47:24 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -87,6 +87,7 @@ in6_gif_output(struct ifnet *ifp, int fa
{
struct rtentry *rt;
struct route *ro;
+ struct gif_ro *gro;
struct gif_softc *sc = ifp->if_softc;
struct sockaddr_in6 *sin6_src = satosin6(sc->gif_psrc);
struct sockaddr_in6 *sin6_dst = satosin6(sc->gif_pdst);
@@ -172,9 +173,12 @@ in6_gif_output(struct ifnet *ifp, int fa
ip6->ip6_flow &= ~ntohl(0xff00000);
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
- ro = percpu_getref(sc->gif_ro_percpu);
+ gro = percpu_getref(sc->gif_ro_percpu);
+ mutex_enter(&gro->gr_lock);
+ ro = &gro->gr_ro;
rt = rtcache_lookup(ro, sc->gif_pdst);
if (rt == NULL) {
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH;
@@ -184,6 +188,7 @@ in6_gif_output(struct ifnet *ifp, int fa
if (rt->rt_ifp == ifp) {
rtcache_unref(rt, ro);
rtcache_free(ro);
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH; /* XXX */
@@ -200,6 +205,7 @@ in6_gif_output(struct ifnet *ifp, int fa
#else
error = ip6_output(m, 0, ro, 0, NULL, NULL, NULL);
#endif
+ mutex_exit(&gro->gr_lock);
percpu_putref(sc->gif_ro_percpu);
return (error);
}