summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_freebsd.h
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-04-20 20:35:46 +0000
committersam <sam@FreeBSD.org>2008-04-20 20:35:46 +0000
commit3569e353ca63336d80ab0143dd9669b0b9e6b123 (patch)
treebc7985c57e7ecfa1ac03e48c406a25430dba634b /sys/net80211/ieee80211_freebsd.h
parent682b4ae9be70192e298129ada878af3486683aaf (diff)
downloadFreeBSD-src-3569e353ca63336d80ab0143dd9669b0b9e6b123.zip
FreeBSD-src-3569e353ca63336d80ab0143dd9669b0b9e6b123.tar.gz
Multi-bss (aka vap) support for 802.11 devices.
Note this includes changes to all drivers and moves some device firmware loading to use firmware(9) and a separate module (e.g. ral). Also there no longer are separate wlan_scan* modules; this functionality is now bundled into the wlan module. Supported by: Hobnob and Marvell Reviewed by: many Obtained from: Atheros (some bits)
Diffstat (limited to 'sys/net80211/ieee80211_freebsd.h')
-rw-r--r--sys/net80211/ieee80211_freebsd.h318
1 files changed, 253 insertions, 65 deletions
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 0052dfe..bccc0cf 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Sam Leffler, Errno Consulting
+ * Copyright (c) 2003-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,12 +28,18 @@
#define _NET80211_IEEE80211_FREEBSD_H_
#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+
/*
* Common state locking definitions.
*/
typedef struct mtx ieee80211_com_lock_t;
#define IEEE80211_LOCK_INIT(_ic, _name) \
- mtx_init(&(_ic)->ic_comlock, _name, "802.11 com lock", MTX_DEF)
+ mtx_init(&(_ic)->ic_comlock, _name, "802.11 com lock", \
+ MTX_DEF | MTX_RECURSE)
#define IEEE80211_LOCK_DESTROY(_ic) mtx_destroy(&(_ic)->ic_comlock)
#define IEEE80211_LOCK(_ic) mtx_lock(&(_ic)->ic_comlock)
#define IEEE80211_UNLOCK(_ic) mtx_unlock(&(_ic)->ic_comlock)
@@ -41,43 +47,61 @@ typedef struct mtx ieee80211_com_lock_t;
mtx_assert(&(_ic)->ic_comlock, MA_OWNED)
/*
- * Beacon locking definitions.
- */
-typedef struct mtx ieee80211_beacon_lock_t;
-#define IEEE80211_BEACON_LOCK_INIT(_ic, _name) \
- mtx_init(&(_ic)->ic_beaconlock, _name, "802.11 beacon lock", MTX_DEF)
-#define IEEE80211_BEACON_LOCK_DESTROY(_ic) mtx_destroy(&(_ic)->ic_beaconlock)
-#define IEEE80211_BEACON_LOCK(_ic) mtx_lock(&(_ic)->ic_beaconlock)
-#define IEEE80211_BEACON_UNLOCK(_ic) mtx_unlock(&(_ic)->ic_beaconlock)
-#define IEEE80211_BEACON_LOCK_ASSERT(_ic) \
- mtx_assert(&(_ic)->ic_beaconlock, MA_OWNED)
-
-/*
* Node locking definitions.
- * NB: MTX_DUPOK is because we don't generate per-interface strings.
*/
-typedef struct mtx ieee80211_node_lock_t;
-#define IEEE80211_NODE_LOCK_INIT(_nt, _name) \
- mtx_init(&(_nt)->nt_nodelock, _name, "802.11 node table", \
- MTX_DEF | MTX_DUPOK)
-#define IEEE80211_NODE_LOCK_DESTROY(_nt) mtx_destroy(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_LOCK(_nt) mtx_lock(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_IS_LOCKED(_nt) mtx_owned(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_UNLOCK(_nt) mtx_unlock(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_LOCK_ASSERT(_nt) \
- mtx_assert(&(_nt)->nt_nodelock, MA_OWNED)
+typedef struct {
+ char name[16]; /* e.g. "ath0_node_lock" */
+ struct mtx mtx;
+} ieee80211_node_lock_t;
+#define IEEE80211_NODE_LOCK_INIT(_nt, _name) do { \
+ ieee80211_node_lock_t *nl = &(_nt)->nt_nodelock; \
+ snprintf(nl->name, sizeof(nl->name), "%s_node_lock", _name); \
+ mtx_init(&nl->mtx, NULL, nl->name, MTX_DEF | MTX_RECURSE); \
+} while (0)
+#define IEEE80211_NODE_LOCK_DESTROY(_nt) \
+ mtx_destroy(&(_nt)->nt_nodelock.mtx)
+#define IEEE80211_NODE_LOCK(_nt) \
+ mtx_lock(&(_nt)->nt_nodelock.mtx)
+#define IEEE80211_NODE_IS_LOCKED(_nt) \
+ mtx_owned(&(_nt)->nt_nodelock.mtx)
+#define IEEE80211_NODE_UNLOCK(_nt) \
+ mtx_unlock(&(_nt)->nt_nodelock.mtx)
+#define IEEE80211_NODE_LOCK_ASSERT(_nt) \
+ mtx_assert(&(_nt)->nt_nodelock.mtx, MA_OWNED)
/*
- * Node table scangen locking definitions.
+ * Node table iteration locking definitions; this protects the
+ * scan generation # used to iterate over the station table
+ * while grabbing+releasing the node lock.
*/
-typedef struct mtx ieee80211_scan_lock_t;
-#define IEEE80211_SCAN_LOCK_INIT(_nt, _name) \
- mtx_init(&(_nt)->nt_scanlock, _name, "802.11 node scangen", MTX_DEF)
-#define IEEE80211_SCAN_LOCK_DESTROY(_nt) mtx_destroy(&(_nt)->nt_scanlock)
-#define IEEE80211_SCAN_LOCK(_nt) mtx_lock(&(_nt)->nt_scanlock)
-#define IEEE80211_SCAN_UNLOCK(_nt) mtx_unlock(&(_nt)->nt_scanlock)
-#define IEEE80211_SCAN_LOCK_ASSERT(_nt) \
- mtx_assert(&(_nt)->nt_scanlock, MA_OWNED)
+typedef struct {
+ char name[16]; /* e.g. "ath0_scan_lock" */
+ struct mtx mtx;
+} ieee80211_scan_lock_t;
+#define IEEE80211_NODE_ITERATE_LOCK_INIT(_nt, _name) do { \
+ ieee80211_scan_lock_t *sl = &(_nt)->nt_scanlock; \
+ snprintf(sl->name, sizeof(sl->name), "%s_scan_lock", _name); \
+ mtx_init(&sl->mtx, NULL, sl->name, MTX_DEF); \
+} while (0)
+#define IEEE80211_NODE_ITERATE_LOCK_DESTROY(_nt) \
+ mtx_destroy(&(_nt)->nt_scanlock.mtx)
+#define IEEE80211_NODE_ITERATE_LOCK(_nt) \
+ mtx_lock(&(_nt)->nt_scanlock.mtx)
+#define IEEE80211_NODE_ITERATE_UNLOCK(_nt) \
+ mtx_unlock(&(_nt)->nt_scanlock.mtx)
+
+#define _AGEQ_ENQUEUE(_ifq, _m, _qlen, _age) do { \
+ (_m)->m_nextpkt = NULL; \
+ if ((_ifq)->ifq_tail != NULL) { \
+ _age -= M_AGE_GET((_ifq)->ifq_tail); \
+ (_ifq)->ifq_tail->m_nextpkt = (_m); \
+ } else { \
+ (_ifq)->ifq_head = (_m); \
+ } \
+ M_AGE_SET(_m, _age); \
+ (_ifq)->ifq_tail = (_m); \
+ (_qlen) = ++(_ifq)->ifq_len; \
+} while (0)
/*
* Per-node power-save queue definitions.
@@ -113,16 +137,7 @@ typedef struct mtx ieee80211_scan_lock_t;
_IF_DEQUEUE(&(_ni)->ni_savedq, m); \
} while (0)
#define _IEEE80211_NODE_SAVEQ_ENQUEUE(_ni, _m, _qlen, _age) do {\
- (_m)->m_nextpkt = NULL; \
- if ((_ni)->ni_savedq.ifq_tail != NULL) { \
- _age -= M_AGE_GET((_ni)->ni_savedq.ifq_tail); \
- (_ni)->ni_savedq.ifq_tail->m_nextpkt = (_m); \
- } else { \
- (_ni)->ni_savedq.ifq_head = (_m); \
- } \
- M_AGE_SET(_m, _age); \
- (_ni)->ni_savedq.ifq_tail = (_m); \
- (_qlen) = ++(_ni)->ni_savedq.ifq_len; \
+ _AGEQ_ENQUEUE(&ni->ni_savedq, _m, _qlen, _age); \
} while (0)
#define IEEE80211_TAPQ_INIT(_tap) do { \
@@ -147,6 +162,24 @@ typedef struct mtx ieee80211_scan_lock_t;
} while (0)
#endif /* IF_PREPEND_LIST */
+/* XXX temporary */
+#define IEEE80211_NODE_WDSQ_INIT(_ni, _name) do { \
+ mtx_init(&(_ni)->ni_wdsq.ifq_mtx, _name, "802.11 wds queue", MTX_DEF);\
+ (_ni)->ni_wdsq.ifq_maxlen = IEEE80211_PS_MAX_QUEUE; \
+} while (0)
+#define IEEE80211_NODE_WDSQ_DESTROY(_ni) do { \
+ mtx_destroy(&(_ni)->ni_wdsq.ifq_mtx); \
+} while (0)
+#define IEEE80211_NODE_WDSQ_QLEN(_ni) _IF_QLEN(&(_ni)->ni_wdsq)
+#define IEEE80211_NODE_WDSQ_LOCK(_ni) IF_LOCK(&(_ni)->ni_wdsq)
+#define IEEE80211_NODE_WDSQ_UNLOCK(_ni) IF_UNLOCK(&(_ni)->ni_wdsq)
+#define _IEEE80211_NODE_WDSQ_DEQUEUE_HEAD(_ni, _m) do { \
+ _IF_DEQUEUE(&(_ni)->ni_wdsq, m); \
+} while (0)
+#define _IEEE80211_NODE_WDSQ_ENQUEUE(_ni, _m, _qlen, _age) do { \
+ _AGEQ_ENQUEUE(&ni->ni_wdsq, _m, _qlen, _age); \
+} while (0)
+
/*
* 802.1x MAC ACL database locking definitions.
*/
@@ -182,43 +215,53 @@ int ieee80211_node_dectestref(struct ieee80211_node *ni);
#define ieee80211_node_refcnt(_ni) (_ni)->ni_refcnt
struct ifqueue;
+struct ieee80211vap;
void ieee80211_drain_ifq(struct ifqueue *);
+void ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *);
+
+void ieee80211_vap_destroy(struct ieee80211vap *);
+
+#define IFNET_IS_UP_RUNNING(_ifp) \
+ (((_ifp)->if_flags & IFF_UP) && \
+ ((_ifp)->if_drv_flags & IFF_DRV_RUNNING))
#define msecs_to_ticks(ms) (((ms)*hz)/1000)
-#define ticks_to_msecs(t) ((t) / hz)
+#define ticks_to_msecs(t) (1000*(t) / hz)
+#define ticks_to_secs(t) ((t) / hz)
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
#define time_before_eq(a,b) time_after_eq(b,a)
+#define memmove(dst, src, n) ovbcopy(src, dst, n)
+
struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
/* tx path usage */
#define M_LINK0 M_PROTO1 /* WEP requested */
+#define M_WDS M_PROTO2 /* WDS frame */
+#define M_EAPOL M_PROTO3 /* PAE/EAPOL frame */
#define M_PWR_SAV M_PROTO4 /* bypass PS handling */
#define M_MORE_DATA M_PROTO5 /* more data frames to follow */
-#define M_FF 0x20000 /* fast frame */
-#define M_TXCB 0x40000 /* do tx complete callback */
-#define M_80211_TX (0x60000|M_PROTO1|M_WME_AC_MASK|M_PROTO4|M_PROTO5)
+#define M_FF M_PROTO6 /* fast frame */
+#define M_TXCB M_PROTO7 /* do tx complete callback */
+#define M_80211_TX \
+ (M_LINK0|M_WDS|M_EAPOL|M_PWR_SAV|M_MORE_DATA|M_FF|M_TXCB)
/* rx path usage */
#define M_AMPDU M_PROTO1 /* A-MPDU processing done */
#define M_WEP M_PROTO2 /* WEP done by hardware */
#define M_80211_RX (M_AMPDU|M_WEP)
/*
- * Encode WME access control bits in the PROTO flags.
- * This is safe since it's passed directly in to the
- * driver and there's no chance someone else will clobber
- * them on us.
+ * Store WME access control bits in the vlan tag.
+ * This is safe since it's done after the packet is classified
+ * (where we use any previous tag) and because it's passed
+ * directly in to the driver and there's no chance someone
+ * else will clobber them on us.
*/
-#define M_WME_AC_MASK (M_PROTO2|M_PROTO3)
-/* XXX 5 is wrong if M_PROTO* are redefined */
-#define M_WME_AC_SHIFT 5
-
#define M_WME_SETAC(m, ac) \
- ((m)->m_flags = ((m)->m_flags &~ M_WME_AC_MASK) | \
- ((ac) << M_WME_AC_SHIFT))
-#define M_WME_GETAC(m) (((m)->m_flags >> M_WME_AC_SHIFT) & 0x3)
+ ((m)->m_pkthdr.ether_vtag = (ac))
+#define M_WME_GETAC(m) ((m)->m_pkthdr.ether_vtag)
/*
* Mbufs on the power save queue are tagged with an age and
@@ -246,16 +289,29 @@ struct ieee80211com;
void ieee80211_sysctl_attach(struct ieee80211com *);
void ieee80211_sysctl_detach(struct ieee80211com *);
+void ieee80211_sysctl_vattach(struct ieee80211vap *);
+void ieee80211_sysctl_vdetach(struct ieee80211vap *);
void ieee80211_load_module(const char *);
-#define IEEE80211_CRYPTO_MODULE(name, version) \
+/*
+ * A "policy module" is an adjunct module to net80211 that provides
+ * functionality that typically includes policy decisions. This
+ * modularity enables extensibility and vendor-supplied functionality.
+ */
+#define _IEEE80211_POLICY_MODULE(policy, name, version) \
+typedef void (*policy##_setup)(int); \
+SET_DECLARE(policy##_set, policy##_setup); \
static int \
-name##_modevent(module_t mod, int type, void *unused) \
+wlan_##name##_modevent(module_t mod, int type, void *unused) \
{ \
+ policy##_setup * const *iter, f; \
switch (type) { \
case MOD_LOAD: \
- ieee80211_crypto_register(&name); \
+ SET_FOREACH(iter, policy##_set) { \
+ f = (void*) *iter; \
+ f(type); \
+ } \
return 0; \
case MOD_UNLOAD: \
case MOD_QUIESCE: \
@@ -264,20 +320,100 @@ name##_modevent(module_t mod, int type, void *unused) \
nrefs); \
return EBUSY; \
} \
- if (type == MOD_UNLOAD) \
- ieee80211_crypto_unregister(&name); \
+ if (type == MOD_UNLOAD) { \
+ SET_FOREACH(iter, policy##_set) { \
+ f = (void*) *iter; \
+ f(type); \
+ } \
+ } \
return 0; \
} \
return EINVAL; \
} \
static moduledata_t name##_mod = { \
"wlan_" #name, \
- name##_modevent, \
+ wlan_##name##_modevent, \
0 \
}; \
DECLARE_MODULE(wlan_##name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
MODULE_VERSION(wlan_##name, version); \
MODULE_DEPEND(wlan_##name, wlan, 1, 1, 1)
+
+/*
+ * Crypto modules implement cipher support.
+ */
+#define IEEE80211_CRYPTO_MODULE(name, version) \
+_IEEE80211_POLICY_MODULE(crypto, name, version); \
+static void \
+name##_modevent(int type) \
+{ \
+ if (type == MOD_LOAD) \
+ ieee80211_crypto_register(&name); \
+ else \
+ ieee80211_crypto_unregister(&name); \
+} \
+TEXT_SET(crypto##_set, name##_modevent)
+
+/*
+ * Scanner modules provide scanning policy.
+ */
+#define IEEE80211_SCANNER_MODULE(name, version) \
+ _IEEE80211_POLICY_MODULE(scanner, name, version)
+
+#define IEEE80211_SCANNER_ALG(name, alg, v) \
+static void \
+name##_modevent(int type) \
+{ \
+ if (type == MOD_LOAD) \
+ ieee80211_scanner_register(alg, &v); \
+ else \
+ ieee80211_scanner_unregister(alg, &v); \
+} \
+TEXT_SET(scanner_set, name##_modevent); \
+
+/*
+ * ACL modules implement acl policy.
+ */
+#define IEEE80211_ACL_MODULE(name, alg, version) \
+_IEEE80211_POLICY_MODULE(acl, name, version); \
+static void \
+alg##_modevent(int type) \
+{ \
+ if (type == MOD_LOAD) \
+ ieee80211_aclator_register(&alg); \
+ else \
+ ieee80211_aclator_unregister(&alg); \
+} \
+TEXT_SET(acl_set, alg##_modevent); \
+
+/*
+ * Authenticator modules handle 802.1x/WPA authentication.
+ */
+#define IEEE80211_AUTH_MODULE(name, version) \
+ _IEEE80211_POLICY_MODULE(auth, name, version)
+
+#define IEEE80211_AUTH_ALG(name, alg, v) \
+static void \
+name##_modevent(int type) \
+{ \
+ if (type == MOD_LOAD) \
+ ieee80211_authenticator_register(alg, &v); \
+ else \
+ ieee80211_authenticator_unregister(alg); \
+} \
+TEXT_SET(auth_set, name##_modevent)
+
+/*
+ * Rate control modules provide tx rate control support.
+ */
+#define IEEE80211_RATE_MODULE(alg, version) \
+_IEEE80211_POLICY_MODULE(rate, alg, version); \
+static void \
+alg##_modevent(int type) \
+{ \
+ /* XXX nothing to do until the rate control framework arrives */\
+} \
+TEXT_SET(rate##_set, alg##_modevent)
#endif /* _KERNEL */
/* XXX this stuff belongs elsewhere */
@@ -310,6 +446,50 @@ struct ieee80211_michael_event {
uint8_t iev_keyix; /* key id/index */
};
+struct ieee80211_wds_event {
+ uint8_t iev_addr[6];
+};
+
+struct ieee80211_csa_event {
+ uint32_t iev_flags; /* channel flags */
+ uint16_t iev_freq; /* setting in Mhz */
+ uint8_t iev_ieee; /* IEEE channel number */
+ uint8_t iev_mode; /* CSA mode */
+ uint8_t iev_count; /* CSA count */
+};
+
+struct ieee80211_cac_event {
+ uint32_t iev_flags; /* channel flags */
+ uint16_t iev_freq; /* setting in Mhz */
+ uint8_t iev_ieee; /* IEEE channel number */
+ /* XXX timestamp? */
+ uint8_t iev_type; /* IEEE80211_NOTIFY_CAC_* */
+};
+
+struct ieee80211_radar_event {
+ uint32_t iev_flags; /* channel flags */
+ uint16_t iev_freq; /* setting in Mhz */
+ uint8_t iev_ieee; /* IEEE channel number */
+ /* XXX timestamp? */
+};
+
+struct ieee80211_auth_event {
+ uint8_t iev_addr[6];
+};
+
+struct ieee80211_deauth_event {
+ uint8_t iev_addr[6];
+};
+
+struct ieee80211_country_event {
+ uint8_t iev_addr[6];
+ uint8_t iev_cc[2]; /* ISO country code */
+};
+
+struct ieee80211_radio_event {
+ uint8_t iev_state; /* 1 on, 0 off */
+};
+
#define RTM_IEEE80211_ASSOC 100 /* station associate (bss mode) */
#define RTM_IEEE80211_REASSOC 101 /* station re-associate (bss mode) */
#define RTM_IEEE80211_DISASSOC 102 /* station disassociate (bss mode) */
@@ -319,6 +499,14 @@ struct ieee80211_michael_event {
#define RTM_IEEE80211_REPLAY 106 /* sequence counter replay detected */
#define RTM_IEEE80211_MICHAEL 107 /* Michael MIC failure detected */
#define RTM_IEEE80211_REJOIN 108 /* station re-associate (ap mode) */
+#define RTM_IEEE80211_WDS 109 /* WDS discovery (ap mode) */
+#define RTM_IEEE80211_CSA 110 /* Channel Switch Announcement event */
+#define RTM_IEEE80211_RADAR 111 /* radar event */
+#define RTM_IEEE80211_CAC 112 /* Channel Availability Check event */
+#define RTM_IEEE80211_DEAUTH 113 /* station deauthenticate */
+#define RTM_IEEE80211_AUTH 114 /* station authenticate (ap mode) */
+#define RTM_IEEE80211_COUNTRY 115 /* discovered country code (sta mode) */
+#define RTM_IEEE80211_RADIO 116 /* RF kill switch state change */
/*
* Structure prepended to raw packets sent through the bpf
OpenPOWER on IntegriCloud