summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2008-09-25 12:35:01 +0000
committerdwmalone <dwmalone@FreeBSD.org>2008-09-25 12:35:01 +0000
commitaf76980ef5353eee84271a4934c37c01861d8644 (patch)
tree9cb4ad827715ce5138415ffa2aa2bfd77062a7bc /sys/net
parent3476eb5656ca042f7a348020333c2a57fbf0f8b2 (diff)
downloadFreeBSD-src-af76980ef5353eee84271a4934c37c01861d8644.zip
FreeBSD-src-af76980ef5353eee84271a4934c37c01861d8644.tar.gz
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.
Diffstat (limited to 'sys/net')
-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 bc644e9..4e365d5 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
OpenPOWER on IntegriCloud