summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2015-08-27 08:56:39 +0000
committerglebius <glebius@FreeBSD.org>2015-08-27 08:56:39 +0000
commit619aca846fad0cf56fcd9c3374008f26a6f98b24 (patch)
tree7898977af912b148a68c6e102a888b4316ea1fb5 /sys/net80211
parent433b16759b09dba93b94a1ff1a85dd74e64c6de2 (diff)
downloadFreeBSD-src-619aca846fad0cf56fcd9c3374008f26a6f98b24.zip
FreeBSD-src-619aca846fad0cf56fcd9c3374008f26a6f98b24.tar.gz
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack. Historical background: originally wireless devices created an interface, just like Ethernet devices do. Name of an interface matched the name of the driver that created. Later, wlan(4) layer was introduced, and the wlanX interfaces become the actual interface, leaving original ones as "a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer and a driver became a mix of methods that pass a pointer to struct ifnet as identifier and methods that pass pointer to struct ieee80211com. From user point of view, the parent interface just hangs on in the ifconfig list, and user can't do anything useful with it. Now, the struct ifnet goes away. The struct ieee80211com is the only KPI between a device driver and net80211. Details: - The struct ieee80211com is embedded into drivers softc. - Packets are sent via new ic_transmit method, which is very much like the previous if_transmit. - Bringing parent up/down is done via new ic_parent method, which notifies driver about any changes: number of wlan(4) interfaces, number of them in promisc or allmulti state. - Device specific ioctls (if any) are received on new ic_ioctl method. - Packets/errors accounting are done by the stack. In certain cases, when driver experiences errors and can not attribute them to any specific interface, driver updates ic_oerrors or ic_ierrors counters. Details on interface configuration with new world order: - A sequence of commands needed to bring up wireless DOESN"T change. - /etc/rc.conf parameters DON'T change. - List of devices that can be used to create wlan(4) interfaces is now provided by net.wlan.devices sysctl. Most drivers in this change were converted by me, except of wpi(4), that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann, Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in testing. Reviewed by: adrian Sponsored by: Netflix Sponsored by: Nginx, Inc.
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211.c282
-rw-r--r--sys/net80211/ieee80211_ddb.c3
-rw-r--r--sys/net80211/ieee80211_freebsd.c90
-rw-r--r--sys/net80211/ieee80211_ioctl.c71
-rw-r--r--sys/net80211/ieee80211_output.c30
-rw-r--r--sys/net80211/ieee80211_power.c55
-rw-r--r--sys/net80211/ieee80211_proto.c36
-rw-r--r--sys/net80211/ieee80211_proto.h3
-rw-r--r--sys/net80211/ieee80211_regdomain.c3
-rw-r--r--sys/net80211/ieee80211_scan_sta.c26
-rw-r--r--sys/net80211/ieee80211_var.h27
11 files changed, 217 insertions, 409 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 3902227..39e03ea 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sbuf.h>
#include <machine/stdarg.h>
@@ -91,8 +92,6 @@ static void ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag);
static int ieee80211_media_setup(struct ieee80211com *ic,
struct ifmedia *media, int caps, int addsta,
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat);
-static void ieee80211com_media_status(struct ifnet *, struct ifmediareq *);
-static int ieee80211com_media_change(struct ifnet *);
static int media_status(enum ieee80211_opmode,
const struct ieee80211_channel *);
static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter);
@@ -121,7 +120,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g =
* all available channels as active, and pick
* a default channel if not already specified.
*/
-static void
+void
ieee80211_chan_init(struct ieee80211com *ic)
{
#define DEFAULTRATES(m, def) do { \
@@ -238,29 +237,6 @@ null_update_promisc(struct ieee80211com *ic)
ic_printf(ic, "need promiscuous mode update callback\n");
}
-static int
-null_transmit(struct ifnet *ifp, struct mbuf *m)
-{
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return EACCES; /* XXX EIO/EPERM? */
-}
-
-static int
-null_output(struct ifnet *ifp, struct mbuf *m,
- const struct sockaddr *dst, struct route *ro)
-{
- if_printf(ifp, "discard raw packet\n");
- return null_transmit(ifp, m);
-}
-
-static void
-null_input(struct ifnet *ifp, struct mbuf *m)
-{
- if_printf(ifp, "if_input should not be called\n");
- m_freem(m);
-}
-
static void
null_update_chw(struct ieee80211com *ic)
{
@@ -281,19 +257,43 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...)
return (retval);
}
+static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head);
+static struct mtx ic_list_mtx;
+MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF);
+
+static int
+sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS)
+{
+ struct ieee80211com *ic;
+ struct sbuf *sb;
+ char *sp;
+ int error;
+
+ sb = sbuf_new_auto();
+ sp = "";
+ mtx_lock(&ic_list_mtx);
+ LIST_FOREACH(ic, &ic_head, ic_next) {
+ sbuf_printf(sb, "%s%s", sp, ic->ic_name);
+ sp = " ";
+ }
+ mtx_unlock(&ic_list_mtx);
+ sbuf_finish(sb);
+ error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
+ sbuf_delete(sb);
+ return (error);
+}
+
+SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_ieee80211coms, "A", "names of available 802.11 devices");
+
/*
* Attach/setup the common net80211 state. Called by
* the driver on attach to prior to creating any vap's.
*/
void
-ieee80211_ifattach(struct ieee80211com *ic,
- const uint8_t macaddr[IEEE80211_ADDR_LEN])
+ieee80211_ifattach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct sockaddr_dl *sdl;
- struct ifaddr *ifa;
-
- KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
IEEE80211_LOCK_INIT(ic, ic->ic_name);
IEEE80211_TX_LOCK_INIT(ic, ic->ic_name);
@@ -311,7 +311,7 @@ ieee80211_ifattach(struct ieee80211com *ic,
* available channels as active, and pick a default
* channel if not already specified.
*/
- ieee80211_media_init(ic);
+ ieee80211_chan_init(ic);
ic->ic_update_mcast = null_update_mcast;
ic->ic_update_promisc = null_update_promisc;
@@ -336,28 +336,9 @@ ieee80211_ifattach(struct ieee80211com *ic,
ieee80211_sysctl_attach(ic);
- ifp->if_addrlen = IEEE80211_ADDR_LEN;
- ifp->if_hdrlen = 0;
-
- CURVNET_SET(vnet0);
-
- if_attach(ifp);
-
- ifp->if_mtu = IEEE80211_MTU_MAX;
- ifp->if_broadcastaddr = ieee80211broadcastaddr;
- ifp->if_output = null_output;
- ifp->if_input = null_input; /* just in case */
- ifp->if_resolvemulti = NULL; /* NB: callers check */
-
- ifa = ifaddr_byindex(ifp->if_index);
- KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
- sdl = (struct sockaddr_dl *)ifa->ifa_addr;
- sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */
- sdl->sdl_alen = IEEE80211_ADDR_LEN;
- IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr);
- ifa_free(ifa);
-
- CURVNET_RESTORE();
+ mtx_lock(&ic_list_mtx);
+ LIST_INSERT_HEAD(&ic_head, ic, ic_next);
+ mtx_unlock(&ic_list_mtx);
}
/*
@@ -369,16 +350,11 @@ ieee80211_ifattach(struct ieee80211com *ic,
void
ieee80211_ifdetach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap;
- /*
- * This detaches the main interface, but not the vaps.
- * Each VAP may be in a separate VIMAGE.
- */
- CURVNET_SET(ifp->if_vnet);
- if_detach(ifp);
- CURVNET_RESTORE();
+ mtx_lock(&ic_list_mtx);
+ LIST_REMOVE(ic, ic_next);
+ mtx_unlock(&ic_list_mtx);
/*
* The VAP is responsible for setting and clearing
@@ -402,8 +378,6 @@ ieee80211_ifdetach(struct ieee80211com *ic)
ieee80211_power_detach(ic);
ieee80211_node_detach(ic);
- /* XXX VNET needed? */
- ifmedia_removeall(&ic->ic_media);
counter_u64_free(ic->ic_ierrors);
counter_u64_free(ic->ic_oerrors);
@@ -412,6 +386,20 @@ ieee80211_ifdetach(struct ieee80211com *ic)
IEEE80211_LOCK_DESTROY(ic);
}
+struct ieee80211com *
+ieee80211_find_com(const char *name)
+{
+ struct ieee80211com *ic;
+
+ mtx_lock(&ic_list_mtx);
+ LIST_FOREACH(ic, &ic_head, ic_next)
+ if (strcmp(ic->ic_name, name) == 0)
+ break;
+ mtx_unlock(&ic_list_mtx);
+
+ return (ic);
+}
+
/*
* Default reset method for use with the ioctl support. This
* method is invoked after any state change in the 802.11
@@ -460,8 +448,7 @@ ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt)
int
ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode,
- int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
- const uint8_t macaddr[IEEE80211_ADDR_LEN])
+ int flags, const uint8_t bssid[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp;
@@ -490,6 +477,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
vap->iv_htextcaps = ic->ic_htextcaps;
vap->iv_opmode = opmode;
vap->iv_caps |= ieee80211_opcap[opmode];
+ vap->iv_myaddr = ic->ic_macaddr;
switch (opmode) {
case IEEE80211_M_WDS:
/*
@@ -556,8 +544,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
*/
vap->iv_reset = default_reset;
- IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr);
-
ieee80211_sysctl_vattach(vap);
ieee80211_crypto_vattach(vap);
ieee80211_node_vattach(vap);
@@ -581,8 +567,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
* from this call the vap is ready for use.
*/
int
-ieee80211_vap_attach(struct ieee80211vap *vap,
- ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
+ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
+ ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
@@ -610,7 +596,8 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
if (maxrate)
ifp->if_baudrate = IF_Mbps(maxrate);
- ether_ifattach(ifp, vap->iv_myaddr);
+ ether_ifattach(ifp, macaddr);
+ vap->iv_myaddr = IF_LLADDR(ifp);
/* hook output method setup by ether_ifattach */
vap->iv_output = ifp->if_output;
ifp->if_output = ieee80211_output;
@@ -626,8 +613,6 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
IEEE80211_UNLOCK(ic);
return 1;
@@ -677,8 +662,10 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
/* NB: this handles the bpfdetach done below */
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ if (vap->iv_ifflags & IFF_PROMISC)
+ ieee80211_promisc(vap, false);
+ if (vap->iv_ifflags & IFF_ALLMULTI)
+ ieee80211_allmulti(vap, false);
IEEE80211_UNLOCK(ic);
ifmedia_removeall(&vap->iv_media);
@@ -703,49 +690,57 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
}
/*
- * Synchronize flag bit state in the parent ifnet structure
- * according to the state of all vap ifnet's. This is used,
- * for example, to handle IFF_PROMISC and IFF_ALLMULTI.
+ * Count number of vaps in promisc, and issue promisc on
+ * parent respectively.
*/
void
-ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
+ieee80211_promisc(struct ieee80211vap *vap, bool on)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ieee80211vap *vap;
- int bit, oflags;
+ struct ieee80211com *ic = vap->iv_ic;
- IEEE80211_LOCK_ASSERT(ic);
+ /*
+ * XXX the bridge sets PROMISC but we don't want to
+ * enable it on the device, discard here so all the
+ * drivers don't need to special-case it
+ */
+ if (!(vap->iv_opmode == IEEE80211_M_MONITOR ||
+ (vap->iv_opmode == IEEE80211_M_AHDEMO &&
+ (vap->iv_caps & IEEE80211_C_TDMA) == 0)))
+ return;
- bit = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- if (vap->iv_ifp->if_flags & flag) {
- /*
- * XXX the bridge sets PROMISC but we don't want to
- * enable it on the device, discard here so all the
- * drivers don't need to special-case it
- */
- if (flag == IFF_PROMISC &&
- !(vap->iv_opmode == IEEE80211_M_MONITOR ||
- (vap->iv_opmode == IEEE80211_M_AHDEMO &&
- (vap->iv_caps & IEEE80211_C_TDMA) == 0)))
- continue;
- bit = 1;
- break;
- }
- oflags = ifp->if_flags;
- if (bit)
- ifp->if_flags |= flag;
- else
- ifp->if_flags &= ~flag;
- if ((ifp->if_flags ^ oflags) & flag) {
- /* XXX should we return 1/0 and let caller do this? */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (flag == IFF_PROMISC)
- ieee80211_runtask(ic, &ic->ic_promisc_task);
- else if (flag == IFF_ALLMULTI)
- ieee80211_runtask(ic, &ic->ic_mcast_task);
- }
+ IEEE80211_LOCK(ic);
+ if (on) {
+ if (++ic->ic_promisc == 1)
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
+ } else {
+ KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc",
+ __func__, ic));
+ if (--ic->ic_promisc == 0)
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
}
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Count number of vaps in allmulti, and issue allmulti on
+ * parent respectively.
+ */
+void
+ieee80211_allmulti(struct ieee80211vap *vap, bool on)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ IEEE80211_LOCK(ic);
+ if (on) {
+ if (++ic->ic_allmulti == 1)
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
+ } else {
+ KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti",
+ __func__, ic));
+ if (--ic->ic_allmulti == 0)
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
+ }
+ IEEE80211_UNLOCK(ic);
}
/*
@@ -1234,39 +1229,6 @@ ieee80211_media_setup(struct ieee80211com *ic,
return maxrate;
}
-void
-ieee80211_media_init(struct ieee80211com *ic)
-{
- struct ifnet *ifp = ic->ic_ifp;
- int maxrate;
-
- /* NB: this works because the structure is initialized to zero */
- if (!LIST_EMPTY(&ic->ic_media.ifm_list)) {
- /*
- * We are re-initializing the channel list; clear
- * the existing media state as the media routines
- * don't suppress duplicates.
- */
- ifmedia_removeall(&ic->ic_media);
- }
- ieee80211_chan_init(ic);
-
- /*
- * Recalculate media settings in case new channel list changes
- * the set of available modes.
- */
- maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1,
- ieee80211com_media_change, ieee80211com_media_status);
- /* NB: strip explicit mode; we're actually in autoselect */
- ifmedia_set(&ic->ic_media,
- media_status(ic->ic_opmode, ic->ic_curchan) &~
- (IFM_MMASK | IFM_IEEE80211_TURBO));
- if (maxrate)
- ifp->if_baudrate = IF_Mbps(maxrate);
-
- /* XXX need to propagate new media settings to vap's */
-}
-
/* XXX inline or eliminate? */
const struct ieee80211_rateset *
ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
@@ -1395,15 +1357,6 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode)
}
/*
- * Handle a media change request on the underlying interface.
- */
-int
-ieee80211com_media_change(struct ifnet *ifp)
-{
- return EINVAL;
-}
-
-/*
* Handle a media change request on the vap interface.
*/
int
@@ -1480,23 +1433,6 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan)
return status;
}
-static void
-ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr)
-{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap;
-
- imr->ifm_status = IFM_AVALID;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- if (vap->iv_ifp->if_flags & IFF_UP) {
- imr->ifm_status |= IFM_ACTIVE;
- break;
- }
- imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
- if (imr->ifm_status & IFM_ACTIVE)
- imr->ifm_current = imr->ifm_active;
-}
-
void
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index e646cf2..ae4910c 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -520,7 +520,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap);
db_printf("\n");
- db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname);
+ db_printf("\tsoftc %p", ic->ic_softc);
db_printf("\tname %s", ic->ic_name);
db_printf(" comlock %p", &ic->ic_comlock);
db_printf("\n");
@@ -528,7 +528,6 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
db_printf(" phytype %d", ic->ic_phytype);
db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
db_printf("\n");
- db_printf("\tmedia %p", &ic->ic_media);
db_printf(" inact %p", &ic->ic_inact);
db_printf("\n");
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 3af75df..9a8e941 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -69,58 +69,27 @@ static MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state");
static const char wlanname[] = "wlan";
static struct if_clone *wlan_cloner;
-/*
- * Allocate/free com structure in conjunction with ifnet;
- * these routines are registered with if_register_com_alloc
- * below and are called automatically by the ifnet code
- * when the ifnet of the parent device is created.
- */
-static void *
-wlan_alloc(u_char type, struct ifnet *ifp)
-{
- struct ieee80211com *ic;
-
- ic = IEEE80211_MALLOC(sizeof(struct ieee80211com), M_80211_COM,
- IEEE80211_M_WAITOK | IEEE80211_M_ZERO);
- ic->ic_ifp = ifp;
-
- return (ic);
-}
-
-static void
-wlan_free(void *ic, u_char type)
-{
- IEEE80211_FREE(ic, M_80211_COM);
-}
-
static int
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct ieee80211_clone_params cp;
struct ieee80211vap *vap;
struct ieee80211com *ic;
- struct ifnet *ifp;
int error;
error = copyin(params, &cp, sizeof(cp));
if (error)
return error;
- ifp = ifunit(cp.icp_parent);
- if (ifp == NULL)
+ ic = ieee80211_find_com(cp.icp_parent);
+ if (ic == NULL)
return ENXIO;
- /* XXX move printfs to DIAGNOSTIC before release */
- if (ifp->if_type != IFT_IEEE80211) {
- if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
- return ENXIO;
- }
if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
- if_printf(ifp, "%s: invalid opmode %d\n",
- __func__, cp.icp_opmode);
+ ic_printf(ic, "%s: invalid opmode %d\n", __func__,
+ cp.icp_opmode);
return EINVAL;
}
- ic = ifp->if_l2com;
if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
- if_printf(ifp, "%s mode not supported\n",
+ ic_printf(ic, "%s mode not supported\n",
ieee80211_opmode_name[cp.icp_opmode]);
return EOPNOTSUPP;
}
@@ -131,13 +100,13 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
(1)
#endif
) {
- if_printf(ifp, "TDMA not supported\n");
+ ic_printf(ic, "TDMA not supported\n");
return EOPNOTSUPP;
}
vap = ic->ic_vap_create(ic, wlanname, unit,
cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
cp.icp_flags & IEEE80211_CLONE_MACADDR ?
- cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
+ cp.icp_macaddr : ic->ic_macaddr);
return (vap == NULL ? EIO : 0);
}
@@ -528,17 +497,19 @@ ieee80211_process_callback(struct ieee80211_node *ni,
* (the callers will first need modifying.)
*/
int
-ieee80211_parent_xmitpkt(struct ieee80211com *ic,
- struct mbuf *m)
+ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
{
- struct ifnet *parent = ic->ic_ifp;
+ int error;
+
/*
* Assert the IC TX lock is held - this enforces the
* processing -> queuing order is maintained
*/
IEEE80211_TX_LOCK_ASSERT(ic);
-
- return (parent->if_transmit(parent, m));
+ error = ic->ic_transmit(ic, m);
+ if (error)
+ m_freem(m);
+ return (error);
}
/*
@@ -836,7 +807,6 @@ ieee80211_load_module(const char *modname)
}
static eventhandler_tag wlan_bpfevent;
-static eventhandler_tag wlan_ifllevent;
static void
bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
@@ -864,33 +834,6 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
}
}
-static void
-wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
-{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap, *next;
-
- if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
- return;
-
- IEEE80211_LOCK(ic);
- TAILQ_FOREACH_SAFE(vap, &ic->ic_vaps, iv_next, next) {
- /*
- * If the MAC address has changed on the parent and it was
- * copied to the vap on creation then re-sync.
- */
- if (vap->iv_ic == ic &&
- (vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
- IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
- IEEE80211_UNLOCK(ic);
- if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
- IEEE80211_ADDR_LEN);
- IEEE80211_LOCK(ic);
- }
- }
- IEEE80211_UNLOCK(ic);
-}
-
/*
* Module glue.
*
@@ -905,17 +848,12 @@ wlan_modevent(module_t mod, int type, void *unused)
printf("wlan: <802.11 Link Layer>\n");
wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
bpf_track, 0, EVENTHANDLER_PRI_ANY);
- wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
- wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
wlan_cloner = if_clone_simple(wlanname, wlan_clone_create,
wlan_clone_destroy, 0);
- if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
return 0;
case MOD_UNLOAD:
- if_deregister_com_alloc(IFT_IEEE80211);
if_clone_detach(wlan_cloner);
EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
- EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
return 0;
}
return EINVAL;
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 54ab390..1c7ddb9 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -1329,13 +1329,12 @@ static int
setmlme_dropsta(struct ieee80211vap *vap,
const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_node_table *nt = &ic->ic_sta;
+ struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
struct ieee80211_node *ni;
int error = 0;
/* NB: the broadcast address means do 'em all */
- if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
+ if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
IEEE80211_NODE_LOCK(nt);
ni = ieee80211_find_node_locked(nt, mac);
IEEE80211_NODE_UNLOCK(nt);
@@ -2529,14 +2528,9 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
static __noinline int
ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
- struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_req sr; /* XXX off stack? */
int error;
- /* NB: parent must be running */
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return ENXIO;
-
if (ireq->i_len != sizeof(sr))
return EINVAL;
error = copyin(ireq->i_data, &sr, sizeof(sr));
@@ -3300,41 +3294,6 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
return error;
}
-/*
- * Rebuild the parent's multicast address list after an add/del
- * of a multicast address for a vap. We have no way to tell
- * what happened above to optimize the work so we purge the entire
- * list and rebuild from scratch. This is way expensive.
- * Note also the half-baked workaround for if_addmulti calling
- * back to the parent device; there's no way to insert mcast
- * entries quietly and/or cheaply.
- */
-static void
-ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
-{
- struct ifnet *parent = ic->ic_ifp;
- struct ieee80211vap *vap;
- void *ioctl;
-
- IEEE80211_LOCK(ic);
- if_delallmulti(parent);
- ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
- parent->if_ioctl = NULL;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- struct ifnet *ifp = vap->iv_ifp;
- struct ifmultiaddr *ifma;
-
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- (void) if_addmulti(parent, ifma->ifma_addr, NULL);
- }
- }
- parent->if_ioctl = ioctl;
- ieee80211_runtask(ic, &ic->ic_mcast_task);
- IEEE80211_UNLOCK(ic);
-}
-
int
ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -3347,8 +3306,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFFLAGS:
IEEE80211_LOCK(ic);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC)
+ ieee80211_promisc(vap, ifp->if_flags & IFF_PROMISC);
+ if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI)
+ ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
+ vap->iv_ifflags = ifp->if_flags;
if (ifp->if_flags & IFF_UP) {
/*
* Bring ourself up unless we're already operational.
@@ -3371,7 +3333,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- ieee80211_ioctl_updatemulti(ic);
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@@ -3427,17 +3389,16 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
break;
- /* Pass NDIS ioctls up to the driver */
- case SIOCGDRVSPEC:
- case SIOCSDRVSPEC:
- case SIOCGPRIVATE_0: {
- struct ifnet *parent = vap->iv_ic->ic_ifp;
- error = parent->if_ioctl(parent, cmd, data);
- break;
- }
default:
+ /*
+ * Pass unknown ioctls first to the driver, and if it
+ * returns ENOTTY, then to the generic Ethernet handler.
+ */
+ if (ic->ic_ioctl != NULL &&
+ (error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
+ break;
error = ether_ioctl(ifp, cmd, data);
break;
}
- return error;
+ return (error);
}
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index d11628d..eb333da1 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -254,10 +254,6 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m,
/* NB: IFQ_HANDOFF reclaims mbuf */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- } else {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
- if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
}
ic->ic_lastdata = ticks;
@@ -430,17 +426,6 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *parent = ic->ic_ifp;
-
- /* NB: parent must be up and running */
- if (!IFNET_IS_UP_RUNNING(parent)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: ignore queue, parent %s not up+running\n",
- __func__, parent->if_xname);
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return (ENETDOWN);
- }
/*
* No data frames go out unless we're running.
@@ -507,6 +492,7 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct mbuf *m, const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = vap->iv_ic;
+ int error;
/*
* Set node - the caller has taken a reference, so ensure
@@ -528,7 +514,10 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (params)
(void) ieee80211_add_xmit_params(m, params);
- return (ic->ic_raw_xmit(ni, m, params));
+ error = ic->ic_raw_xmit(ni, m, params);
+ if (error)
+ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ return (error);
}
/*
@@ -3457,6 +3446,15 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status)
{
if (ni != NULL) {
+ struct ifnet *ifp = ni->ni_vap->iv_ifp;
+
+ if (status == 0) {
+ if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ if (m->m_flags & M_MCAST)
+ if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
+ } else
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, status);
ieee80211_free_node(ni);
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 91668cc..2d216c2 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -418,7 +418,6 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
- struct ifnet *parent, *ifp;
struct mbuf *parent_q = NULL, *ifp_q = NULL;
struct mbuf *m;
@@ -429,59 +428,51 @@ pwrsave_flushq(struct ieee80211_node *ni)
qhead = &psq->psq_head[0]; /* 802.11 frames */
if (qhead->head != NULL) {
/* XXX could dispatch through vap and check M_ENCAP */
- parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
- } else
- parent = NULL;
+ }
qhead = &psq->psq_head[1]; /* 802.3 frames */
if (qhead->head != NULL) {
- ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
- } else
- ifp = NULL;
+ }
psq->psq_len = 0;
IEEE80211_PSQ_UNLOCK(psq);
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
/* parent frames, should be encapsulated */
- if (parent != NULL) {
- while (parent_q != NULL) {
- m = parent_q;
- parent_q = m->m_nextpkt;
- m->m_nextpkt = NULL;
- /* must be encapsulated */
- KASSERT((m->m_flags & M_ENCAP),
- ("%s: parentq with non-M_ENCAP frame!\n",
- __func__));
- /*
- * For encaped frames, we need to free the node
- * reference upon failure.
- */
- if (ieee80211_parent_xmitpkt(ic, m) != 0)
- ieee80211_free_node(ni);
- }
+ while (parent_q != NULL) {
+ m = parent_q;
+ parent_q = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ /* must be encapsulated */
+ KASSERT((m->m_flags & M_ENCAP),
+ ("%s: parentq with non-M_ENCAP frame!\n",
+ __func__));
+ /*
+ * For encaped frames, we need to free the node
+ * reference upon failure.
+ */
+ if (ieee80211_parent_xmitpkt(ic, m) != 0)
+ ieee80211_free_node(ni);
}
/* VAP frames, aren't encapsulated */
- if (ifp != NULL) {
- while (ifp_q != NULL) {
- m = ifp_q;
- ifp_q = m->m_nextpkt;
- m->m_nextpkt = NULL;
- KASSERT((!(m->m_flags & M_ENCAP)),
- ("%s: vapq with M_ENCAP frame!\n", __func__));
- (void) ieee80211_vap_xmitpkt(vap, m);
- }
+ while (ifp_q != NULL) {
+ m = ifp_q;
+ ifp_q = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ KASSERT((!(m->m_flags & M_ENCAP)),
+ ("%s: vapq with M_ENCAP frame!\n", __func__));
+ (void) ieee80211_vap_xmitpkt(vap, m);
}
}
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 548daca..cbcf6b1 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -122,23 +122,23 @@ null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
void
ieee80211_proto_attach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
+ uint8_t hdrlen;
/* override the 802.3 setting */
- ifp->if_hdrlen = ic->ic_headroom
+ hdrlen = ic->ic_headroom
+ sizeof(struct ieee80211_qosframe_addr4)
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_EXTIVLEN;
/* XXX no way to recalculate on ifdetach */
- if (ALIGN(ifp->if_hdrlen) > max_linkhdr) {
+ if (ALIGN(hdrlen) > max_linkhdr) {
/* XXX sanity check... */
- max_linkhdr = ALIGN(ifp->if_hdrlen);
+ max_linkhdr = ALIGN(hdrlen);
max_hdr = max_linkhdr + max_protohdr;
max_datalen = MHLEN - max_hdr;
}
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
- TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
+ TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic);
TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
@@ -188,7 +188,10 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
int i;
/* override the 802.3 setting */
- ifp->if_hdrlen = ic->ic_ifp->if_hdrlen;
+ ifp->if_hdrlen = ic->ic_headroom
+ + sizeof(struct ieee80211_qosframe_addr4)
+ + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ + IEEE80211_WEP_EXTIVLEN;
vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT;
vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT;
@@ -1155,9 +1158,9 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap)
static void
parent_updown(void *arg, int npending)
{
- struct ifnet *parent = arg;
+ struct ieee80211com *ic = arg;
- parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
+ ic->ic_parent(ic);
}
static void
@@ -1259,7 +1262,6 @@ ieee80211_start_locked(struct ieee80211vap *vap)
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@@ -1281,8 +1283,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* We are not running; if this we are the first vap
* to be brought up auto-up the parent if necessary.
*/
- if (ic->ic_nrunning++ == 0 &&
- (parent->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if (ic->ic_nrunning++ == 0) {
/* reset the channel to a known good channel */
if (ieee80211_start_check_reset_chan(vap))
@@ -1290,8 +1291,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
- "%s: up parent %s\n", __func__, parent->if_xname);
- parent->if_flags |= IFF_UP;
+ "%s: up parent %s\n", __func__, ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
return;
}
@@ -1300,8 +1300,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* If the parent is up and running, then kick the
* 802.11 state machine as appropriate.
*/
- if ((parent->if_drv_flags & IFF_DRV_RUNNING) &&
- vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
+ if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
if (vap->iv_opmode == IEEE80211_M_STA) {
#if 0
/* XXX bypasses scan too easily; disable for now */
@@ -1384,7 +1383,6 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
- struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@@ -1394,12 +1392,10 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */
- if (--ic->ic_nrunning == 0 &&
- (parent->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (--ic->ic_nrunning == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
- "down parent %s\n", parent->if_xname);
- parent->if_flags &= ~IFF_UP;
+ "down parent %s\n", ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
}
}
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index a812393..b5918b4 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -56,7 +56,8 @@ void ieee80211_proto_detach(struct ieee80211com *);
void ieee80211_proto_vattach(struct ieee80211vap *);
void ieee80211_proto_vdetach(struct ieee80211vap *);
-void ieee80211_syncifflag_locked(struct ieee80211com *, int flag);
+void ieee80211_promisc(struct ieee80211vap *, bool);
+void ieee80211_allmulti(struct ieee80211vap *, bool);
void ieee80211_syncflag(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ht(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ext(struct ieee80211vap *, int flag);
diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c
index 9dfef2c..efbe1a8 100644
--- a/sys/net80211/ieee80211_regdomain.c
+++ b/sys/net80211/ieee80211_regdomain.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-
#include <sys/socket.h>
#include <net/if.h>
@@ -487,7 +486,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
memset(&ic->ic_channels[ic->ic_nchans], 0,
(IEEE80211_CHAN_MAX - ic->ic_nchans) *
sizeof(struct ieee80211_channel));
- ieee80211_media_init(ic);
+ ieee80211_chan_init(ic);
/*
* Invalidate channel-related state.
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index c0cbb7d..709710c 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -1706,26 +1706,6 @@ static const struct ieee80211_scanner adhoc_default = {
IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
-static void
-ap_force_promisc(struct ieee80211com *ic)
-{
- struct ifnet *ifp = ic->ic_ifp;
-
- IEEE80211_LOCK(ic);
- /* set interface into promiscuous mode */
- ifp->if_flags |= IFF_PROMISC;
- ieee80211_runtask(ic, &ic->ic_promisc_task);
- IEEE80211_UNLOCK(ic);
-}
-
-static void
-ap_reset_promisc(struct ieee80211com *ic)
-{
- IEEE80211_LOCK(ic);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- IEEE80211_UNLOCK(ic);
-}
-
static int
ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
@@ -1741,7 +1721,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
st->st_scangen++;
st->st_newscan = 1;
- ap_force_promisc(vap->iv_ic);
+ ieee80211_promisc(vap, true);
return 0;
}
@@ -1751,7 +1731,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
static int
ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
- ap_reset_promisc(vap->iv_ic);
+ ieee80211_promisc(vap, false);
return 0;
}
@@ -1825,7 +1805,7 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
return 0;
}
}
- ap_reset_promisc(ic);
+ ieee80211_promisc(vap, false);
if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) {
/*
* Manual/background scan, don't select+join the
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 26238b8..a450701 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -116,16 +116,15 @@ struct ieee80211_superg;
struct ieee80211_frame;
struct ieee80211com {
- struct ifnet *ic_ifp; /* associated device */
void *ic_softc; /* driver softc */
const char *ic_name; /* usually device name */
ieee80211_com_lock_t ic_comlock; /* state update lock */
ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */
+ LIST_ENTRY(ieee80211com) ic_next; /* on global list */
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
int ic_headroom; /* driver tx headroom needs */
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
enum ieee80211_opmode ic_opmode; /* operation mode */
- struct ifmedia ic_media; /* interface media config */
struct callout ic_inact; /* inactivity processing */
struct taskqueue *ic_tq; /* deferred state thread */
struct task ic_parent_task; /* deferred parent processing */
@@ -151,6 +150,7 @@ struct ieee80211com {
uint8_t ic_allmulti; /* vap's needing all multicast*/
uint8_t ic_nrunning; /* vap's marked running */
uint8_t ic_curmode; /* current mode */
+ uint8_t ic_macaddr[IEEE80211_ADDR_LEN];
uint16_t ic_bintval; /* beacon interval */
uint16_t ic_lintval; /* listen interval */
uint16_t ic_holdover; /* PM hold over duration */
@@ -241,6 +241,11 @@ struct ieee80211com {
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
void (*ic_vap_delete)(struct ieee80211vap *);
+ /* device specific ioctls */
+ int (*ic_ioctl)(struct ieee80211com *,
+ u_long, void *);
+ /* start/stop device */
+ void (*ic_parent)(struct ieee80211com *);
/* operating mode attachment */
ieee80211vap_attach ic_vattach[IEEE80211_OPMODE_MAX];
/* return hardware/radio capabilities */
@@ -254,6 +259,9 @@ struct ieee80211com {
int (*ic_set_quiet)(struct ieee80211_node *,
u_int8_t *quiet_elm);
+ /* regular transmit */
+ int (*ic_transmit)(struct ieee80211com *,
+ struct mbuf *);
/* send/recv 802.11 management frame */
int (*ic_send_mgmt)(struct ieee80211_node *,
int, int);
@@ -351,14 +359,15 @@ struct ieee80211vap {
TAILQ_ENTRY(ieee80211vap) iv_next; /* list of vap instances */
struct ieee80211com *iv_ic; /* back ptr to common state */
+ const uint8_t *iv_myaddr; /* MAC address: ifp or ic */
uint32_t iv_debug; /* debug msg flags */
struct ieee80211_stats iv_stats; /* statistics */
- uint8_t iv_myaddr[IEEE80211_ADDR_LEN];
uint32_t iv_flags; /* state flags */
uint32_t iv_flags_ext; /* extended state flags */
uint32_t iv_flags_ht; /* HT state flags */
uint32_t iv_flags_ven; /* vendor state flags */
+ uint32_t iv_ifflags; /* ifnet flags */
uint32_t iv_caps; /* capabilities */
uint32_t iv_htcaps; /* HT capabilities */
uint32_t iv_htextcaps; /* HT extended capabilities */
@@ -681,24 +690,24 @@ MALLOC_DECLARE(M_80211_VAP);
"\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
-void ieee80211_ifattach(struct ieee80211com *,
- const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);
int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
const char name[IFNAMSIZ], int unit,
enum ieee80211_opmode opmode, int flags,
- const uint8_t bssid[IEEE80211_ADDR_LEN],
- const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+ const uint8_t bssid[IEEE80211_ADDR_LEN]);
int ieee80211_vap_attach(struct ieee80211vap *,
- ifm_change_cb_t, ifm_stat_cb_t);
+ ifm_change_cb_t, ifm_stat_cb_t,
+ const uint8_t macaddr[IEEE80211_ADDR_LEN]);
void ieee80211_vap_detach(struct ieee80211vap *);
const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic,
const struct ieee80211_channel *);
void ieee80211_announce(struct ieee80211com *);
void ieee80211_announce_channels(struct ieee80211com *);
void ieee80211_drain(struct ieee80211com *);
-void ieee80211_media_init(struct ieee80211com *);
+void ieee80211_chan_init(struct ieee80211com *);
struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
+struct ieee80211com *ieee80211_find_com(const char *name);
int ieee80211_media_change(struct ifnet *);
void ieee80211_media_status(struct ifnet *, struct ifmediareq *);
int ieee80211_ioctl(struct ifnet *, u_long, caddr_t);
OpenPOWER on IntegriCloud