aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Malone <dwmalone@FreeBSD.org>2008-09-25 12:35:01 +0000
committerDavid Malone <dwmalone@FreeBSD.org>2008-09-25 12:35:01 +0000
commit0dae32f2ebcdda4f44f6f16df3447cdb618b61b7 (patch)
tree9cb4ad827715ce5138415ffa2aa2bfd77062a7bc /sys
parent0ae492beb3ff29b2c1e14091e6ef1514668da482 (diff)
downloadsrc-0dae32f2ebcdda4f44f6f16df3447cdb618b61b7.tar.gz
src-0dae32f2ebcdda4f44f6f16df3447cdb618b61b7.zip
Some people's 6to4 routers seem to have been blowing up because of
the unlocked route caching in if_stf. Add a mutex that protects access to cached route. This seemed to fix problems for Pekka Savola. Nick Sayer had similar problems, and in his case completly disabling the route cache seemed to help. Add a sysctl net.link.stf.route_cache that can be used to turn off route caching in if_stf. PR: 122283 MFC after: 2 weeks Tested by: Pekka Savola, Nick Sayer.
Notes
Notes: svn path=/head/; revision=183351
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_stf.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index bc644e9fcef2..4e365d5fdaa9 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -89,6 +89,7 @@
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/sysctl.h>
#include <machine/cpu.h>
#include <sys/malloc.h>
@@ -120,6 +121,13 @@
#include <security/mac/mac_framework.h>
+SYSCTL_DECL(_net_link);
+SYSCTL_NODE(_net_link, IFT_STF, stf, CTLFLAG_RW, 0, "6to4 Interface");
+
+static int stf_route_cache = 1;
+SYSCTL_INT(_net_link_stf, OID_AUTO, route_cache, CTLFLAG_RW,
+ &stf_route_cache, 0, "Caching of IPv4 routes for 6to4 Output");
+
#define STFNAME "stf"
#define STFUNIT 0
@@ -138,15 +146,15 @@ struct stf_softc {
struct route_in6 __sc_ro6; /* just for safety */
} __sc_ro46;
#define sc_ro __sc_ro46.__sc_ro4
+ struct mtx sc_ro_mtx;
u_int sc_fibnum;
const struct encaptab *encap_cookie;
};
#define STF2IFP(sc) ((sc)->sc_ifp)
/*
- * XXXRW: Note that mutable fields in the softc are not currently locked:
- * in particular, sc_ro needs to be protected from concurrent entrance
- * of stf_output().
+ * Note that mutable fields in the softc are not currently locked.
+ * We do lock sc_ro in stf_output though.
*/
static MALLOC_DEFINE(M_STF, STFNAME, "6to4 Tunnel Interface");
static const int ip_stf_ttl = 40;
@@ -232,6 +240,7 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_dname = ifc->ifc_name;
ifp->if_dunit = IF_DUNIT_NONE;
+ mtx_init(&(sc)->sc_ro_mtx, "stf ro", NULL, MTX_DEF);
sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
stf_encapcheck, &in_stf_protosw, sc);
if (sc->encap_cookie == NULL) {
@@ -258,6 +267,7 @@ stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
err = encap_detach(sc->encap_cookie);
KASSERT(err == 0, ("Unexpected error detaching encap_cookie"));
+ mtx_destroy(&(sc)->sc_ro_mtx);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
@@ -399,6 +409,7 @@ stf_output(ifp, m, dst, rt)
{
struct stf_softc *sc;
struct sockaddr_in6 *dst6;
+ struct route *cached_route;
struct in_addr in4;
caddr_t ptr;
struct sockaddr_in *dst4;
@@ -407,9 +418,9 @@ stf_output(ifp, m, dst, rt)
struct ip6_hdr *ip6;
struct in6_ifaddr *ia6;
u_int32_t af;
-#ifdef MAC
int error;
+#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error) {
m_freem(m);
@@ -508,9 +519,15 @@ stf_output(ifp, m, dst, rt)
else
ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
+ if (!stf_route_cache) {
+ cached_route = NULL;
+ goto sendit;
+ }
+
/*
- * XXXRW: Locking of sc_ro required.
+ * Do we have a cached route?
*/
+ mtx_lock(&(sc)->sc_ro_mtx);
dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
if (dst4->sin_family != AF_INET ||
bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) {
@@ -528,14 +545,21 @@ stf_output(ifp, m, dst, rt)
rtalloc_fib(&sc->sc_ro, sc->sc_fibnum);
if (sc->sc_ro.ro_rt == NULL) {
m_freem(m);
+ mtx_unlock(&(sc)->sc_ro_mtx);
ifp->if_oerrors++;
return ENETUNREACH;
}
}
+ cached_route = &sc->sc_ro;
+sendit:
M_SETFIB(m, sc->sc_fibnum);
ifp->if_opackets++;
- return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL);
+ error = ip_output(m, NULL, cached_route, 0, NULL, NULL);
+
+ if (cached_route != NULL)
+ mtx_unlock(&(sc)->sc_ro_mtx);
+ return error;
}
static int