diff options
author | gjb <gjb@FreeBSD.org> | 2016-04-04 23:55:32 +0000 |
---|---|---|
committer | gjb <gjb@FreeBSD.org> | 2016-04-04 23:55:32 +0000 |
commit | 1dc4c40e3b35564cb2e787ad968e6b4a9fb7eb0f (patch) | |
tree | a027fe5a27446f32854d6a07b34b5f2a992bf283 /sys/net80211 | |
parent | 3669a0dced7e344be71d234ffc3a71530ef0ae08 (diff) | |
parent | 589cedfe0cde2b49d5f47fc240de37c8bf307abd (diff) | |
download | FreeBSD-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.h | 187 | ||||
-rw-r--r-- | sys/net80211/ieee80211_amrr.c | 31 | ||||
-rw-r--r-- | sys/net80211/ieee80211_dfs.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_freebsd.h | 8 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ht.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_hwmp.c | 6 | ||||
-rw-r--r-- | sys/net80211/ieee80211_input.c | 5 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.h | 5 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_power.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 7 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ratectl.c | 41 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ratectl.h | 11 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sta.c | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sw.c | 10 | ||||
-rw-r--r-- | sys/net80211/ieee80211_sta.c | 43 | ||||
-rw-r--r-- | sys/net80211/ieee80211_wds.c | 3 |
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); |