svn commit: r183893 - in stable/7/sys: . dev/twa net

David Malone dwmalone at FreeBSD.org
Tue Oct 14 19:48:58 UTC 2008


Author: dwmalone
Date: Tue Oct 14 19:48:58 2008
New Revision: 183893
URL: http://svn.freebsd.org/changeset/base/183893

Log:
  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. Various versions of this patch were tested
  by Pekka Savola, Nick Sayer and Wouter Snels.
  
  Approved by:    re (gnn)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/dev/twa/   (props changed)
  stable/7/sys/net/if_stf.c

Modified: stable/7/sys/net/if_stf.c
==============================================================================
--- stable/7/sys/net/if_stf.c	Tue Oct 14 19:02:47 2008	(r183892)
+++ stable/7/sys/net/if_stf.c	Tue Oct 14 19:48:58 2008	(r183893)
@@ -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>
@@ -119,6 +120,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
 
@@ -137,15 +145,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;
@@ -231,6 +239,7 @@ stf_clone_create(struct if_clone *ifc, c
 	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) {
@@ -257,6 +266,7 @@ stf_clone_destroy(struct if_clone *ifc, 
 
 	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);
@@ -398,6 +408,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;
@@ -406,9 +417,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_check_ifnet_transmit(ifp, m);
 	if (error) {
 		m_freem(m);
@@ -507,9 +518,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) {
@@ -527,14 +544,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


More information about the svn-src-all mailing list