Module Name: src
Committed By: knakahara
Date: Wed Dec 14 11:19:15 UTC 2016
Modified Files:
src/sys/net: if_etherip.h if_gif.c if_gif.h
src/sys/netinet: in_gif.c
src/sys/netinet6: in6_gif.c
Log Message:
fix race of gif_softc->gif_ro when we send multiple flows over gif on
NET_MPSAFE enabled kernel.
make gif_softc->gif_ro percpu as well as ipforward_rt to resolve this race.
and add future TODO comment for etherip(4).
To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/sys/net/if_etherip.h
cvs rdiff -u -r1.123 -r1.124 src/sys/net/if_gif.c
cvs rdiff -u -r1.24 -r1.25 src/sys/net/if_gif.h
cvs rdiff -u -r1.85 -r1.86 src/sys/netinet/in_gif.c
cvs rdiff -u -r1.81 -r1.82 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_etherip.h
diff -u src/sys/net/if_etherip.h:1.11 src/sys/net/if_etherip.h:1.12
--- src/sys/net/if_etherip.h:1.11 Sat Jul 28 00:43:24 2012
+++ src/sys/net/if_etherip.h Wed Dec 14 11:19:15 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_etherip.h,v 1.11 2012/07/28 00:43:24 matt Exp $ */
+/* $NetBSD: if_etherip.h,v 1.12 2016/12/14 11:19:15 knakahara Exp $ */
/*
* Copyright (c) 2006, Hans Rosenfeld <[email protected]>
@@ -46,7 +46,11 @@ struct etherip_softc {
struct ethercom sc_ec;
struct sockaddr *sc_src; /* tunnel source address */
struct sockaddr *sc_dst; /* tunnel destination address */
- struct route sc_ro; /* cached inet route */
+ struct route sc_ro; /*
+ * cached inet route
+ * TODO:
+ * we must make percpu when MP-ify
+ */
void *sc_si; /* softintr handle */
LIST_ENTRY(etherip_softc) etherip_list; /* list of etherip tunnels */
};
Index: src/sys/net/if_gif.c
diff -u src/sys/net/if_gif.c:1.123 src/sys/net/if_gif.c:1.124
--- src/sys/net/if_gif.c:1.123 Thu Sep 15 06:59:32 2016
+++ src/sys/net/if_gif.c Wed Dec 14 11:19:15 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gif.c,v 1.123 2016/09/15 06:59:32 knakahara Exp $ */
+/* $NetBSD: if_gif.c,v 1.124 2016/12/14 11:19:15 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.123 2016/09/15 06:59:32 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.124 2016/12/14 11:19:15 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -240,6 +240,9 @@ gif_clone_create(struct if_clone *ifc, i
gifattach0(sc);
+ sc->gif_ro_percpu = percpu_alloc(sizeof(struct route));
+ KASSERTMSG(sc->gif_ro_percpu != NULL,
+ "failed to allocate sc->gif_ro_percpu");
LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
return (0);
}
@@ -271,6 +274,14 @@ gifattach0(struct gif_softc *sc)
bpf_attach(&sc->gif_if, DLT_NULL, sizeof(u_int));
}
+void
+gif_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
+{
+ struct route *ro = p;
+
+ rtcache_free(ro);
+}
+
static int
gif_clone_destroy(struct ifnet *ifp)
{
@@ -281,8 +292,8 @@ gif_clone_destroy(struct ifnet *ifp)
gif_delete_tunnel(&sc->gif_if);
bpf_detach(ifp);
if_detach(ifp);
- rtcache_free(&sc->gif_ro);
-
+ percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
+ percpu_free(sc->gif_ro_percpu, sizeof(struct route));
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.24 src/sys/net/if_gif.h:1.25
--- src/sys/net/if_gif.h:1.24 Fri Jun 24 04:38:12 2016
+++ src/sys/net/if_gif.h Wed Dec 14 11:19:15 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gif.h,v 1.24 2016/06/24 04:38:12 knakahara Exp $ */
+/* $NetBSD: if_gif.h,v 1.25 2016/12/14 11:19:15 knakahara Exp $ */
/* $KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $ */
/*
@@ -38,6 +38,7 @@
#define _NET_IF_GIF_H_
#include <sys/queue.h>
+#include <sys/percpu.h>
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -52,9 +53,7 @@ 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 */
- union {
- struct route gifscr_ro; /* xxx */
- } gifsc_gifscr;
+ percpu_t *gif_ro_percpu;
int gif_flags;
const struct encaptab *encap_cookie4;
const struct encaptab *encap_cookie6;
@@ -62,8 +61,6 @@ struct gif_softc {
};
#define GIF_ROUTE_TTL 10
-#define gif_ro gifsc_gifscr.gifscr_ro
-
#define GIF_MTU (1280) /* Default MTU */
#define GIF_MTU_MIN (1280) /* Minimum MTU */
#define GIF_MTU_MAX (8192) /* Maximum MTU */
@@ -71,6 +68,8 @@ struct gif_softc {
/* Prototypes */
void gif_input(struct mbuf *, int, struct ifnet *);
+void gif_rtcache_free_pc(void *, void *, struct cpu_info *);
+
#ifdef GIF_ENCAPCHECK
int gif_encapcheck(struct mbuf *, int, int, void *);
#endif
Index: src/sys/netinet/in_gif.c
diff -u src/sys/netinet/in_gif.c:1.85 src/sys/netinet/in_gif.c:1.86
--- src/sys/netinet/in_gif.c:1.85 Mon Dec 12 03:55:57 2016
+++ src/sys/netinet/in_gif.c Wed Dec 14 11:19:15 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: in_gif.c,v 1.85 2016/12/12 03:55:57 ozaki-r Exp $ */
+/* $NetBSD: in_gif.c,v 1.86 2016/12/14 11:19:15 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.85 2016/12/12 03:55:57 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.86 2016/12/14 11:19:15 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -83,6 +83,7 @@ int
in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
{
struct rtentry *rt;
+ struct route *ro;
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);
@@ -170,21 +171,26 @@ in_gif_output(struct ifnet *ifp, int fam
bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip));
sockaddr_in_init(&u.dst4, &sin_dst->sin_addr, 0);
- if ((rt = rtcache_lookup(&sc->gif_ro, &u.dst)) == NULL) {
+
+ ro = percpu_getref(sc->gif_ro_percpu);
+ if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) {
+ percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH;
}
/* If the route constitutes infinite encapsulation, punt. */
if (rt->rt_ifp == ifp) {
- rtcache_unref(rt, &sc->gif_ro);
- rtcache_free(&sc->gif_ro);
+ rtcache_unref(rt, ro);
+ rtcache_free(ro);
+ percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH; /*XXX*/
}
- rtcache_unref(rt, &sc->gif_ro);
+ rtcache_unref(rt, ro);
- error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL);
+ error = ip_output(m, NULL, ro, 0, NULL, NULL);
+ percpu_putref(sc->gif_ro_percpu);
return (error);
}
@@ -399,7 +405,7 @@ in_gif_detach(struct gif_softc *sc)
error = in_gif_pause(sc);
- rtcache_free(&sc->gif_ro);
+ percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
return error;
}
Index: src/sys/netinet6/in6_gif.c
diff -u src/sys/netinet6/in6_gif.c:1.81 src/sys/netinet6/in6_gif.c:1.82
--- src/sys/netinet6/in6_gif.c:1.81 Mon Dec 12 03:55:57 2016
+++ src/sys/netinet6/in6_gif.c Wed Dec 14 11:19:15 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_gif.c,v 1.81 2016/12/12 03:55:57 ozaki-r Exp $ */
+/* $NetBSD: in6_gif.c,v 1.82 2016/12/14 11:19:15 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.81 2016/12/12 03:55:57 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.82 2016/12/14 11:19:15 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -86,6 +86,7 @@ int
in6_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
{
struct rtentry *rt;
+ struct route *ro;
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);
@@ -176,20 +177,23 @@ in6_gif_output(struct ifnet *ifp, int fa
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
sockaddr_in6_init(&u.dst6, &sin6_dst->sin6_addr, 0, 0, 0);
- rt = rtcache_lookup(&sc->gif_ro, &u.dst);
+ ro = percpu_getref(sc->gif_ro_percpu);
+ rt = rtcache_lookup(ro, &u.dst);
if (rt == NULL) {
+ percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH;
}
/* If the route constitutes infinite encapsulation, punt. */
if (rt->rt_ifp == ifp) {
- rtcache_unref(rt, &sc->gif_ro);
- rtcache_free(&sc->gif_ro);
+ rtcache_unref(rt, ro);
+ rtcache_free(ro);
+ percpu_putref(sc->gif_ro_percpu);
m_freem(m);
return ENETUNREACH; /* XXX */
}
- rtcache_unref(rt, &sc->gif_ro);
+ rtcache_unref(rt, ro);
#ifdef IPV6_MINMTU
/*
@@ -197,11 +201,11 @@ in6_gif_output(struct ifnet *ifp, int fa
* it is too painful to ask for resend of inner packet, to achieve
* path MTU discovery for encapsulated packets.
*/
- error = ip6_output(m, 0, &sc->gif_ro, IPV6_MINMTU, NULL, NULL, NULL);
+ error = ip6_output(m, 0, ro, IPV6_MINMTU, NULL, NULL, NULL);
#else
- error = ip6_output(m, 0, &sc->gif_ro, 0, NULL, NULL, NULL);
+ error = ip6_output(m, 0, ro, 0, NULL, NULL, NULL);
#endif
-
+ percpu_putref(sc->gif_ro_percpu);
return (error);
}
@@ -402,7 +406,7 @@ in6_gif_detach(struct gif_softc *sc)
error = in6_gif_pause(sc);
- rtcache_free(&sc->gif_ro);
+ percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
return error;
}
@@ -426,6 +430,7 @@ in6_gif_ctlinput(int cmd, const struct s
struct ip6ctlparam *ip6cp = NULL;
struct ip6_hdr *ip6;
const struct sockaddr_in6 *dst6;
+ struct route *ro;
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
@@ -454,13 +459,15 @@ in6_gif_ctlinput(int cmd, const struct s
if (sc->gif_psrc->sa_family != AF_INET6)
return NULL;
- dst6 = satocsin6(rtcache_getdst(&sc->gif_ro));
+ ro = percpu_getref(sc->gif_ro_percpu);
+ dst6 = satocsin6(rtcache_getdst(ro));
/* XXX scope */
if (dst6 == NULL)
;
else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr))
- rtcache_free(&sc->gif_ro);
+ rtcache_free(ro);
+ percpu_putref(sc->gif_ro_percpu);
return NULL;
}