PERFORCE change 130106 for review
Sam Leffler
sam at FreeBSD.org
Mon Dec 3 10:39:30 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=130106
Change 130106 by sam at sam_ebb on 2007/12/03 18:39:25
checkpoint vap integration; compiles but needs major work
and is still missing pieces
Supported by: Marvell
Affected files ...
.. //depot/projects/vap/sys/conf/files#8 edit
.. //depot/projects/vap/sys/conf/options#6 edit
.. //depot/projects/vap/sys/modules/Makefile#7 edit
.. //depot/projects/vap/sys/modules/wlan/Makefile#6 edit
.. //depot/projects/vap/sys/net/if_media.h#7 edit
.. //depot/projects/vap/sys/net80211/_ieee80211.h#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211.c#16 edit
.. //depot/projects/vap/sys/net80211/ieee80211.h#6 edit
.. //depot/projects/vap/sys/net80211/ieee80211_acl.c#6 edit
.. //depot/projects/vap/sys/net80211/ieee80211_adhoc.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_adhoc.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_amrr.c#4 edit
.. //depot/projects/vap/sys/net80211/ieee80211_amrr.h#4 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto.c#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto.h#9 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_ccmp.c#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_none.c#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_tkip.c#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto_wep.c#8 edit
.. //depot/projects/vap/sys/net80211/ieee80211_dfs.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_dfs.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_freebsd.c#13 edit
.. //depot/projects/vap/sys/net80211/ieee80211_freebsd.h#12 edit
.. //depot/projects/vap/sys/net80211/ieee80211_hostap.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_hostap.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_ht.c#4 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ht.h#4 edit
.. //depot/projects/vap/sys/net80211/ieee80211_input.c#22 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#18 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ioctl.h#10 edit
.. //depot/projects/vap/sys/net80211/ieee80211_monitor.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_monitor.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_node.c#16 edit
.. //depot/projects/vap/sys/net80211/ieee80211_node.h#11 edit
.. //depot/projects/vap/sys/net80211/ieee80211_output.c#19 edit
.. //depot/projects/vap/sys/net80211/ieee80211_power.c#6 edit
.. //depot/projects/vap/sys/net80211/ieee80211_proto.c#16 edit
.. //depot/projects/vap/sys/net80211/ieee80211_proto.h#11 edit
.. //depot/projects/vap/sys/net80211/ieee80211_radiotap.h#6 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan.c#11 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan.h#9 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan_ap.c#7 delete
.. //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#13 edit
.. //depot/projects/vap/sys/net80211/ieee80211_sta.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_sta.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#21 edit
.. //depot/projects/vap/sys/net80211/ieee80211_wds.c#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_wds.h#1 add
.. //depot/projects/vap/sys/net80211/ieee80211_xauth.c#6 edit
Differences ...
==== //depot/projects/vap/sys/conf/files#8 (text+ko) ====
@@ -1650,24 +1650,29 @@
mxge | ppp_deflate | netgraph_deflate
net80211/ieee80211.c optional wlan
net80211/ieee80211_acl.c optional wlan_acl
+net80211/ieee80211_adhoc.c optional wlan
net80211/ieee80211_amrr.c optional wlan_amrr
net80211/ieee80211_crypto.c optional wlan
net80211/ieee80211_crypto_ccmp.c optional wlan_ccmp
net80211/ieee80211_crypto_none.c optional wlan
net80211/ieee80211_crypto_tkip.c optional wlan_tkip
net80211/ieee80211_crypto_wep.c optional wlan_wep
+net80211/ieee80211_dfs.c optional wlan
net80211/ieee80211_freebsd.c optional wlan
+net80211/ieee80211_hostap.c optional wlan
net80211/ieee80211_ht.c optional wlan
net80211/ieee80211_input.c optional wlan
net80211/ieee80211_ioctl.c optional wlan
+net80211/ieee80211_monitor.c optional wlan
net80211/ieee80211_node.c optional wlan
net80211/ieee80211_output.c optional wlan
net80211/ieee80211_power.c optional wlan
net80211/ieee80211_proto.c optional wlan
net80211/ieee80211_regdomain.c optional wlan
net80211/ieee80211_scan.c optional wlan
-net80211/ieee80211_scan_ap.c optional wlan_scan_ap
net80211/ieee80211_scan_sta.c optional wlan_scan_sta
+net80211/ieee80211_sta.c optional wlan
+net80211/ieee80211_wds.c optional wlan
net80211/ieee80211_xauth.c optional wlan_xauth
netatalk/aarp.c optional netatalk
netatalk/at_control.c optional netatalk
==== //depot/projects/vap/sys/conf/options#6 (text+ko) ====
@@ -750,3 +750,8 @@
# Interrupt filtering
INTR_FILTER opt_global.h
+
+# 802.11 support layer
+IEEE80211_DEBUG opt_wlan.h
+IEEE80211_DEBUG_REFCNT opt_wlan.h
+IEEE80211_AMPDU_AGE opt_wlan.h
==== //depot/projects/vap/sys/modules/Makefile#7 (text+ko) ====
@@ -304,7 +304,6 @@
wlan_acl \
wlan_amrr \
wlan_ccmp \
- wlan_scan_ap \
wlan_scan_sta \
wlan_tkip \
wlan_wep \
==== //depot/projects/vap/sys/modules/wlan/Makefile#6 (text+ko) ====
@@ -3,16 +3,18 @@
.PATH: ${.CURDIR}/../../net80211
KMOD= wlan
-SRCS= ieee80211.c ieee80211_crypto.c ieee80211_crypto_none.c \
+SRCS= ieee80211.c ieee80211_crypto.c ieee80211_crypto_none.c ieee80211_dfs.c \
ieee80211_freebsd.c ieee80211_input.c ieee80211_ioctl.c \
ieee80211_node.c ieee80211_output.c ieee80211_power.c \
ieee80211_proto.c ieee80211_scan.c ieee80211_regdomain.c \
- ieee80211_ht.c
-SRCS+= bus_if.h device_if.h opt_compat.h opt_inet.h opt_ipx.h
+ ieee80211_ht.c \
+ ieee80211_adhoc.c ieee80211_hostap.c ieee80211_monitor.c \
+ ieee80211_sta.c ieee80211_wds.c
+SRCS+= bus_if.h device_if.h opt_inet.h opt_ipx.h opt_wlan.h
.if !defined(KERNBUILDDIR)
-opt_compat.h:
- echo "#define COMPAT_FREEBSD6 1" > ${.TARGET}
+opt_wlan.h:
+ echo "#define IEEE80211_DEBUG 1" > opt_wlan.h
opt_inet.h:
echo "#define INET 1" > opt_inet.h
==== //depot/projects/vap/sys/net/if_media.h#7 (text+ko) ====
@@ -208,7 +208,7 @@
#define IFM_IEEE80211_ADHOC 0x00000100 /* Operate in Adhoc mode */
#define IFM_IEEE80211_HOSTAP 0x00000200 /* Operate in Host AP mode */
#define IFM_IEEE80211_IBSS 0x00000400 /* Operate in IBSS mode */
-#define IFM_IEEE80211_IBSSMASTER 0x00000800 /* Operate as an IBSS master */
+#define IFM_IEEE80211_WDS 0x00000800 /* Operate in WDS mode */
#define IFM_IEEE80211_TURBO 0x00001000 /* Operate in turbo mode */
#define IFM_IEEE80211_MONITOR 0x00002000 /* Operate in monitor mode */
@@ -495,7 +495,7 @@
{ IFM_IEEE80211_ADHOC, "adhoc" }, \
{ IFM_IEEE80211_HOSTAP, "hostap" }, \
{ IFM_IEEE80211_IBSS, "ibss" }, \
- { IFM_IEEE80211_IBSSMASTER, "ibss-master" }, \
+ { IFM_IEEE80211_WDS, "wds" }, \
{ IFM_IEEE80211_TURBO, "turbo" }, \
{ IFM_IEEE80211_MONITOR, "monitor" }, \
{ 0, NULL }, \
==== //depot/projects/vap/sys/net80211/_ieee80211.h#8 (text+ko) ====
@@ -28,16 +28,31 @@
#ifndef _NET80211__IEEE80211_H_
#define _NET80211__IEEE80211_H_
+/*
+ * 802.11 implementation definitions.
+ *
+ * NB: this file is used by applications.
+ */
+
+/*
+ * PHY type; mostly used to identify FH phys.
+ */
enum ieee80211_phytype {
IEEE80211_T_DS, /* direct sequence spread spectrum */
IEEE80211_T_FH, /* frequency hopping */
IEEE80211_T_OFDM, /* frequency division multiplexing */
IEEE80211_T_TURBO, /* high rate OFDM, aka turbo mode */
- IEEE80211_T_HT, /* high throughput, full GI */
+ IEEE80211_T_HT, /* high throughput */
};
#define IEEE80211_T_CCK IEEE80211_T_DS /* more common nomenclature */
-/* XXX not really a mode; there are really multiple PHY's */
+/*
+ * PHY mode; this is not really a mode as multi-mode devices
+ * have multiple PHY's. Mode is mostly used as a shorthand
+ * for constraining which channels to consider in setting up
+ * operation. Modes used to be used more extensively when
+ * channels were identified as IEEE channel numbers.
+ */
enum ieee80211_phymode {
IEEE80211_MODE_AUTO = 0, /* autoselect */
IEEE80211_MODE_11A = 1, /* 5GHz, OFDM */
@@ -52,13 +67,18 @@
};
#define IEEE80211_MODE_MAX (IEEE80211_MODE_11NG+1)
+/*
+ * Operating mode. Devices do not necessarily support
+ * all modes; they indicate which are supported in their
+ * capabilities.
+ */
enum ieee80211_opmode {
+ IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
IEEE80211_M_STA = 1, /* infrastructure station */
- IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
+ IEEE80211_M_WDS = 2, /* WDS link */
IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
- IEEE80211_M_HOSTAP = 6, /* Software Access Point */
- IEEE80211_M_MONITOR = 8, /* Monitor mode */
- IEEE80211_M_WDS = 2 /* WDS link */
+ IEEE80211_M_HOSTAP = 4, /* Software Access Point */
+ IEEE80211_M_MONITOR = 5, /* Monitor mode */
};
#define IEEE80211_OPMODE_MAX (IEEE80211_M_MONITOR+1)
@@ -72,7 +92,11 @@
};
/*
- * Authentication mode.
+ * Authentication mode. The open and shared key authentication
+ * modes are implemented within the 802.11 layer. 802.1x and
+ * WPA/802.11i are implemented in user mode by setting the
+ * 802.11 layer into IEEE80211_AUTH_8021X and deferring
+ * authentication to user space programs.
*/
enum ieee80211_authmode {
IEEE80211_AUTH_NONE = 0,
@@ -265,18 +289,28 @@
#define IEEE80211_NONQOS_TID WME_NUM_TID /* index for non-QoS sta */
/*
+ * The 802.11 spec says at most 2007 stations may be
+ * associated at once. For most AP's this is way more
+ * than is feasible so we use a default of 128. This
+ * number may be overridden by the driver and/or by
+ * user configuration but may not be less than IEEE80211_AID_MIN.
+ */
+#define IEEE80211_AID_DEF 128
+#define IEEE80211_AID_MIN 16
+
+/*
* 802.11 rate set.
*/
#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */
#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
struct ieee80211_rateset {
- uint8_t rs_nrates;
- uint8_t rs_rates[IEEE80211_RATE_MAXSIZE];
+ uint8_t rs_nrates;
+ uint8_t rs_rates[IEEE80211_RATE_MAXSIZE];
};
/*
- * 802.11n variant of ieee80211_rateset. Instead
+ * 802.11n variant of ieee80211_rateset. Instead of
* legacy rates the entries are MCS rates. We define
* the structure such that it can be used interchangeably
* with an ieee80211_rateset (modulo structure size).
@@ -284,27 +318,58 @@
#define IEEE80211_HTRATE_MAXSIZE 127
struct ieee80211_htrateset {
- uint8_t rs_nrates;
- uint8_t rs_rates[IEEE80211_HTRATE_MAXSIZE];
+ uint8_t rs_nrates;
+ uint8_t rs_rates[IEEE80211_HTRATE_MAXSIZE];
};
#define IEEE80211_RATE_MCS 0x80
/*
- * Roaming state visible to user space. There are two
- * thresholds that control whether roaming is considered;
- * when either is exceeded the 802.11 layer will check
- * the scan cache for another AP. If the cache is stale
- * then a scan may be triggered.
+ * Per-mode transmit parameters/controls visible to user space.
+ * These can be used to set fixed transmit rate for all operating
+ * modes or on a per-client basis according to the capabilities
+ * of the client (e.g. an 11b client associated to an 11g ap).
+ *
+ * MCS are distinguished from legacy rates by or'ing in 0x80.
+ */
+struct ieee80211_txparam {
+ uint8_t ucastrate; /* ucast data rate (legacy/MCS|0x80) */
+ uint8_t mgmtrate; /* mgmt frame rate (legacy/MCS|0x80) */
+ uint8_t mcastrate; /* multicast rate (legacy/MCS|0x80) */
+ uint8_t maxretry; /* max unicast data retry count */
+};
+
+/*
+ * Per-mode roaming state visible to user space. There are two
+ * thresholds that control whether roaming is considered; when
+ * either is exceeded the 802.11 layer will check the scan cache
+ * for another AP. If the cache is stale then a scan may be
+ * triggered.
+ */
+struct ieee80211_roamparam {
+ int8_t rssi; /* rssi thresh (.5 dBm) */
+ uint8_t rate; /* tx rate thresh (.5 Mb/s or MCS) */
+ uint16_t pad; /* reserve */
+};
+
+/*
+ * Regulatory Information.
+ */
+struct ieee80211_regdomain {
+ uint16_t regdomain; /* SKU */
+ uint16_t country; /* ISO country code */
+ uint8_t location; /* I (indoor), O (outdoor), other */
+ uint8_t ecm; /* Extended Channel Mode */
+ char isocc[2]; /* country code string */
+ short pad[2];
+};
+
+/*
+ * MIMO antenna/radio state.
*/
-struct ieee80211_roam {
- int8_t rssi11a; /* rssi thresh for 11a bss */
- int8_t rssi11b; /* for 11g sta in 11b bss */
- int8_t rssi11bOnly; /* for 11b sta */
- uint8_t pad1;
- uint8_t rate11a; /* rate thresh for 11a bss */
- uint8_t rate11b; /* for 11g sta in 11b bss */
- uint8_t rate11bOnly; /* for 11b sta */
- uint8_t pad2;
+struct ieee80211_mimo_info {
+ int8_t rssi[3]; /* per-antenna rssi */
+ int8_t noise[3]; /* per-antenna noise floor */
+ uint32_t evm[3]; /* EVM data */
};
#endif /* _NET80211__IEEE80211_H_ */
==== //depot/projects/vap/sys/net80211/ieee80211.c#16 (text+ko) ====
@@ -38,10 +38,13 @@
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_media.h>
+#include <net/if_types.h>
#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
#include <net/bpf.h>
@@ -57,7 +60,21 @@
"11na", /* IEEE80211_MODE_11NA */
"11ng", /* IEEE80211_MODE_11NG */
};
+static const uint8_t ieee80211broadcastaddr[IEEE80211_ADDR_LEN] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static void ieee80211_syncflag_locked(struct ieee80211com *ic, int flag);
+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 *);
+MALLOC_DEFINE(M_80211_VAP, "80211vap", "802.11 vap state");
+
/*
* Default supported rates for 802.11 operation (in IEEE .5Mb units).
*/
@@ -75,66 +92,6 @@
{ 12, { B(2), B(4), B(11), B(22), 12, 18, 24, 36, 48, 72, 96, 108 } };
#undef B
-static int media_status(enum ieee80211_opmode ,
- const struct ieee80211_channel *);
-
-/* list of all instances */
-SLIST_HEAD(ieee80211_list, ieee80211com);
-static struct ieee80211_list ieee80211_list =
- SLIST_HEAD_INITIALIZER(ieee80211_list);
-static uint8_t ieee80211_vapmap[32]; /* enough for 256 */
-static struct mtx ieee80211_vap_mtx;
-MTX_SYSINIT(ieee80211, &ieee80211_vap_mtx, "net80211 instances", MTX_DEF);
-
-static void
-ieee80211_add_vap(struct ieee80211com *ic)
-{
-#define N(a) (sizeof(a)/sizeof(a[0]))
- int i;
- uint8_t b;
-
- mtx_lock(&ieee80211_vap_mtx);
- ic->ic_vap = 0;
- for (i = 0; i < N(ieee80211_vapmap) && ieee80211_vapmap[i] == 0xff; i++)
- ic->ic_vap += NBBY;
- if (i == N(ieee80211_vapmap))
- panic("vap table full");
- for (b = ieee80211_vapmap[i]; b & 1; b >>= 1)
- ic->ic_vap++;
- setbit(ieee80211_vapmap, ic->ic_vap);
- SLIST_INSERT_HEAD(&ieee80211_list, ic, ic_next);
- mtx_unlock(&ieee80211_vap_mtx);
-#undef N
-}
-
-static void
-ieee80211_remove_vap(struct ieee80211com *ic)
-{
- mtx_lock(&ieee80211_vap_mtx);
- SLIST_REMOVE(&ieee80211_list, ic, ieee80211com, ic_next);
- KASSERT(ic->ic_vap < sizeof(ieee80211_vapmap)*NBBY,
- ("invalid vap id %d", ic->ic_vap));
- KASSERT(isset(ieee80211_vapmap, ic->ic_vap),
- ("vap id %d not allocated", ic->ic_vap));
- clrbit(ieee80211_vapmap, ic->ic_vap);
- mtx_unlock(&ieee80211_vap_mtx);
-}
-
-/*
- * Default reset method for use with the ioctl support. This
- * method is invoked after any state change in the 802.11
- * layer that should be propagated to the hardware but not
- * require re-initialization of the 802.11 state machine (e.g
- * rescanning for an ap). We always return ENETRESET which
- * should cause the driver to re-initialize the device. Drivers
- * can override this method to implement more optimized support.
- */
-static int
-ieee80211_default_reset(struct ifnet *ifp)
-{
- return ENETRESET;
-}
-
/*
* Fill in 802.11 available channel set, mark
* all available channels as active, and pick
@@ -153,6 +110,7 @@
KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX,
("invalid number of channels specified: %u", ic->ic_nchans));
memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
+ memset(ic->ic_modecaps, 0, sizeof(ic->ic_modecaps));
setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
@@ -186,9 +144,13 @@
memcpy(ic->ic_chan_active, ic->ic_chan_avail,
sizeof(ic->ic_chan_avail));
- ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */
+ /* sort channel table to allow lookup optimizations */
+ ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
+
+ /* invalidate any previous state */
ic->ic_bsschan = IEEE80211_CHAN_ANYC;
ic->ic_prevchan = NULL;
+ ic->ic_csa_newchan = NULL;
/* arbitrarily pick the first channel */
ic->ic_curchan = &ic->ic_channels[0];
@@ -206,54 +168,45 @@
#undef DEFAULTRATES
}
+static void
+null_update_mcast(struct ifnet *ifp)
+{
+ if_printf(ifp, "need multicast update callback\n");
+}
+
+static void
+null_update_promisc(struct ifnet *ifp)
+{
+ if_printf(ifp, "need promiscuous mode update callback\n");
+}
+
+/*
+ * 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)
{
struct ifnet *ifp = ic->ic_ifp;
+ struct sockaddr_dl *sdl;
+ struct ifaddr *ifa;
ether_ifattach(ifp, ic->ic_myaddr);
- ifp->if_output = ieee80211_output;
- bpfattach2(ifp, DLT_IEEE802_11,
- sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
-
- /* override the 802.3 setting */
- ifp->if_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) {
- /* XXX sanity check... */
- max_linkhdr = ALIGN(ifp->if_hdrlen);
- max_hdr = max_linkhdr + max_protohdr;
- max_datalen = MHLEN - max_hdr;
- }
-
+ IEEE80211_LOCK_INIT(ic, "ieee80211com");
+ TAILQ_INIT(&ic->ic_vaps);
/*
* Fill in 802.11 available channel set, mark all
* available channels as active, and pick a default
* channel if not already specified.
*/
- ieee80211_chan_init(ic);
+ ieee80211_media_init(ic,
+ ieee80211com_media_change, ieee80211com_media_status);
- if (ic->ic_caps & IEEE80211_C_BGSCAN) /* enable if capable */
- ic->ic_flags |= IEEE80211_F_BGSCAN;
-#if 0
- /* XXX not until WME+WPA issues resolved */
- if (ic->ic_caps & IEEE80211_C_WME) /* enable if capable */
- ic->ic_flags |= IEEE80211_F_WME;
-#endif
- if (ic->ic_caps & IEEE80211_C_BURST)
- ic->ic_flags |= IEEE80211_F_BURST;
- ic->ic_flags |= IEEE80211_F_DOTH; /* XXX out of caps, just ena */
+ ic->ic_update_mcast = null_update_mcast;
+ ic->ic_update_promisc = null_update_promisc;
ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
- ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;
- ic->ic_dtim_period = IEEE80211_DTIM_DEFAULT;
- IEEE80211_LOCK_INIT(ic, "ieee80211com");
- IEEE80211_BEACON_LOCK_INIT(ic, "beacon");
-
ic->ic_lintval = ic->ic_bintval;
ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
@@ -263,30 +216,43 @@
ieee80211_proto_attach(ic);
ieee80211_ht_attach(ic);
ieee80211_scan_attach(ic);
+ ieee80211_regdomain_attach(ic);
- ieee80211_add_vap(ic);
+ ieee80211_sysctl_attach(ic);
- ieee80211_sysctl_attach(ic); /* NB: requires ic_vap */
-
- /*
- * Install a default reset method for the ioctl support.
- * The driver is expected to fill this in before calling us.
- */
- if (ic->ic_reset == NULL)
- ic->ic_reset = ieee80211_default_reset;
-
- KASSERT(ifp->if_spare2 == NULL, ("oops, hosed"));
- ifp->if_spare2 = ic; /* XXX temp backpointer */
+ ifp->if_type = IFT_IEEE80211; /* NB: not IFT_ETHER */
+ ifp->if_addrlen = IEEE80211_ADDR_LEN;
+ ifp->if_hdrlen = 0;
+ if_attach(ifp);
+ /* NB: must do after 'cuz if_attach resets state */
+ ifp->if_mtu = IEEE80211_MTU_MAX;
+ 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), ic->ic_myaddr);
+ ifp->if_broadcastaddr = ieee80211broadcastaddr;
}
+/*
+ * Detach net80211 state on device detach. Tear down
+ * all vap's and reclaim all common state prior to the
+ * device state going away. Note we may call back into
+ * driver; it must be prepared for this.
+ */
void
ieee80211_ifdetach(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
+ struct ieee80211vap *vap;
- ieee80211_remove_vap(ic);
+ /* XXX ieee80211_stop_all? */
+ while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL)
+ ic->ic_vap_delete(vap);
ieee80211_sysctl_detach(ic);
+ ieee80211_regdomain_detach(ic);
ieee80211_scan_detach(ic);
ieee80211_ht_detach(ic);
/* NB: must be called before ieee80211_node_detach */
@@ -296,13 +262,356 @@
ieee80211_node_detach(ic);
ifmedia_removeall(&ic->ic_media);
+ bpfdetach(ifp);
+ ether_ifdetach(ifp);
+
IEEE80211_LOCK_DESTROY(ic);
- IEEE80211_BEACON_LOCK_DESTROY(ic);
+ if_detach(ifp);
+}
+
+/*
+ * Default reset method for use with the ioctl support. This
+ * method is invoked after any state change in the 802.11
+ * layer that should be propagated to the hardware but not
+ * require re-initialization of the 802.11 state machine (e.g
+ * rescanning for an ap). We always return ENETRESET which
+ * should cause the driver to re-initialize the device. Drivers
+ * can override this method to implement more optimized support.
+ */
+static int
+default_reset(struct ieee80211vap *vap)
+{
+ return ENETRESET;
+}
+
+/*
+ * Prepare a vap for use. Drivers use this call to
+ * setup net80211 state in new vap's prior attaching
+ * them with ieee80211_vap_attach (below).
+ */
+int
+ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
+ const char name[IFNAMSIZ], int unit, int opmode, int flags,
+ const uint8_t bssid[IEEE80211_ADDR_LEN])
+{
+#define IEEE80211_C_OPMODE \
+ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \
+ IEEE80211_C_MONITOR | IEEE80211_C_WDS)
+ struct ifnet *ifp;
+
+ ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ /* XXX msg,stat? */
+ return 0;
+ }
+ if_initname(ifp, name, unit);
+ ifp->if_softc = vap; /* back pointer */
+ ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
+ ifp->if_start = ieee80211_start;
+ ifp->if_ioctl = ieee80211_ioctl;
+ ifp->if_watchdog = NULL; /* NB: no watchdog routine */
+ ifp->if_init = ieee80211_init;
+ /* NB: input+output filled in by ether_ifattach */
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ vap->iv_ifp = ifp;
+ vap->iv_ic = ic;
+ vap->iv_flags = ic->ic_flags; /* propagate common flags */
+ vap->iv_flags_ext = ic->ic_flags_ext;
+ vap->iv_flags_ven = ic->ic_flags_ven;
+ vap->iv_caps = ic->ic_caps &~ IEEE80211_C_OPMODE;
+ vap->iv_htcaps = ic->ic_htcaps;
+ vap->iv_opmode = opmode;
+ switch (opmode) {
+ case IEEE80211_M_STA:
+ /* auto-enable s/w beacon miss support */
+ if (flags & IEEE80211_CLONE_NOBEACONS)
+ vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS;
+ break;
+ case IEEE80211_M_IBSS:
+ vap->iv_caps |= IEEE80211_C_IBSS;
+ break;
+ case IEEE80211_M_AHDEMO:
+ vap->iv_caps |= IEEE80211_C_AHDEMO;
+ break;
+ case IEEE80211_M_HOSTAP:
+ vap->iv_caps |= IEEE80211_C_HOSTAP;
+ break;
+ case IEEE80211_M_MONITOR:
+ vap->iv_caps |= IEEE80211_C_MONITOR;
+ break;
+ case IEEE80211_M_WDS:
+ vap->iv_caps |= IEEE80211_C_WDS;
+ /*
+ * WDS links must specify the bssid of the far end.
+ * For legacy operation this is a static relationship.
+ * For non-legacy operation the station must associate
+ * and be authorized to pass traffic. Plumbing the
+ * vap to the proper node happens when the vap
+ * transitions to RUN state.
+ */
+ IEEE80211_ADDR_COPY(vap->iv_des_bssid, bssid);
+ vap->iv_flags |= IEEE80211_F_DESBSSID;
+ if (flags & IEEE80211_CLONE_WDSLEGACY)
+ vap->iv_flags_ext |= IEEE80211_FEXT_WDSLEGACY;
+ break;
+ }
+ /*
+ * Enable various functionality by default if we're
+ * capable; the driver can override us if it knows better.
+ */
+ if (vap->iv_caps & IEEE80211_C_WME)
+ vap->iv_flags |= IEEE80211_F_WME;
+ if (vap->iv_caps & IEEE80211_C_BURST)
+ vap->iv_flags |= IEEE80211_F_BURST;
+ if (vap->iv_caps & IEEE80211_C_FF)
+ vap->iv_flags |= IEEE80211_F_FF;
+ if (vap->iv_caps & IEEE80211_C_TURBOP)
+ vap->iv_flags |= IEEE80211_F_TURBOP;
+ /* NB: bg scanning only makes sense for station mode right now */
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ (vap->iv_caps & IEEE80211_C_BGSCAN))
+ vap->iv_flags |= IEEE80211_F_BGSCAN;
+ vap->iv_flags |= IEEE80211_F_DOTH; /* XXX out of caps, just ena */
+ /* XXX out of caps, just ena */
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP)
+ vap->iv_flags_ext |= IEEE80211_FEXT_DFS;
+
+ vap->iv_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */
+ vap->iv_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;
+ vap->iv_dtim_period = IEEE80211_DTIM_DEFAULT;
+ /*
+ * Install a default reset method for the ioctl support;
+ * the driver can override this.
+ */
+ vap->iv_reset = default_reset;
+
+ IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_myaddr);
+
+ ieee80211_sysctl_vattach(vap);
+ ieee80211_crypto_vattach(vap);
+ ieee80211_node_vattach(vap);
+ ieee80211_power_vattach(vap);
+ ieee80211_proto_vattach(vap);
+ ieee80211_ht_vattach(vap);
+ ieee80211_scan_vattach(vap);
+ ieee80211_regdomain_vattach(vap);
+
+ return 1;
+#undef IEEE80211_C_OPMODE
+}
+
+/*
+ * Activate a vap. State should have been prepared with a
+ * call to ieee80211_vap_setup and by the driver. On return
+ * 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)
+{
+ struct ifnet *ifp = vap->iv_ifp;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifmediareq imr;
+ int maxrate;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
+ "%s: %s parent %s flags 0x%x flags_ext 0x%x\n",
+ __func__, ieee80211_opmode_name[vap->iv_opmode],
+ ic->ic_ifp->if_xname, vap->iv_flags, vap->iv_flags_ext);
+
+ /*
+ * Do late attach work that cannot happen until after
+ * the driver has had a chance to override defaults.
+ */
+ ieee80211_node_latevattach(vap);
+ ieee80211_power_latevattach(vap);
+
+ maxrate = ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps,
+ vap->iv_opmode == IEEE80211_M_STA, media_change, media_stat);
+ ieee80211_media_status(ifp, &imr);
+ /* NB: strip explicit mode; we're actually in autoselect */
+ ifmedia_set(&vap->iv_media, imr.ifm_active &~ IFM_MMASK);
+ if (maxrate)
+ ifp->if_baudrate = IF_Mbps(maxrate);
+
+ ether_ifattach(ifp, vap->iv_myaddr);
+ /* hook output method setup by ether_ifattach */
+ vap->iv_output = ifp->if_output;
+ ifp->if_output = ieee80211_output;
+ /* NB: if_mtu set by ether_ifattach to ETHERMTU */
+ bpfattach2(ifp, DLT_IEEE802_11, ifp->if_hdrlen, &vap->iv_rawbpf);
+
+ IEEE80211_LOCK(ic);
+ TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_PCF);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
+ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_HT);
+ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_USEHT40);
+ ieee80211_syncifflag_locked(ic, IFF_PROMISC);
+ ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ IEEE80211_UNLOCK(ic);
+
+ return 1;
+}
+
+/*
+ * Tear down vap state prior to reclaiming the ifnet.
+ */
+void
+ieee80211_vap_detach(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifnet *ifp = vap->iv_ifp;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s parent %s\n",
+ __func__, ieee80211_opmode_name[vap->iv_opmode],
+ ic->ic_ifp->if_xname);
+ /*
+ * Mark interface down so we ignore calls by the bridge
+ * to turn off promiscuous mode as a result of calling
+ * ether_ifdetach.
+ */
+ ifp->if_flags &= ~IFF_UP;
+ ieee80211_stop(vap);
bpfdetach(ifp);
ether_ifdetach(ifp);
+
+ IEEE80211_LOCK(ic);
+ TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_PCF);
+ ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
+ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_HT);
+ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_USEHT40);
+ ieee80211_syncifflag_locked(ic, IFF_PROMISC);
+ ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ IEEE80211_UNLOCK(ic);
+
+ ifmedia_removeall(&vap->iv_media);
+
+ ieee80211_regdomain_vdetach(vap);
+ ieee80211_scan_vdetach(vap);
+ ieee80211_ht_vdetach(vap);
+ /* NB: must be before ieee80211_node_vdetach */
+ ieee80211_proto_vdetach(vap);
+ ieee80211_crypto_vdetach(vap);
+ ieee80211_power_vdetach(vap);
+ ieee80211_node_vdetach(vap);
+ ieee80211_sysctl_vdetach(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.
+ */
+void
+ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
+{
+ struct ieee80211vap *vap;
+ int bit;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ bit = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if (vap->iv_ifp->if_flags & flag) {
+ bit = 1;
+ break;
+ }
+ if (bit)
+ ic->ic_ifp->if_flags |= flag;
+ else
+ ic->ic_ifp->if_flags &= ~flag;
+}
+
+/*
+ * Synchronize flag bit state in the com structure
+ * according to the state of all vap's. This is used,
+ * for example, to handle state changes via ioctls.
+ */
+static void
+ieee80211_syncflag_locked(struct ieee80211com *ic, int flag)
+{
+ struct ieee80211vap *vap;
+ int bit;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ bit = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if (vap->iv_flags & flag) {
+ bit = 1;
+ break;
+ }
+ if (bit)
+ ic->ic_flags |= flag;
+ else
+ ic->ic_flags &= ~flag;
+}
+
+void
+ieee80211_syncflag(struct ieee80211vap *vap, int flag)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ IEEE80211_LOCK(ic);
+ if (flag < 0) {
+ flag = -flag;
+ vap->iv_flags &= ~flag;
+ } else
+ vap->iv_flags |= flag;
+ ieee80211_syncflag_locked(ic, flag);
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Synchronize flag bit state in the com structure
+ * according to the state of all vap's. This is used,
+ * for example, to handle state changes via ioctls.
+ */
+static void
+ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag)
+{
+ struct ieee80211vap *vap;
+ int bit;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ bit = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if (vap->iv_flags_ext & flag) {
+ bit = 1;
+ break;
+ }
+ if (bit)
+ ic->ic_flags_ext |= flag;
+ else
+ ic->ic_flags_ext &= ~flag;
+}
+
+void
+ieee80211_syncflag_ext(struct ieee80211vap *vap, int flag)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ IEEE80211_LOCK(ic);
+ if (flag < 0) {
+ flag = -flag;
+ vap->iv_flags_ext &= ~flag;
+ } else
+ vap->iv_flags_ext |= flag;
+ ieee80211_syncflag_ext_locked(ic, flag);
+ IEEE80211_UNLOCK(ic);
+}
+
static __inline int
mapgsm(u_int freq, u_int flags)
{
@@ -416,7 +725,7 @@
/*
* Locate a channel given a frequency+flags. We cache
- * the previous lookup to optimize swithing between two
+ * the previous lookup to optimize switching between two
* channels--as happens with dynamic turbo.
*/
struct ieee80211_channel *
@@ -467,80 +776,58 @@
}
static void
-addmedia(struct ieee80211com *ic, int mode, int mword)
+addmedia(struct ifmedia *media, int caps, int addsta, int mode, int mword)
{
-#define TURBO(m) ((m) | IFM_IEEE80211_TURBO)
#define ADD(_ic, _s, _o) \
- ifmedia_add(&(_ic)->ic_media, \
+ ifmedia_add(media, \
IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
static const u_int mopts[IEEE80211_MODE_MAX] = {
- IFM_AUTO, /* IEEE80211_MODE_AUTO */
- IFM_IEEE80211_11A, /* IEEE80211_MODE_11A */
- IFM_IEEE80211_11B, /* IEEE80211_MODE_11B */
- IFM_IEEE80211_11G, /* IEEE80211_MODE_11G */
- IFM_IEEE80211_FH, /* IEEE80211_MODE_FH */
- TURBO(IFM_IEEE80211_11A), /* IEEE80211_MODE_TURBO_A */
- TURBO(IFM_IEEE80211_11G), /* IEEE80211_MODE_TURBO_G */
- TURBO(IFM_IEEE80211_11A), /* IEEE80211_MODE_STURBO_A */
- IFM_IEEE80211_11NA, /* IEEE80211_MODE_11NA */
- IFM_IEEE80211_11NG, /* IEEE80211_MODE_11NG */
+ IFM_AUTO,
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list