diff options
author | zec <zec@FreeBSD.org> | 2009-05-05 10:56:12 +0000 |
---|---|---|
committer | zec <zec@FreeBSD.org> | 2009-05-05 10:56:12 +0000 |
commit | d78a1b1a824c4f5eb8cb3583bb5265f73dcc24dd (patch) | |
tree | 79a0bccccf2c92504cdf23ad15f7c1813bb3f926 /sys/net80211/ieee80211_freebsd.c | |
parent | 8e4ffe653f6c9ff6da3eed58566ef35e77d530d0 (diff) | |
download | FreeBSD-src-d78a1b1a824c4f5eb8cb3583bb5265f73dcc24dd.zip FreeBSD-src-d78a1b1a824c4f5eb8cb3583bb5265f73dcc24dd.tar.gz |
Change the curvnet variable from a global const struct vnet *,
previously always pointing to the default vnet context, to a
dynamically changing thread-local one. The currvnet context
should be set on entry to networking code via CURVNET_SET() macros,
and reverted to previous state via CURVNET_RESTORE(). Recursions
on curvnet are permitted, though strongly discuouraged.
This change should have no functional impact on nooptions VIMAGE
kernel builds, where CURVNET_* macros expand to whitespace.
The curthread->td_vnet (aka curvnet) variable's purpose is to be an
indicator of the vnet context in which the current network-related
operation takes place, in case we cannot deduce the current vnet
context from any other source, such as by looking at mbuf's
m->m_pkthdr.rcvif->if_vnet, sockets's so->so_vnet etc. Moreover, so
far curvnet has turned out to be an invaluable consistency checking
aid: it helps to catch cases when sockets, ifnets or any other
vnet-aware structures may have leaked from one vnet to another.
The exact placement of the CURVNET_SET() / CURVNET_RESTORE() macros
was a result of an empirical iterative process, whith an aim to
reduce recursions on CURVNET_SET() to a minimum, while still reducing
the scope of CURVNET_SET() to networking only operations - the
alternative would be calling CURVNET_SET() on each system call entry.
In general, curvnet has to be set in three typicall cases: when
processing socket-related requests from userspace or from within the
kernel; when processing inbound traffic flowing from device drivers
to upper layers of the networking stack, and when executing
timer-driven networking functions.
This change also introduces a DDB subcommand to show the list of all
vnet instances.
Approved by: julian (mentor)
Diffstat (limited to 'sys/net80211/ieee80211_freebsd.c')
-rw-r--r-- | sys/net80211/ieee80211_freebsd.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 8d38614..e2d42a6 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/socket.h> +#include <sys/vimage.h> #include <net/if.h> #include <net/if_dl.h> @@ -498,9 +499,11 @@ notify_macaddr(struct ifnet *ifp, int op, const uint8_t mac[IEEE80211_ADDR_LEN]) { struct ieee80211_join_event iev; + CURVNET_SET(ifp->if_vnet); memset(&iev, 0, sizeof(iev)); IEEE80211_ADDR_COPY(iev.iev_addr, mac); rt_ieee80211msg(ifp, op, &iev, sizeof(iev)); + CURVNET_RESTORE(); } void @@ -509,6 +512,7 @@ ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc) struct ieee80211vap *vap = ni->ni_vap; struct ifnet *ifp = vap->iv_ifp; + CURVNET_SET_QUIET(ifp->if_vnet); IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%snode join", (ni == vap->iv_bss) ? "bss " : ""); @@ -520,6 +524,7 @@ ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc) notify_macaddr(ifp, newassoc ? RTM_IEEE80211_JOIN : RTM_IEEE80211_REJOIN, ni->ni_macaddr); } + CURVNET_RESTORE(); } void @@ -528,6 +533,7 @@ ieee80211_notify_node_leave(struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; struct ifnet *ifp = vap->iv_ifp; + CURVNET_SET_QUIET(ifp->if_vnet); IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%snode leave", (ni == vap->iv_bss) ? "bss " : ""); @@ -538,6 +544,7 @@ ieee80211_notify_node_leave(struct ieee80211_node *ni) /* fire off wireless event station leaving */ notify_macaddr(ifp, RTM_IEEE80211_LEAVE, ni->ni_macaddr); } + CURVNET_RESTORE(); } void @@ -548,7 +555,9 @@ ieee80211_notify_scan_done(struct ieee80211vap *vap) IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s\n", "notify scan done"); /* dispatch wireless event indicating scan completed */ + CURVNET_SET(ifp->if_vnet); rt_ieee80211msg(ifp, RTM_IEEE80211_SCAN, NULL, 0); + CURVNET_RESTORE(); } void @@ -576,7 +585,9 @@ ieee80211_notify_replay_failure(struct ieee80211vap *vap, iev.iev_keyix = k->wk_keyix; iev.iev_keyrsc = k->wk_keyrsc[0]; /* XXX need tid */ iev.iev_rsc = rsc; + CURVNET_SET(ifp->if_vnet); rt_ieee80211msg(ifp, RTM_IEEE80211_REPLAY, &iev, sizeof(iev)); + CURVNET_RESTORE(); } } @@ -597,7 +608,9 @@ ieee80211_notify_michael_failure(struct ieee80211vap *vap, IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2); iev.iev_cipher = IEEE80211_CIPHER_TKIP; iev.iev_keyix = keyix; + CURVNET_SET(ifp->if_vnet); rt_ieee80211msg(ifp, RTM_IEEE80211_MICHAEL, &iev, sizeof(iev)); + CURVNET_RESTORE(); } } |