summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_freebsd.c
diff options
context:
space:
mode:
authorzec <zec@FreeBSD.org>2009-05-05 10:56:12 +0000
committerzec <zec@FreeBSD.org>2009-05-05 10:56:12 +0000
commitd78a1b1a824c4f5eb8cb3583bb5265f73dcc24dd (patch)
tree79a0bccccf2c92504cdf23ad15f7c1813bb3f926 /sys/net80211/ieee80211_freebsd.c
parent8e4ffe653f6c9ff6da3eed58566ef35e77d530d0 (diff)
downloadFreeBSD-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.c13
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();
}
}
OpenPOWER on IntegriCloud