summaryrefslogtreecommitdiffstats
path: root/sys/net/if_gif.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2006-01-30 08:39:09 +0000
committerglebius <glebius@FreeBSD.org>2006-01-30 08:39:09 +0000
commitaecf4a6244730d904a75f88ec9ea7eba0be9dd34 (patch)
treee06d7957fe2790ef47aabd00c8f3a9d96af9e3b5 /sys/net/if_gif.c
parent02a28f2514c2622f785b9c1e84417e4971151c72 (diff)
downloadFreeBSD-src-aecf4a6244730d904a75f88ec9ea7eba0be9dd34.zip
FreeBSD-src-aecf4a6244730d904a75f88ec9ea7eba0be9dd34.tar.gz
Add some initial locking to gif(4). It doesn't covers the whole driver,
however IPv4-in-IPv4 tunnels are now stable on SMP. Details: - Add per-softc mutex. - Hold the mutex on output. The main problem was the rtentry, placed in softc. It could be freed by ip_output(). Meanwhile, another thread being in in_gif_output() can read and write this rtentry. Reported by: many Tested by: Alexander Shiryaev <aixp mail.ru>
Diffstat (limited to 'sys/net/if_gif.c')
-rw-r--r--sys/net/if_gif.c39
1 files changed, 15 insertions, 24 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 940e00e..c67f62d 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -90,7 +90,6 @@
/*
* gif_mtx protects the global gif_softc_list.
- * XXX: Per-softc locking is still required.
*/
static struct mtx gif_mtx;
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
@@ -154,22 +153,11 @@ gif_clone_create(ifc, unit)
return (ENOSPC);
}
+ GIF_LOCK_INIT(sc);
+
GIF2IFP(sc)->if_softc = sc;
if_initname(GIF2IFP(sc), ifc->ifc_name, unit);
- gifattach0(sc);
-
- mtx_lock(&gif_mtx);
- LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
- mtx_unlock(&gif_mtx);
- return (0);
-}
-
-void
-gifattach0(sc)
- struct gif_softc *sc;
-{
-
sc->encap_cookie4 = sc->encap_cookie6 = NULL;
GIF2IFP(sc)->if_addrlen = 0;
@@ -187,6 +175,12 @@ gifattach0(sc)
bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
if (ng_gif_attach_p != NULL)
(*ng_gif_attach_p)(GIF2IFP(sc));
+
+ mtx_lock(&gif_mtx);
+ LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
+ mtx_unlock(&gif_mtx);
+
+ return (0);
}
static void
@@ -220,6 +214,8 @@ gif_clone_destroy(ifp)
if_detach(ifp);
if_free(ifp);
+ GIF_LOCK_DESTROY(sc);
+
free(sc, M_GIF);
}
@@ -411,6 +407,9 @@ gif_output(ifp, m, dst, rt)
m_tag_prepend(m, mtag);
m->m_flags &= ~(M_BCAST|M_MCAST);
+
+ GIF_LOCK(sc);
+
if (!(ifp->if_flags & IFF_UP) ||
sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
m_freem(m);
@@ -460,7 +459,8 @@ gif_output(ifp, m, dst, rt)
end:
if (error)
ifp->if_oerrors++;
- return error;
+ GIF_UNLOCK(sc);
+ return (error);
}
void
@@ -827,11 +827,8 @@ gif_set_tunnel(ifp, src, dst)
struct gif_softc *sc = ifp->if_softc;
struct gif_softc *sc2;
struct sockaddr *osrc, *odst, *sa;
- int s;
int error = 0;
- s = splnet();
-
mtx_lock(&gif_mtx);
LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
if (sc2 == sc)
@@ -925,7 +922,6 @@ gif_set_tunnel(ifp, src, dst)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
else
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- splx(s);
return 0;
@@ -934,7 +930,6 @@ gif_set_tunnel(ifp, src, dst)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
else
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- splx(s);
return error;
}
@@ -944,9 +939,6 @@ gif_delete_tunnel(ifp)
struct ifnet *ifp;
{
struct gif_softc *sc = ifp->if_softc;
- int s;
-
- s = splnet();
if (sc->gif_psrc) {
free((caddr_t)sc->gif_psrc, M_IFADDR);
@@ -968,5 +960,4 @@ gif_delete_tunnel(ifp)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
else
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- splx(s);
}
OpenPOWER on IntegriCloud