From 19c49ad2c7cbeca9553738f8fd1e36f2d823979b Mon Sep 17 00:00:00 2001 From: rwatson Date: Tue, 9 Mar 2004 20:29:19 +0000 Subject: Introduce stf_mtx to protect global softc list in if_stf. Add stf_destroy() to handle the common softc destruction path for the two destruction sources: interface cloning destroy, and module unload. NOTE: sc_ro, the cached route for stf conversion, is not synchronized against concurrent access in this change, that will follow in a future change. Reviewed by: pjd --- sys/net/if_stf.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'sys/net') diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index 8c1ab87..98e8ce2 100644 --- a/sys/net/if_stf.c +++ b/sys/net/if_stf.c @@ -138,6 +138,13 @@ struct stf_softc { LIST_ENTRY(stf_softc) sc_list; /* all stf's are linked */ }; +/* + * All mutable global variables in if_stf.c are protected by stf_mtx. + * 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(). + */ +static struct mtx stf_mtx; static LIST_HEAD(, stf_softc) stf_softc_list; static MALLOC_DEFINE(M_STF, STFNAME, "6to4 Tunnel Interface"); @@ -197,24 +204,36 @@ stf_clone_create(ifc, unit) sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach(&sc->sc_if); bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); + mtx_lock(&stf_mtx); LIST_INSERT_HEAD(&stf_softc_list, sc, sc_list); + mtx_unlock(&stf_mtx); return (0); } +static void +stf_destroy(struct stf_softc *sc) +{ + int err; + + err = encap_detach(sc->encap_cookie); + KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); + bpfdetach(&sc->sc_if); + if_detach(&sc->sc_if); + + free(sc, M_STF); +} + void stf_clone_destroy(ifp) struct ifnet *ifp; { - int err; struct stf_softc *sc = (void *) ifp; + mtx_lock(&stf_mtx); LIST_REMOVE(sc, sc_list); - err = encap_detach(sc->encap_cookie); - KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); - bpfdetach(ifp); - if_detach(ifp); + mtx_unlock(&stf_mtx); - free(sc, M_STF); + stf_destroy(sc); } static int @@ -223,9 +242,11 @@ stfmodevent(mod, type, data) int type; void *data; { + struct stf_softc *sc; switch (type) { case MOD_LOAD: + mtx_init(&stf_mtx, "stf_mtx", NULL, MTX_DEF); LIST_INIT(&stf_softc_list); if_clone_attach(&stf_cloner); @@ -233,8 +254,15 @@ stfmodevent(mod, type, data) case MOD_UNLOAD: if_clone_detach(&stf_cloner); - while (!LIST_EMPTY(&stf_softc_list)) - stf_clone_destroy(&LIST_FIRST(&stf_softc_list)->sc_if); + mtx_lock(&stf_mtx); + while ((sc = LIST_FIRST(&stf_softc_list)) != NULL) { + LIST_REMOVE(sc, sc_list); + mtx_unlock(&stf_mtx); + stf_destroy(sc); + mtx_lock(&stf_mtx); + } + mtx_unlock(&stf_mtx); + mtx_destroy(&stf_mtx); break; } @@ -467,6 +495,9 @@ stf_output(ifp, m, dst, rt) else ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); + /* + * XXXRW: Locking of sc_ro required. + */ 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) { -- cgit v1.1