summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorgjb <gjb@FreeBSD.org>2016-04-04 23:55:32 +0000
committergjb <gjb@FreeBSD.org>2016-04-04 23:55:32 +0000
commit1dc4c40e3b35564cb2e787ad968e6b4a9fb7eb0f (patch)
treea027fe5a27446f32854d6a07b34b5f2a992bf283 /sys/net80211
parent3669a0dced7e344be71d234ffc3a71530ef0ae08 (diff)
parent589cedfe0cde2b49d5f47fc240de37c8bf307abd (diff)
downloadFreeBSD-src-1dc4c40e3b35564cb2e787ad968e6b4a9fb7eb0f.zip
FreeBSD-src-1dc4c40e3b35564cb2e787ad968e6b4a9fb7eb0f.tar.gz
MFH
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211.h187
-rw-r--r--sys/net80211/ieee80211_amrr.c31
-rw-r--r--sys/net80211/ieee80211_dfs.c2
-rw-r--r--sys/net80211/ieee80211_freebsd.h8
-rw-r--r--sys/net80211/ieee80211_ht.c2
-rw-r--r--sys/net80211/ieee80211_hwmp.c6
-rw-r--r--sys/net80211/ieee80211_input.c5
-rw-r--r--sys/net80211/ieee80211_ioctl.h5
-rw-r--r--sys/net80211/ieee80211_node.c2
-rw-r--r--sys/net80211/ieee80211_power.c2
-rw-r--r--sys/net80211/ieee80211_proto.c7
-rw-r--r--sys/net80211/ieee80211_ratectl.c41
-rw-r--r--sys/net80211/ieee80211_ratectl.h11
-rw-r--r--sys/net80211/ieee80211_scan_sta.c4
-rw-r--r--sys/net80211/ieee80211_scan_sw.c10
-rw-r--r--sys/net80211/ieee80211_sta.c43
-rw-r--r--sys/net80211/ieee80211_wds.c3
17 files changed, 326 insertions, 43 deletions
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
index 0a25392..f5fdd5a 100644
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -317,6 +317,27 @@ struct ieee80211_wme_param {
} __packed;
/*
+ * WME U-APSD qos info field defines
+ */
+#define WME_CAPINFO_UAPSD_EN 0x00000080
+#define WME_CAPINFO_UAPSD_VO 0x00000001
+#define WME_CAPINFO_UAPSD_VI 0x00000002
+#define WME_CAPINFO_UAPSD_BK 0x00000004
+#define WME_CAPINFO_UAPSD_BE 0x00000008
+#define WME_CAPINFO_UAPSD_ACFLAGS_SHIFT 0
+#define WME_CAPINFO_UAPSD_ACFLAGS_MASK 0xF
+#define WME_CAPINFO_UAPSD_MAXSP_SHIFT 5
+#define WME_CAPINFO_UAPSD_MAXSP_MASK 0x3
+#define WME_CAPINFO_IE_OFFSET 8
+#define WME_UAPSD_MAXSP(_qosinfo) \
+ (((_qosinfo) >> WME_CAPINFO_UAPSD_MAXSP_SHIFT) & \
+ WME_CAPINFO_UAPSD_MAXSP_MASK)
+#define WME_UAPSD_AC_ENABLED(_ac, _qosinfo) \
+ ((1 << (3 - (_ac))) & ( \
+ ((_qosinfo) >> WME_CAPINFO_UAPSD_ACFLAGS_SHIFT) & \
+ WME_CAPINFO_UAPSD_ACFLAGS_MASK))
+
+/*
* Management Notification Frame
*/
struct ieee80211_mnf {
@@ -346,6 +367,7 @@ struct ieee80211_action {
#define IEEE80211_ACTION_CAT_MESH 13 /* Mesh */
#define IEEE80211_ACTION_CAT_SELF_PROT 15 /* Self-protected */
/* 16 - 125 reserved */
+#define IEEE80211_ACTION_VHT 21
#define IEEE80211_ACTION_CAT_VENDOR 127 /* Vendor Specific */
#define IEEE80211_ACTION_HT_TXCHWIDTH 0 /* recommended xmit chan width*/
@@ -695,6 +717,151 @@ struct ieee80211_ie_htinfo {
#define IEEE80211_HTINFO_BASIC_STBCMCS_S 0
#define IEEE80211_HTINFO_DUALPROTECTED 0x80
+
+/*
+ * 802.11ac definitions - 802.11ac-2013 .
+ */
+
+/* VHT opmode bits */
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_MASK 3
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_20MHZ 0
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_40MHZ 1
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_80MHZ 2
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_160MHZ 3
+#define IEEE80211_VHT_OPMODE_RX_NSS_MASK 0x70
+#define IEEE80211_VHT_OPMODE_RX_NSS_SHIFT 4
+#define IEEE80211_VHT_OPMODE_RX_NSS_TYPE_BF 0x80
+
+/*
+ * Maximum length of A-MPDU that the STA can RX in VHT.
+ * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+ */
+#define IEEE80211_VHTCAP_MAX_AMPDU_8K 0
+#define IEEE80211_VHTCAP_MAX_AMPDU_16K 1
+#define IEEE80211_VHTCAP_MAX_AMPDU_32K 2
+#define IEEE80211_VHTCAP_MAX_AMPDU_64K 3
+#define IEEE80211_VHTCAP_MAX_AMPDU_128K 4
+#define IEEE80211_VHTCAP_MAX_AMPDU_256K 5
+#define IEEE80211_VHTCAP_MAX_AMPDU_512K 6
+#define IEEE80211_VHTCAP_MAX_AMPDU_1024K 7
+
+/*
+ * VHT MCS information.
+ * + rx_highest/tx_highest: optional; maximum long GI VHT PPDU
+ * data rate. 1Mbit/sec units.
+ * + rx_mcs_map/tx_mcs_map: bitmap of per-stream supported MCS;
+ * 2 bits each.
+ */
+#define IEEE80211_VHT_MCS_SUPPORT_0_7 0 /* MCS0-7 */
+#define IEEE80211_VHT_MCS_SUPPORT_0_8 1 /* MCS0-8 */
+#define IEEE80211_VHT_MCS_SUPPORT_0_9 2 /* MCS0-9 */
+#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 /* not supported */
+
+struct ieee80211_vht_mcs_info {
+ uint16_t rx_mcs_map;
+ uint16_t rx_highest;
+ uint16_t tx_mcs_map;
+ uint16_t tx_highest;
+} __packed;
+
+/* VHT capabilities element: 802.11ac-2013 8.4.2.160 */
+struct ieee80211_ie_vhtcap {
+ uint8_t ie;
+ uint8_t len;
+ uint32_t vht_cap_info;
+ struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+#define IEEE80211_VHT_CHANWIDTH_USE_HT 0 /* Use HT IE for chw */
+#define IEEE80211_VHT_CHANWIDTH_80MHZ 1 /* 80MHz */
+#define IEEE80211_VHT_CHANWIDTH_160MHZ 2 /* 160MHz */
+#define IEEE80211_VHT_CHANWIDTH_80P80MHZ 3 /* 80+80MHz */
+
+/* VHT operation IE - 802.11ac-2013 8.4.2.161 */
+struct ieee80211_ie_vht_operation {
+ uint8_t ie;
+ uint8_t len;
+ uint8_t chan_width;
+ uint8_t center_freq_seg1_idx;
+ uint8_t center_freq_seg2_idx;
+ uint16_t basic_mcs_set;
+} __packed;
+
+/* 802.11ac VHT Capabilities */
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895 0x00000000
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_7991 0x00000001
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_11454 0x00000002
+#define IEEE80211_VHTCAP_MAX_MPDU_MASK 0x00000003
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK 0x0000000C
+#define IEEE80211_VHTCAP_RXLDPC 0x00000010
+#define IEEE80211_VHTCAP_SHORT_GI_80 0x00000020
+#define IEEE80211_VHTCAP_SHORT_GI_160 0x00000040
+#define IEEE80211_VHTCAP_TXSTBC 0x00000080
+#define IEEE80211_VHTCAP_RXSTBC_1 0x00000100
+#define IEEE80211_VHTCAP_RXSTBC_2 0x00000200
+#define IEEE80211_VHTCAP_RXSTBC_3 0x00000300
+#define IEEE80211_VHTCAP_RXSTBC_4 0x00000400
+#define IEEE80211_VHTCAP_RXSTBC_MASK 0x00000700
+#define IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE 0x00000800
+#define IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+#define IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT 13
+#define IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK \
+ (7 << IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT)
+#define IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT 16
+#define IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK \
+ (7 << IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT)
+#define IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE 0x00080000
+#define IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE 0x00100000
+#define IEEE80211_VHTCAP_VHT_TXOP_PS 0x00200000
+#define IEEE80211_VHTCAP_HTC_VHT 0x00400000
+#define IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23
+#define IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \
+ (7 << IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT)
+#define IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
+#define IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
+#define IEEE80211_VHTCAP_RX_ANTENNA_PATTERN 0x10000000
+#define IEEE80211_VHTCAP_TX_ANTENNA_PATTERN 0x20000000
+
+/*
+ * VHT Transmit Power Envelope element - 802.11ac-2013 8.4.2.164
+ *
+ * This defines the maximum transmit power for various bandwidths.
+ */
+/*
+ * Count is how many elements follow and what they're for:
+ *
+ * 0 - 20 MHz
+ * 1 - 20+40 MHz
+ * 2 - 20+40+80 MHz
+ * 3 - 20+40+80+(160, 80+80) MHz
+ */
+#define IEEE80211_VHT_TXPWRENV_INFO_COUNT_SHIFT 0
+#define IEEE80211_VHT_TXPWRENV_INFO_COUNT_MASK 0x07
+
+/*
+ * Unit is the tx power representation. It should be EIRP for now;
+ * other values are reserved.
+ */
+#define IEEE80211_VHT_TXPWRENV_UNIT_MASK 0x38
+#define IEEE80211_VHT_TXPWRENV_UNIT_SHIFT 3
+
+/* This value is within the unit mask/shift above */
+#define IEEE80211_VHT_TXPWRENV_UNIT_EIRP 0
+
+struct ieee80211_ie_vht_txpwrenv {
+ uint8_t ie;
+ uint8_t len;
+ uint8_t tx_info;
+ int8_t tx_elem[0]; /* TX power elements, 1/2 dB, signed */
+};
+
+/* VHT action codes */
+#define WLAN_ACTION_VHT_COMPRESSED_BF 0
+#define WLAN_ACTION_VHT_GROUPID_MGMT 1
+#define WLAN_ACTION_VHT_OPMODE_NOTIF 2
+
/*
* Management information element payloads.
*/
@@ -709,6 +876,8 @@ enum {
IEEE80211_ELEMID_IBSSPARMS = 6,
IEEE80211_ELEMID_COUNTRY = 7,
IEEE80211_ELEMID_BSSLOAD = 11,
+ IEEE80211_ELEMID_TSPEC = 13,
+ IEEE80211_ELEMID_TCLAS = 14,
IEEE80211_ELEMID_CHALLENGE = 16,
/* 17-31 reserved for challenge text extension */
IEEE80211_ELEMID_PWRCNSTR = 32,
@@ -728,6 +897,17 @@ enum {
IEEE80211_ELEMID_XRATES = 50,
IEEE80211_ELEMID_APCHANREP = 51,
IEEE80211_ELEMID_HTINFO = 61,
+ IEEE80211_ELEMID_SECCHAN_OFFSET = 62,
+ IEEE80211_ELEMID_RRM_ENACAPS = 70,
+ IEEE80211_ELEMID_MULTIBSSID = 71,
+ IEEE80211_ELEMID_COEX_2040 = 72,
+ IEEE80211_ELEMID_INTOL_CHN_REPORT = 73,
+ IEEE80211_ELEMID_OVERLAP_BSS_SCAN_PARAM = 74,
+ IEEE80211_ELEMID_TSF_REQ = 91,
+ IEEE80211_ELEMID_TSF_RESP = 92,
+ IEEE80211_ELEMID_WNM_SLEEP_MODE = 93,
+ IEEE80211_ELEMID_TIM_BCAST_REQ = 94,
+ IEEE80211_ELEMID_TIM_BCAST_RESP = 95,
IEEE80211_ELEMID_TPC = 150,
IEEE80211_ELEMID_CCKM = 156,
IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
@@ -751,7 +931,7 @@ enum {
IEEE80211_ELEMID_MESHGANN = 125,
IEEE80211_ELEMID_MESHRANN = 126,
/* 127 Extended Capabilities */
- IEEE80211_ELEMID_MESHEXTCAP = 127,
+ IEEE80211_ELEMID_EXTCAP = 127,
/* 128-129 reserved */
IEEE80211_ELEMID_MESHPREQ = 130,
IEEE80211_ELEMID_MESHPREP = 131,
@@ -760,6 +940,11 @@ enum {
IEEE80211_ELEMID_MESHPXU = 137,
IEEE80211_ELEMID_MESHPXUC = 138,
IEEE80211_ELEMID_MESHAH = 60, /* XXX: remove */
+
+ /* 802.11ac */
+ IEEE80211_ELEMID_VHT_CAP = 191,
+ IEEE80211_ELEMID_VHT_OPMODE = 192,
+ IEEE80211_ELEMID_VHT_PWR_ENV = 195,
};
struct ieee80211_tim_ie {
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
index f50334e..7460223 100644
--- a/sys/net80211/ieee80211_amrr.c
+++ b/sys/net80211/ieee80211_amrr.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/sbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@@ -75,6 +76,7 @@ static void amrr_tx_update(const struct ieee80211vap *vap,
const struct ieee80211_node *, void *, void *, void *);
static void amrr_sysctlattach(struct ieee80211vap *,
struct sysctl_ctx_list *, struct sysctl_oid *);
+static void amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s);
/* number of references from net80211 layer */
static int nrefs = 0;
@@ -91,6 +93,7 @@ static const struct ieee80211_ratectl amrr = {
.ir_tx_complete = amrr_tx_complete,
.ir_tx_update = amrr_tx_update,
.ir_setinterval = amrr_setinterval,
+ .ir_node_stats = amrr_node_stats,
};
IEEE80211_RATECTL_MODULE(amrr, 1);
IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr);
@@ -410,3 +413,31 @@ amrr_sysctlattach(struct ieee80211vap *vap,
"amrr_min_sucess_threshold", CTLFLAG_RW,
&amrr->amrr_min_success_threshold, 0, "");
}
+
+static void
+amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
+{
+ int rate;
+ struct ieee80211_amrr_node *amn = ni->ni_rctls;
+ struct ieee80211_rateset *rs;
+
+ /* XXX TODO: check locking? */
+
+ /* XXX TODO: this should be a method */
+ if (amrr_node_is_11n(ni)) {
+ rs = (struct ieee80211_rateset *) &ni->ni_htrates;
+ rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
+ sbuf_printf(s, "rate: MCS %d\n", rate);
+ } else {
+ rs = &ni->ni_rates;
+ rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
+ sbuf_printf(s, "rate: %d Mbit\n", rate / 2);
+ }
+
+ sbuf_printf(s, "ticks: %d\n", amn->amn_ticks);
+ sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt);
+ sbuf_printf(s, "success: %u\n", amn->amn_success);
+ sbuf_printf(s, "success_threshold: %u\n", amn->amn_success_threshold);
+ sbuf_printf(s, "recovery: %u\n", amn->amn_recovery);
+ sbuf_printf(s, "retry_cnt: %u\n", amn->amn_retrycnt);
+}
diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c
index 232ceb7..4478d9e 100644
--- a/sys/net80211/ieee80211_dfs.c
+++ b/sys/net80211/ieee80211_dfs.c
@@ -245,7 +245,7 @@ dfs_timeout(void *arg)
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
if (IEEE80211_IS_CHAN_RADAR(c)) {
- if (time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
+ if (ieee80211_time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
c->ic_state &= ~IEEE80211_CHANSTATE_RADAR;
if (c->ic_state & IEEE80211_CHANSTATE_NORADAR) {
/*
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 0566da7..62f3335 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -251,10 +251,10 @@ void ieee80211_vap_destroy(struct ieee80211vap *);
#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 ieee80211_time_after(a,b) ((long)(b) - (long)(a) < 0)
+#define ieee80211_time_before(a,b) ieee80211_time_after(b,a)
+#define ieee80211_time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
+#define ieee80211_time_before_eq(a,b) ieee80211_time_after_eq(b,a)
struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 1a21734..be380e9 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -1406,7 +1406,7 @@ ieee80211_ht_timeout(struct ieee80211com *ic)
IEEE80211_LOCK_ASSERT(ic);
if ((ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) &&
- time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
+ ieee80211_time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
#if 0
IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
"%s", "time out non-HT STA present on channel");
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 6bbc32c..0c920d8 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -260,7 +260,7 @@ ieee80211_hwmp_init(void)
}
SYSINIT(wlan_hwmp, SI_SUB_DRIVERS, SI_ORDER_SECOND, ieee80211_hwmp_init, NULL);
-void
+static void
hwmp_vattach(struct ieee80211vap *vap)
{
struct ieee80211_hwmp_state *hs;
@@ -279,7 +279,7 @@ hwmp_vattach(struct ieee80211vap *vap)
vap->iv_hwmp = hs;
}
-void
+static void
hwmp_vdetach(struct ieee80211vap *vap)
{
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
@@ -289,7 +289,7 @@ hwmp_vdetach(struct ieee80211vap *vap)
vap->iv_hwmp = NULL;
}
-int
+static int
hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
{
enum ieee80211_state nstate = vap->iv_state;
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 3b4379f..5c2f9e5 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -603,9 +603,10 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
case IEEE80211_ELEMID_MESHCONF:
scan->meshconf = frm;
break;
- case IEEE80211_ELEMID_MESHEXTCAP:
- break;
#endif
+ /* Extended capabilities; nothing handles it for now */
+ case IEEE80211_ELEMID_EXTCAP:
+ break;
case IEEE80211_ELEMID_VENDOR:
if (iswpaoui(frm))
scan->wpa = frm;
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index ee98026..8c606c1 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -246,7 +246,10 @@ struct ieee80211_stats {
uint32_t is_ampdu_bar_tx_retry; /* A-MPDU BAR frames TX rtry */
uint32_t is_ampdu_bar_tx_fail; /* A-MPDU BAR frames TX fail */
- uint32_t is_spare[7];
+ uint32_t is_ff_encapfail; /* failed FF encap */
+ uint32_t is_amsdu_encapfail; /* failed A-MSDU encap */
+
+ uint32_t is_spare[5];
};
/*
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 6ac3655..520687b 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -2638,7 +2638,7 @@ ieee80211_erp_timeout(struct ieee80211com *ic)
IEEE80211_LOCK_ASSERT(ic);
if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
- time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
+ ieee80211_time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
#if 0
IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
"%s", "age out non-ERP sta present on channel");
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 587e48f..4493ed6 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -623,7 +623,7 @@ ieee80211_sta_ps_timer_check(struct ieee80211vap *vap)
/* If we've done any data within our idle interval, bail */
/* XXX hard-coded to one second for now, ew! */
- if (time_after(ic->ic_lastdata + 500, ticks))
+ if (ieee80211_time_after(ic->ic_lastdata + 500, ticks))
goto out;
/*
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 3bc3141..2feb59a 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1531,7 +1531,7 @@ beacon_miss(void *arg, int npending)
IEEE80211_LOCK(ic);
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
/*
- * We only pass events through for sta vap's in RUN state;
+ * We only pass events through for sta vap's in RUN+ state;
* may be too restrictive but for now this saves all the
* handlers duplicating these checks.
*/
@@ -1550,7 +1550,7 @@ beacon_swmiss(void *arg, int npending)
struct ieee80211com *ic = vap->iv_ic;
IEEE80211_LOCK(ic);
- if (vap->iv_state == IEEE80211_S_RUN) {
+ if (vap->iv_state >= IEEE80211_S_RUN) {
/* XXX Call multiple times if npending > zero? */
vap->iv_bmiss(vap);
}
@@ -1570,8 +1570,7 @@ ieee80211_swbmiss(void *arg)
IEEE80211_LOCK_ASSERT(ic);
- /* XXX sleep state? */
- KASSERT(vap->iv_state == IEEE80211_S_RUN,
+ KASSERT(vap->iv_state >= IEEE80211_S_RUN,
("wrong state %d", vap->iv_state));
if (ic->ic_flags & IEEE80211_F_SCAN) {
diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c
index 3eff898..e9a0e2f 100644
--- a/sys/net80211/ieee80211_ratectl.c
+++ b/sys/net80211/ieee80211_ratectl.c
@@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/sbuf.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/malloc.h>
@@ -68,12 +69,52 @@ ieee80211_ratectl_unregister(int type)
ratectls[type] = NULL;
}
+static void
+ieee80211_ratectl_sysctl_stats_node_iter(void *arg, struct ieee80211_node *ni)
+{
+
+ struct sbuf *sb = (struct sbuf *) arg;
+ sbuf_printf(sb, "MAC: %6D\n", ni->ni_macaddr, ":");
+ ieee80211_ratectl_node_stats(ni, sb);
+ sbuf_printf(sb, "\n");
+}
+
+static int
+ieee80211_ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)
+{
+ struct ieee80211vap *vap = arg1;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct sbuf sb;
+ int error;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error)
+ return (error);
+ sbuf_new_for_sysctl(&sb, NULL, 8, req);
+ sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
+
+ IEEE80211_LOCK(ic);
+ ieee80211_iterate_nodes(&ic->ic_sta,
+ ieee80211_ratectl_sysctl_stats_node_iter,
+ &sb);
+ IEEE80211_UNLOCK(ic);
+
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+
void
ieee80211_ratectl_init(struct ieee80211vap *vap)
{
if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
vap->iv_rate->ir_init(vap);
+
+ /* Attach generic stats sysctl */
+ SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), OID_AUTO,
+ "rate_stats", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, vap,
+ 0, ieee80211_ratectl_sysctl_stats, "A", "ratectl node stats");
}
void
diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h
index 5603509..9765fe7 100644
--- a/sys/net80211/ieee80211_ratectl.h
+++ b/sys/net80211/ieee80211_ratectl.h
@@ -53,6 +53,7 @@ struct ieee80211_ratectl {
const struct ieee80211_node *,
void *, void *, void *);
void (*ir_setinterval)(const struct ieee80211vap *, int);
+ void (*ir_node_stats)(struct ieee80211_node *ni, struct sbuf *s);
};
void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
@@ -115,3 +116,13 @@ ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs)
return;
vap->iv_rate->ir_setinterval(vap, msecs);
}
+
+static __inline void
+ieee80211_ratectl_node_stats(struct ieee80211_node *ni, struct sbuf *s)
+{
+ const struct ieee80211vap *vap = ni->ni_vap;
+
+ if (vap->iv_rate->ir_node_stats == NULL)
+ return;
+ vap->iv_rate->ir_node_stats(ni, s);
+}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 07df92f..233c436 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -1323,7 +1323,7 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
* XXX deauth current ap
*/
if (curRate < roamRate || curRssi < roamRssi) {
- if (time_after(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
+ if (ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
/*
* Scan cache contents are too old; force a scan now
* if possible so we have current state to make a
@@ -1333,7 +1333,7 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
* XXX force immediate switch on scan complete
*/
if (!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))
ieee80211_bg_scan(vap, 0);
return;
}
diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c
index fc62f24..5875980 100644
--- a/sys/net80211/ieee80211_scan_sw.c
+++ b/sys/net80211/ieee80211_scan_sw.c
@@ -304,7 +304,7 @@ ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan,
}
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
(flags & IEEE80211_SCAN_FLUSH) == 0 &&
- time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
+ ieee80211_time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
/*
* We're not currently scanning and the cache is
* deemed hot enough to consult. Lock out others
@@ -674,7 +674,7 @@ end:
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
(ss_priv->ss_iflags & ISCAN_ABORT) ||
- time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
+ ieee80211_time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
ss_priv->ss_iflags &= ~ISCAN_RUNNING;
scan_end(ss, scandone);
return;
@@ -686,7 +686,7 @@ end:
/*
* Watch for truncation due to the scan end time.
*/
- if (time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
+ if (ieee80211_time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
maxdwell = ss_priv->ss_scanend - ticks;
else
maxdwell = ss->ss_maxdwell;
@@ -807,7 +807,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone)
if ((ss_priv->ss_iflags & ISCAN_CANCEL) == 0 &&
!ss->ss_ops->scan_end(ss, vap) &&
(ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
- time_before(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
+ ieee80211_time_before(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: done, restart "
"[ticks %u, dwell min %lu scanend %lu]\n",
@@ -923,7 +923,7 @@ ieee80211_swscan_add_scan(struct ieee80211vap *vap,
* the timer so we'll switch to the next channel.
*/
if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
- time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
+ ieee80211_time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: chan %3d%c min dwell met (%u > %lu)\n",
__func__,
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index ee14ffd..16d801c 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -206,6 +206,24 @@ sta_authretry(struct ieee80211vap *vap, struct ieee80211_node *ni, int reason)
}
}
+static void
+sta_swbmiss_start(struct ieee80211vap *vap)
+{
+
+ if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) {
+ /*
+ * Start s/w beacon miss timer for devices w/o
+ * hardware support. We fudge a bit here since
+ * we're doing this in software.
+ */
+ vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS(
+ 2 * vap->iv_bmissthreshold * vap->iv_bss->ni_intval);
+ vap->iv_swbmiss_count = 0;
+ callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
+ ieee80211_swbmiss, vap);
+ }
+}
+
/*
* IEEE80211_M_STA vap state machine handler.
* This routine handles the main states in the 802.11 protocol.
@@ -341,12 +359,13 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
break;
}
break;
+ case IEEE80211_S_SLEEP:
case IEEE80211_S_RUN:
switch (arg & 0xff) {
case IEEE80211_FC0_SUBTYPE_AUTH:
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_AUTH, 2);
- vap->iv_state = ostate; /* stay RUN */
+ vap->iv_state = IEEE80211_S_RUN; /* stay RUN */
break;
case IEEE80211_FC0_SUBTYPE_DEAUTH:
ieee80211_sta_leave(ni);
@@ -418,19 +437,8 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
goto invalid;
}
ieee80211_sync_curchan(ic);
- if (ostate != IEEE80211_S_RUN &&
- (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
- /*
- * Start s/w beacon miss timer for devices w/o
- * hardware support. We fudge a bit here since
- * we're doing this in software.
- */
- vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS(
- 2 * vap->iv_bmissthreshold * ni->ni_intval);
- vap->iv_swbmiss_count = 0;
- callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
- ieee80211_swbmiss, vap);
- }
+ if (ostate != IEEE80211_S_RUN)
+ sta_swbmiss_start(vap);
/*
* When 802.1x is not in use mark the port authorized
* at this point so traffic can flow.
@@ -450,6 +458,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
goto invalid;
break;
case IEEE80211_S_SLEEP:
+ sta_swbmiss_start(vap);
vap->iv_sta_ps(vap, 1);
break;
default:
@@ -1244,7 +1253,7 @@ contbgscan(struct ieee80211vap *vap)
return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
(ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 &&
vap->iv_state == IEEE80211_S_RUN && /* XXX? */
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
/*
@@ -1265,8 +1274,8 @@ startbgscan(struct ieee80211vap *vap)
#ifdef IEEE80211_SUPPORT_SUPERG
!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
#endif
- time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
+ ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
static void
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index 03d9c60..7fe91cc 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -288,9 +288,11 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
/*
* Encapsulate the packet in prep for transmission.
*/
+ IEEE80211_TX_LOCK(ic);
mcopy = ieee80211_encap(vap, ni, mcopy);
if (mcopy == NULL) {
/* NB: stat+msg handled in ieee80211_encap */
+ IEEE80211_TX_UNLOCK(ic);
ieee80211_free_node(ni);
continue;
}
@@ -298,6 +300,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
mcopy->m_pkthdr.rcvif = (void *) ni;
err = ieee80211_parent_xmitpkt(ic, mcopy);
+ IEEE80211_TX_UNLOCK(ic);
if (!err) {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
OpenPOWER on IntegriCloud