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