Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys fix race of gif_softc->gif_ro when we send multiple flow...
details: https://anonhg.NetBSD.org/src/rev/9c4a387c6772
branches: trunk
changeset: 349551:9c4a387c6772
user: knakahara <knakahara%NetBSD.org@localhost>
date: Wed Dec 14 11:19:15 2016 +0000
description:
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).
diffstat:
sys/net/if_etherip.h | 8 ++++++--
sys/net/if_gif.c | 19 +++++++++++++++----
sys/net/if_gif.h | 11 +++++------
sys/netinet/in_gif.c | 22 ++++++++++++++--------
sys/netinet6/in6_gif.c | 31 +++++++++++++++++++------------
5 files changed, 59 insertions(+), 32 deletions(-)
diffs (293 lines):
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_etherip.h
--- a/sys/net/if_etherip.h Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_etherip.h Wed Dec 14 11:19:15 2016 +0000
@@ -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 <rosenfeld%grumpf.hope-2000.org@localhost>
@@ -46,7 +46,11 @@
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 */
};
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_gif.c
--- a/sys/net/if_gif.c Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_gif.c Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
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 @@
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_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);
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_gif.h
--- a/sys/net/if_gif.h Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_gif.h Wed Dec 14 11:19:15 2016 +0000
@@ -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 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 @@
};
#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 @@
/* 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
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/netinet/in_gif.c
--- a/sys/netinet/in_gif.c Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/netinet/in_gif.c Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
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 @@
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 @@
error = in_gif_pause(sc);
- rtcache_free(&sc->gif_ro);
+ percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
return error;
}
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/netinet6/in6_gif.c
--- a/sys/netinet6/in6_gif.c Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/netinet6/in6_gif.c Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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;
}
Home |
Main Index |
Thread Index |
Old Index