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.
This commit is contained in:
parent
0ae492beb3
commit
0dae32f2eb
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user