summaryrefslogtreecommitdiffstats
path: root/sys/net/if_stf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_stf.c')
-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