Module Name:    src
Committed By:   knakahara
Date:           Thu Sep 21 09:42:03 UTC 2017

Modified Files:
        src/sys/net: if_gif.c if_gif.h
        src/sys/netinet: in_gif.c
        src/sys/netinet6: in6_gif.c

Log Message:
add lock for percpu route like l2tp(4).


To generate a diff of this commit:
cvs rdiff -u -r1.128 -r1.129 src/sys/net/if_gif.c
cvs rdiff -u -r1.25 -r1.26 src/sys/net/if_gif.h
cvs rdiff -u -r1.87 -r1.88 src/sys/netinet/in_gif.c
cvs rdiff -u -r1.85 -r1.86 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.128 src/sys/net/if_gif.c:1.129
--- src/sys/net/if_gif.c:1.128	Tue Aug  8 03:14:50 2017
+++ src/sys/net/if_gif.c	Thu Sep 21 09:42:03 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_gif.c,v 1.128 2017/08/08 03:14:50 knakahara Exp $	*/
+/*	$NetBSD: if_gif.c,v 1.129 2017/09/21 09:42:03 knakahara 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.128 2017/08/08 03:14:50 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.129 2017/09/21 09:42:03 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -98,6 +98,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1
  */
 static LIST_HEAD(, gif_softc) gif_softc_list;
 
+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 *,
 			   const struct sockaddr *, const struct rtentry *);
@@ -238,7 +241,9 @@ gif_clone_create(struct if_clone *ifc, i
 
 	gifattach0(sc);
 
-	sc->gif_ro_percpu = percpu_alloc(sizeof(struct route));
+	sc->gif_ro_percpu = percpu_alloc(sizeof(struct gif_ro));
+	percpu_foreach(sc->gif_ro_percpu, gif_ro_init_pc, NULL);
+
 	LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
 	return (0);
 }
@@ -270,12 +275,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 +311,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);

Index: src/sys/net/if_gif.h
diff -u src/sys/net/if_gif.h:1.25 src/sys/net/if_gif.h:1.26
--- src/sys/net/if_gif.h:1.25	Wed Dec 14 11:19:15 2016
+++ src/sys/net/if_gif.h	Thu Sep 21 09:42:03 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.26 2017/09/21 09:42:03 knakahara 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;

Index: src/sys/netinet/in_gif.c
diff -u src/sys/netinet/in_gif.c:1.87 src/sys/netinet/in_gif.c:1.88
--- src/sys/netinet/in_gif.c:1.87	Fri Jan  6 03:25:13 2017
+++ src/sys/netinet/in_gif.c	Thu Sep 21 09:42:03 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.88 2017/09/21 09:42:03 knakahara 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.88 2017/09/21 09:42:03 knakahara 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.86
--- src/sys/netinet6/in6_gif.c:1.85	Mon Jan 16 15:44:47 2017
+++ src/sys/netinet6/in6_gif.c	Thu Sep 21 09:42:03 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.86 2017/09/21 09:42:03 knakahara 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.86 2017/09/21 09:42:03 knakahara 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);
 }

Reply via email to