wlan - Sync netproto/802_11 from FreeBSD part 1/N
authorMatthew Dillon <dillon@backplane.com>
Thu, 12 May 2016 04:58:36 +0000 (21:58 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 24 May 2016 04:26:46 +0000 (21:26 -0700)
* Sync netproto/802_11 from FreeBSD, fbsd git dd885b9a0a0e, May 11 2016.

51 files changed:
sys/netproto/802_11/_ieee80211.h
sys/netproto/802_11/ieee80211.h
sys/netproto/802_11/ieee80211_crypto.h
sys/netproto/802_11/ieee80211_dragonfly.h
sys/netproto/802_11/ieee80211_ht.h
sys/netproto/802_11/ieee80211_input.h
sys/netproto/802_11/ieee80211_ioctl.h
sys/netproto/802_11/ieee80211_node.h
sys/netproto/802_11/ieee80211_phy.h
sys/netproto/802_11/ieee80211_proto.h
sys/netproto/802_11/ieee80211_ratectl.h
sys/netproto/802_11/ieee80211_superg.h
sys/netproto/802_11/ieee80211_var.h
sys/netproto/802_11/wlan/ieee80211.c
sys/netproto/802_11/wlan/ieee80211_action.c
sys/netproto/802_11/wlan/ieee80211_adhoc.c
sys/netproto/802_11/wlan/ieee80211_ageq.c
sys/netproto/802_11/wlan/ieee80211_amrr.c
sys/netproto/802_11/wlan/ieee80211_crypto.c
sys/netproto/802_11/wlan/ieee80211_crypto_none.c
sys/netproto/802_11/wlan/ieee80211_ddb.c
sys/netproto/802_11/wlan/ieee80211_dfs.c
sys/netproto/802_11/wlan/ieee80211_dragonfly.c
sys/netproto/802_11/wlan/ieee80211_hostap.c
sys/netproto/802_11/wlan/ieee80211_ht.c
sys/netproto/802_11/wlan/ieee80211_hwmp.c
sys/netproto/802_11/wlan/ieee80211_input.c
sys/netproto/802_11/wlan/ieee80211_ioctl.c
sys/netproto/802_11/wlan/ieee80211_mesh.c
sys/netproto/802_11/wlan/ieee80211_monitor.c
sys/netproto/802_11/wlan/ieee80211_node.c
sys/netproto/802_11/wlan/ieee80211_output.c
sys/netproto/802_11/wlan/ieee80211_phy.c
sys/netproto/802_11/wlan/ieee80211_power.c
sys/netproto/802_11/wlan/ieee80211_proto.c
sys/netproto/802_11/wlan/ieee80211_ratectl.c
sys/netproto/802_11/wlan/ieee80211_ratectl_none.c
sys/netproto/802_11/wlan/ieee80211_regdomain.c
sys/netproto/802_11/wlan/ieee80211_rssadapt.c
sys/netproto/802_11/wlan/ieee80211_scan.c
sys/netproto/802_11/wlan/ieee80211_scan_sta.c
sys/netproto/802_11/wlan/ieee80211_scan_sw.c
sys/netproto/802_11/wlan/ieee80211_sta.c
sys/netproto/802_11/wlan/ieee80211_superg.c
sys/netproto/802_11/wlan/ieee80211_tdma.c
sys/netproto/802_11/wlan/ieee80211_wds.c
sys/netproto/802_11/wlan_acl/ieee80211_acl.c
sys/netproto/802_11/wlan_ccmp/ieee80211_crypto_ccmp.c
sys/netproto/802_11/wlan_tkip/ieee80211_crypto_tkip.c
sys/netproto/802_11/wlan_wep/ieee80211_crypto_wep.c
sys/netproto/802_11/wlan_xauth/ieee80211_xauth.c

index 5120d41..4aab224 100644 (file)
@@ -70,6 +70,7 @@ enum ieee80211_phymode {
        IEEE80211_MODE_QUARTER  = 11,   /* OFDM, 1/4x clock */
 };
 #define        IEEE80211_MODE_MAX      (IEEE80211_MODE_QUARTER+1)
+#define IEEE80211_MODE_BYTES   howmany(IEEE80211_MODE_MAX, NBBY)
 
 /*
  * Operating mode.  Devices do not necessarily support
@@ -146,7 +147,7 @@ struct ieee80211_channel {
 };
 
 #define        IEEE80211_CHAN_MAX      256
-#define        IEEE80211_CHAN_BYTES    32      /* howmany(IEEE80211_CHAN_MAX, NBBY) */
+#define        IEEE80211_CHAN_BYTES    howmany(IEEE80211_CHAN_MAX, NBBY)
 #define        IEEE80211_CHAN_ANY      0xffff  /* token for ``any channel'' */
 #define        IEEE80211_CHAN_ANYC \
        ((struct ieee80211_channel *) IEEE80211_CHAN_ANY)
@@ -390,15 +391,14 @@ struct ieee80211_regdomain {
  * MIMO antenna/radio state.
  */
 
-#define        IEEE80211_MAX_CHAINS            3
-#define        IEEE80211_MAX_EVM_PILOTS        6
-
 /*
  * XXX This doesn't yet export both ctl/ext chain details
+ * XXX TODO: IEEE80211_MAX_CHAINS is defined in _freebsd.h, not here;
+ * figure out how to pull it in!
  */
 struct ieee80211_mimo_info {
-       int8_t          rssi[IEEE80211_MAX_CHAINS];     /* per-antenna rssi */
-       int8_t          noise[IEEE80211_MAX_CHAINS];    /* per-antenna noise floor */
+       int8_t          rssi[3];        /* per-antenna rssi */
+       int8_t          noise[3];       /* per-antenna noise floor */
        uint8_t         pad[2];
        uint32_t        evm[3];         /* EVM data */
 };
index 64d0754..f5fdd5a 100644 (file)
@@ -129,6 +129,7 @@ struct ieee80211_qosframe_addr4 {
 #define        IEEE80211_FC0_SUBTYPE_REASSOC_RESP      0x30
 #define        IEEE80211_FC0_SUBTYPE_PROBE_REQ         0x40
 #define        IEEE80211_FC0_SUBTYPE_PROBE_RESP        0x50
+#define        IEEE80211_FC0_SUBTYPE_TIMING_ADV        0x60
 #define        IEEE80211_FC0_SUBTYPE_BEACON            0x80
 #define        IEEE80211_FC0_SUBTYPE_ATIM              0x90
 #define        IEEE80211_FC0_SUBTYPE_DISASSOC          0xa0
@@ -137,6 +138,7 @@ struct ieee80211_qosframe_addr4 {
 #define        IEEE80211_FC0_SUBTYPE_ACTION            0xd0
 #define        IEEE80211_FC0_SUBTYPE_ACTION_NOACK      0xe0
 /* for TYPE_CTL */
+#define        IEEE80211_FC0_SUBTYPE_CONTROL_WRAP      0x70
 #define        IEEE80211_FC0_SUBTYPE_BAR               0x80
 #define        IEEE80211_FC0_SUBTYPE_BA                0x90
 #define        IEEE80211_FC0_SUBTYPE_PS_POLL           0xa0
@@ -314,6 +316,27 @@ struct ieee80211_wme_param {
        struct ieee80211_wme_acparams   params_acParams[WME_NUM_AC];
 } __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
  */
@@ -344,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*/
@@ -693,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.
  */
@@ -706,6 +875,9 @@ enum {
        IEEE80211_ELEMID_TIM            = 5,
        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,
@@ -723,7 +895,19 @@ enum {
        IEEE80211_ELEMID_QOS            = 46,
        IEEE80211_ELEMID_RSN            = 48,
        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 */
@@ -747,6 +931,7 @@ enum {
        IEEE80211_ELEMID_MESHGANN       = 125,
        IEEE80211_ELEMID_MESHRANN       = 126,
        /* 127 Extended Capabilities */
+       IEEE80211_ELEMID_EXTCAP         = 127,
        /* 128-129 reserved */
        IEEE80211_ELEMID_MESHPREQ       = 130,
        IEEE80211_ELEMID_MESHPREP       = 131,
@@ -755,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 {
@@ -781,6 +971,78 @@ struct ieee80211_country_ie {
 #define        IEEE80211_COUNTRY_MAX_SIZE \
        (sizeof(struct ieee80211_country_ie) + 3*(IEEE80211_COUNTRY_MAX_BANDS-1))
 
+struct ieee80211_bss_load_ie {
+       uint8_t         ie;
+       uint8_t         len;
+       uint16_t        sta_count;      /* station count */
+       uint8_t         chan_load;      /* channel utilization */
+       uint8_t         aac;            /* available admission capacity */
+} __packed;
+
+struct ieee80211_ap_chan_report_ie {
+       uint8_t         ie;
+       uint8_t         len;
+       uint8_t         i_class; /* operating class */
+       /* Annex E, E.1 Country information and operating classes */
+       uint8_t         chan_list[0];
+} __packed;
+
+#define IEEE80211_EXTCAP_CMS                   (1ULL <<  0) /* 20/40 BSS coexistence management support */
+#define IEEE80211_EXTCAP_RSVD_1                        (1ULL <<  1)
+#define IEEE80211_EXTCAP_ECS                   (1ULL <<  2) /* extended channel switching */
+#define IEEE80211_EXTCAP_RSVD_3                        (1ULL <<  3)
+#define IEEE80211_EXTCAP_PSMP_CAP              (1ULL <<  4) /* PSMP capability */
+#define IEEE80211_EXTCAP_RSVD_5                        (1ULL <<  5)
+#define IEEE80211_EXTCAP_S_PSMP_SUPP           (1ULL <<  6)
+#define IEEE80211_EXTCAP_EVENT                 (1ULL <<  7)
+#define IEEE80211_EXTCAP_DIAGNOSTICS           (1ULL <<  8)
+#define IEEE80211_EXTCAP_MCAST_DIAG            (1ULL <<  9)
+#define IEEE80211_EXTCAP_LOC_TRACKING          (1ULL << 10)
+#define IEEE80211_EXTCAP_FMS                   (1ULL << 11)
+#define IEEE80211_EXTCAP_PROXY_ARP             (1ULL << 12)
+#define IEEE80211_EXTCAP_CIR                   (1ULL << 13) /* collocated interference reporting */
+#define IEEE80211_EXTCAP_CIVIC_LOC             (1ULL << 14)
+#define IEEE80211_EXTCAP_GEOSPATIAL_LOC                (1ULL << 15)
+#define IEEE80211_EXTCAP_TFS                   (1ULL << 16)
+#define IEEE80211_EXTCAP_WNM_SLEEPMODE         (1ULL << 17)
+#define IEEE80211_EXTCAP_TIM_BROADCAST         (1ULL << 18)
+#define IEEE80211_EXTCAP_BSS_TRANSITION                (1ULL << 19)
+#define IEEE80211_EXTCAP_QOS_TRAF_CAP          (1ULL << 20)
+#define IEEE80211_EXTCAP_AC_STA_COUNT          (1ULL << 21)
+#define IEEE80211_EXTCAP_M_BSSID               (1ULL << 22) /* multiple BSSID field */
+#define IEEE80211_EXTCAP_TIMING_MEAS           (1ULL << 23)
+#define IEEE80211_EXTCAP_CHAN_USAGE            (1ULL << 24)
+#define IEEE80211_EXTCAP_SSID_LIST             (1ULL << 25)
+#define IEEE80211_EXTCAP_DMS                   (1ULL << 26)
+#define IEEE80211_EXTCAP_UTC_TSF_OFFSET                (1ULL << 27)
+#define IEEE80211_EXTCAP_TLDS_BUF_STA_SUPP     (1ULL << 28) /* TDLS peer U-APSP buffer STA support */
+#define IEEE80211_EXTCAP_TLDS_PPSM_SUPP                (1ULL << 29) /* TDLS peer PSM support */
+#define IEEE80211_EXTCAP_TLDS_CH_SW            (1ULL << 30) /* TDLS channel switching */
+#define IEEE80211_EXTCAP_INTERWORKING          (1ULL << 31)
+#define IEEE80211_EXTCAP_QOSMAP                        (1ULL << 32)
+#define IEEE80211_EXTCAP_EBR                   (1ULL << 33)
+#define IEEE80211_EXTCAP_SSPN_IF               (1ULL << 34)
+#define IEEE80211_EXTCAP_RSVD_35               (1ULL << 35)
+#define IEEE80211_EXTCAP_MSGCF_CAP             (1ULL << 36)
+#define IEEE80211_EXTCAP_TLDS_SUPP             (1ULL << 37)
+#define IEEE80211_EXTCAP_TLDS_PROHIB           (1ULL << 38)
+#define IEEE80211_EXTCAP_TLDS_CH_SW_PROHIB     (1ULL << 39) /* TDLS channel switching prohibited */
+#define IEEE80211_EXTCAP_RUF                   (1ULL << 40) /* reject unadmitted frame */
+/* service interval granularity */
+#define IEEE80211_EXTCAP_SIG \
+                               ((1ULL << 41) | (1ULL << 42) | (1ULL << 43))
+#define IEEE80211_EXTCAP_ID_LOC                        (1ULL << 44)
+#define IEEE80211_EXTCAP_U_APSD_COEX           (1ULL << 45)
+#define IEEE80211_EXTCAP_WNM_NOTIFICATION      (1ULL << 46)
+#define IEEE80211_EXTCAP_RSVD_47               (1ULL << 47)
+#define IEEE80211_EXTCAP_SSID                  (1ULL << 48) /* UTF-8 SSID */
+/* bits 49-n are reserved */
+
+struct ieee80211_extcap_ie {
+       uint8_t         ie;
+       uint8_t         len;
+} __packed;
+
 /*
  * 802.11h Quiet Time Element.
  */
@@ -815,6 +1077,7 @@ struct ieee80211_csa_ie {
 /* rate set entries are in .5 Mb/s units, and potentially marked as basic */
 #define        IEEE80211_RATE_BASIC            0x80
 #define        IEEE80211_RATE_VAL              0x7f
+#define        IEEE80211_RV(v)                 ((v) & IEEE80211_RATE_VAL)
 
 /* ERP information element flags */
 #define        IEEE80211_ERP_NON_ERP_PRESENT   0x01
index d7ac436..cca166d 100644 (file)
@@ -178,8 +178,8 @@ struct ieee80211_cipher {
        void*   (*ic_attach)(struct ieee80211vap *, struct ieee80211_key *);
        void    (*ic_detach)(struct ieee80211_key *);
        int     (*ic_setkey)(struct ieee80211_key *);
-       int     (*ic_encap)(struct ieee80211_key *, struct mbuf *,
-                       uint8_t keyid);
+       void    (*ic_setiv)(struct ieee80211_key *, uint8_t *);
+       int     (*ic_encap)(struct ieee80211_key *, struct mbuf *);
        int     (*ic_decap)(struct ieee80211_key *, struct mbuf *, int);
        int     (*ic_enmic)(struct ieee80211_key *, struct mbuf *, int);
        int     (*ic_demic)(struct ieee80211_key *, struct mbuf *, int);
@@ -193,6 +193,10 @@ void       ieee80211_crypto_register(const struct ieee80211_cipher *);
 void   ieee80211_crypto_unregister(const struct ieee80211_cipher *);
 int    ieee80211_crypto_available(u_int cipher);
 
+uint8_t        ieee80211_crypto_get_keyid(struct ieee80211vap *vap,
+               struct ieee80211_key *k);
+struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *,
+               struct mbuf *);
 struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
                struct mbuf *);
 struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
index 6e84b66..de31f6d 100644 (file)
@@ -126,13 +126,15 @@ uint16_t ieee80211_txtime(struct ieee80211_node *, u_int, uint8_t, uint32_t);
        (((_ifp)->if_flags & IFF_UP) && \
         ((_ifp)->if_flags & IFF_RUNNING))
 
+/* XXX TODO: cap these at 1, as hz may not be 1000 */
 #define        msecs_to_ticks(ms)      (((ms)*hz)/1000)
 #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);
 
@@ -141,7 +143,7 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
 #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            M_PROTO6                /* fast frame */
+#define        M_FF            M_PROTO6                /* fast frame / A-MSDU */
 #define        M_TXCB          M_PROTO7                /* do tx complete callback */
 #define        M_AMPDU_MPDU    M_PROTO8                /* ok for A-MPDU aggregation */
 #define        M_80211_TX \
@@ -211,6 +213,8 @@ void        ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int);
 
 void   get_random_bytes(void *, size_t);
 
+#define        NET80211_TAG_RECV_PARAMS        2
+
 struct ieee80211com;
 
 void   ieee80211_sysctl_attach(struct ieee80211com *);
@@ -507,6 +511,43 @@ int        ieee80211_add_xmit_params(struct mbuf *m,
            const struct ieee80211_bpf_params *);
 int    ieee80211_get_xmit_params(struct mbuf *m,
            struct ieee80211_bpf_params *);
+
+#define        IEEE80211_MAX_CHAINS            3
+#define        IEEE80211_MAX_EVM_PILOTS        6
+
+#define        IEEE80211_R_NF          0x0000001       /* global NF value valid */
+#define        IEEE80211_R_RSSI        0x0000002       /* global RSSI value valid */
+#define        IEEE80211_R_C_CHAIN     0x0000004       /* RX chain count valid */
+#define        IEEE80211_R_C_NF        0x0000008       /* per-chain NF value valid */
+#define        IEEE80211_R_C_RSSI      0x0000010       /* per-chain RSSI value valid */
+#define        IEEE80211_R_C_EVM       0x0000020       /* per-chain EVM valid */
+#define        IEEE80211_R_C_HT40      0x0000040       /* RX'ed packet is 40mhz, pilots 4,5 valid */
+#define        IEEE80211_R_FREQ        0x0000080       /* Freq value populated, MHz */
+#define        IEEE80211_R_IEEE        0x0000100       /* IEEE value populated */
+#define        IEEE80211_R_BAND        0x0000200       /* Frequency band populated */
+
+struct ieee80211_rx_stats {
+       uint32_t r_flags;               /* IEEE80211_R_* flags */
+       uint8_t c_chain;                /* number of RX chains involved */
+       int16_t c_nf_ctl[IEEE80211_MAX_CHAINS]; /* per-chain NF */
+       int16_t c_nf_ext[IEEE80211_MAX_CHAINS]; /* per-chain NF */
+       int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS];       /* per-chain RSSI */
+       int16_t c_rssi_ext[IEEE80211_MAX_CHAINS];       /* per-chain RSSI */
+       uint8_t nf;                     /* global NF */
+       uint8_t rssi;                   /* global RSSI */
+       uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS];
+                                       /* per-chain, per-pilot EVM values */
+       uint16_t c_freq;
+       uint8_t c_ieee;
+};
+
+struct ieee80211_rx_params {
+       struct ieee80211_rx_stats params;
+};
+int    ieee80211_add_rx_params(struct mbuf *m,
+           const struct ieee80211_rx_stats *rxs);
+int    ieee80211_get_rx_params(struct mbuf *m,
+           struct ieee80211_rx_stats *rxs);
 #endif /* _KERNEL */
 
 /*
@@ -583,6 +624,8 @@ typedef struct lock ieee80211_rt_lock_t;
 
 #define IEEE80211_LOCK_ASSERT(ic)              \
                                KKASSERT(lockstatus(&(ic)->ic_comlock, curthread) == LK_EXCLUSIVE)
+#define IEEE80211_UNLOCK_ASSERT(ic)            \
+                               KKASSERT(lockstatus(&(ic)->ic_comlock, curthread) != LK_EXCLUSIVE)
 #define IEEE80211_NODE_LOCK_ASSERT(nt)         \
                                KKASSERT(lockstatus(&(nt)->nt_nodelock, curthread) == LK_EXCLUSIVE)
 #define IEEE80211_NODE_ITERATE_LOCK_ASSERT(nt)         \
@@ -630,4 +673,19 @@ typedef struct lock        ieee80211_rt_lock_t;
 #define callout_schedule_dfly(callo, timo, func, args) \
                                callout_reset(callo, timo, func, args)
 
+/*
+ * if_inc macros
+ */
+#define ifd_IFCOUNTER_IERRORS  ifd_ierrors
+#define ifd_IFCOUNTER_IPACKETS ifd_ipackets
+#define ifd_IFCOUNTER_IBYTES   ifd_ibytes
+#define ifd_IFCOUNTER_OERRORS  ifd_oerrors
+#define ifd_IFCOUNTER_OPACKETS ifd_opackets
+#define ifd_IFCOUNTER_OMCASTS  ifd_omcasts
+#define ifd_IFCOUNTER_OBYTES   ifd_obytes
+
+#define if_inc_counter         IFNET_STAT_INC
+
+#define IEEE80211_FREE(ptr, type)      kfree((ptr), (type))
+
 #endif /* _NET80211_IEEE80211_DRAGONFLY_H_ */
index 3bda5fe..c046411 100644 (file)
@@ -65,6 +65,10 @@ struct ieee80211_tx_ampdu {
 #define        IEEE80211_AMPDU_RUNNING(tap) \
        (((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0)
 
+/* return non-zero if AMPDU tx for the TID was NACKed */
+#define        IEEE80211_AMPDU_NACKED(tap)\
+       (!! ((tap)->txa_flags & IEEE80211_AGGR_NAK))
+
 /* return non-zero if AMPDU tx for the TID is running or started */
 #define        IEEE80211_AMPDU_REQUESTED(tap) \
        (((tap)->txa_flags & \
@@ -83,9 +87,20 @@ struct ieee80211_tx_ampdu {
  * available and more streams are requested than available.
  */
 
+static __inline void
+ieee80211_txampdu_init_pps(struct ieee80211_tx_ampdu *tap)
+{
+       /*
+        * Reset packet estimate.
+        */
+       tap->txa_lastsample = ticks;
+       tap->txa_avgpps = 0;
+}
+
 static __inline void
 ieee80211_txampdu_update_pps(struct ieee80211_tx_ampdu *tap)
 {
+
        /* NB: scale factor of 2 was picked heuristically */
        tap->txa_avgpps = ((tap->txa_avgpps << 2) -
             tap->txa_avgpps + tap->txa_pkts) >> 2;
@@ -97,6 +112,7 @@ ieee80211_txampdu_update_pps(struct ieee80211_tx_ampdu *tap)
 static __inline void
 ieee80211_txampdu_count_packet(struct ieee80211_tx_ampdu *tap)
 {
+
        /* XXX bound loop/do more crude estimate? */
        while (ticks - tap->txa_lastsample >= hz) {
                ieee80211_txampdu_update_pps(tap);
@@ -200,4 +216,10 @@ uint8_t    *ieee80211_add_htinfo_vendor(uint8_t *, struct ieee80211_node *);
 struct ieee80211_beacon_offsets;
 void   ieee80211_ht_update_beacon(struct ieee80211vap *,
                struct ieee80211_beacon_offsets *);
+int    ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid,
+           int seq, int baw);
+int    ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid);
+int    ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni,
+           int tid, int status);
+
 #endif /* _NET80211_IEEE80211_HT_H_ */
index f3b304b..eea667d 100644 (file)
@@ -62,8 +62,7 @@ void  ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag,
            memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
                if (ieee80211_msg_input(vap))                           \
                        ieee80211_ssid_mismatch(vap,                    \
-                           ieee80211_mgt_subtype_name[subtype >>       \
-                               IEEE80211_FC0_SUBTYPE_SHIFT],           \
+                           ieee80211_mgt_subtype_name(subtype),        \
                                wh->i_addr2, _ssid);                    \
                vap->iv_stats.is_rx_ssidmismatch++;                     \
                _action;                                                \
@@ -80,70 +79,58 @@ void        ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag,
 } while (0)
 #endif /* !IEEE80211_DEBUG */
 
-/* unalligned little endian access */     
-#define LE_READ_2(p)                                   \
-       ((uint16_t)                                     \
-        ((((const uint8_t *)(p))[0]      ) |           \
-         (((const uint8_t *)(p))[1] <<  8)))
-#define LE_READ_4(p)                                   \
-       ((uint32_t)                                     \
-        ((((const uint8_t *)(p))[0]      ) |           \
-         (((const uint8_t *)(p))[1] <<  8) |           \
-         (((const uint8_t *)(p))[2] << 16) |           \
-         (((const uint8_t *)(p))[3] << 24)))
+#include <sys/endian.h>                /* For le16toh() / le32dec() */
 
 static __inline int
 iswpaoui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
 }
 
 static __inline int
 iswmeoui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
 }
 
 static __inline int
 iswmeparam(const uint8_t *frm)
 {
-       return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
+       return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
                frm[6] == WME_PARAM_OUI_SUBTYPE;
 }
 
 static __inline int
 iswmeinfo(const uint8_t *frm)
 {
-       return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
+       return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
                frm[6] == WME_INFO_OUI_SUBTYPE;
 }
 
 static __inline int
 isatherosoui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
 }
 
 static __inline int
 istdmaoui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
 }
 
 static __inline int
 ishtcapoui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI);
 }
 
 static __inline int
 ishtinfooui(const uint8_t *frm)
 {
-       return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
+       return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
 }
 
-#include <sys/endian.h>                /* For le16toh() */
-
 /*
  * Check the current frame sequence number against the current TID
  * state and return whether it's in sequence or should be dropped.
@@ -164,12 +151,14 @@ ishtinfooui(const uint8_t *frm)
  * but a retransmit since the initial packet didn't make it.
  */
 static __inline int
-ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
+ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh,
+    uint8_t *bssid)
 {
 #define        SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
 #define        SEQ_EQ(a,b)     ((int)((a)-(b)) == 0)
 #define        SEQNO(a)        ((a) >> IEEE80211_SEQ_SEQ_SHIFT)
 #define        FRAGNO(a)       ((a) & IEEE80211_SEQ_FRAG_MASK)
+       struct ieee80211vap *vap = ni->ni_vap;
        uint16_t rxseq;
        uint8_t type, subtype;
        uint8_t tid;
@@ -198,7 +187,7 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
                /* HT nodes currently doing RX AMPDU are always valid */
                if ((ni->ni_flags & IEEE80211_NODE_HT) &&
                    (rap->rxa_flags & IEEE80211_AGGR_RUNNING))
-                       return 1;
+                       goto ok;
        }
 
        /*
@@ -216,7 +205,7 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
                 */
                if (SEQ_EQ(rxseq, ni->ni_rxseqs[tid]) &&
                    (wh->i_fc[1] & IEEE80211_FC1_RETRY))
-                       return 0;
+                       goto fail;
                /*
                 * Treat any subsequent frame as fine if the last seen frame
                 * is 4095 and it's not a retransmit for the same sequence
@@ -224,7 +213,7 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
                 * fragments w/ sequence number 4095. It shouldn't be seen
                 * in practice, but see the comment above for further info.
                 */
-               return 1;
+               goto ok;
        }
 
        /*
@@ -233,9 +222,23 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
         */
        if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
            SEQ_LEQ(rxseq, ni->ni_rxseqs[tid]))
-               return 0;
+               goto fail;
+
+ok:
+       ni->ni_rxseqs[tid] = rxseq;
 
        return 1;
+
+fail:
+       /* duplicate, discard */
+       IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, bssid, "duplicate",
+           "seqno <%u,%u> fragno <%u,%u> tid %u",
+            SEQNO(rxseq),  SEQNO(ni->ni_rxseqs[tid]),
+           FRAGNO(rxseq), FRAGNO(ni->ni_rxseqs[tid]), tid);
+       vap->iv_stats.is_rx_dup++;
+       IEEE80211_NODE_STAT(ni, rx_dup);
+
+       return 0;
 #undef SEQ_LEQ
 #undef SEQ_EQ
 #undef SEQNO
index fd645d4..a305571 100644 (file)
@@ -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];
 };
 
 /*
@@ -699,6 +702,7 @@ struct ieee80211req {
 #define        IEEE80211_IOC_RIFS              111     /* RIFS config (on, off) */
 #define        IEEE80211_IOC_GREENFIELD        112     /* Greenfield (on, off) */
 #define        IEEE80211_IOC_STBC              113     /* STBC Tx/RX (on, off) */
+#define        IEEE80211_IOC_LDPC              114     /* LDPC Tx/RX (on, off) */
 
 #define        IEEE80211_IOC_MESH_ID           170     /* mesh identifier */
 #define        IEEE80211_IOC_MESH_AP           171     /* accepting peerings */
index 13eb22f..0faaf35 100644 (file)
@@ -219,6 +219,9 @@ struct ieee80211_node {
        struct ieee80211_tx_ampdu ni_tx_ampdu[WME_NUM_TID];
        struct ieee80211_rx_ampdu ni_rx_ampdu[WME_NUM_TID];
 
+       /* fast-frames state */
+       struct mbuf *           ni_tx_superg[WME_NUM_TID];
+
        /* others */
        short                   ni_inact;       /* inactivity mark count */
        short                   ni_inact_reload;/* inactivity reload value */
@@ -327,6 +330,7 @@ void        ieee80211_setupcurchan(struct ieee80211com *,
            struct ieee80211_channel *);
 void   ieee80211_setcurchan(struct ieee80211com *, struct ieee80211_channel *);
 void   ieee80211_update_chw(struct ieee80211com *);
+int    ieee80211_ibss_merge_check(struct ieee80211_node *);
 int    ieee80211_ibss_merge(struct ieee80211_node *);
 struct ieee80211_scan_entry;
 int    ieee80211_sta_join(struct ieee80211vap *, struct ieee80211_channel *,
index bf39cdd..7970388 100644 (file)
 #define IEEE80211_DUR_SHSLOT   9       /* ERP short slottime */
 #define IEEE80211_DUR_OFDM_SLOT        9       /* OFDM slottime */
 
+#define IEEE80211_GET_SLOTTIME(ic) \
+       ((ic->ic_flags & IEEE80211_F_SHSLOT) ? \
+           IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
+
 /*
  * DIFS (microseconds).
  */
@@ -190,6 +194,14 @@ uint8_t            ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype);
  */
 uint8_t                ieee80211_rate2plcp(int, enum ieee80211_phytype);
 
+/*
+ * 802.11n rate manipulation.
+ */
+
+#define        IEEE80211_HT_RC_2_MCS(_rc)      ((_rc) & 0x1f)
+#define        IEEE80211_HT_RC_2_STREAMS(_rc)  ((((_rc) & 0x78) >> 3) + 1)
+#define        IEEE80211_IS_HT_RATE(_rc)               ( (_rc) & IEEE80211_RATE_MCS)
+
 uint32_t       ieee80211_compute_duration_ht(uint32_t frameLen,
                        uint16_t rate, int streams, int isht40,
                        int isShortGI);
index 9ef6217..8c081ad 100644 (file)
@@ -47,46 +47,43 @@ enum ieee80211_state {
 #define        IEEE80211_SEND_MGMT(_ni,_type,_arg) \
        ((*(_ni)->ni_ic->ic_send_mgmt)(_ni, _type, _arg))
 
-extern const char *ieee80211_mgt_subtype_name[];
+extern const char *mgt_subtype_name[];
+extern const char *ctl_subtype_name[];
 extern const char *ieee80211_phymode_name[IEEE80211_MODE_MAX];
 extern const int ieee80211_opcap[IEEE80211_OPMODE_MAX];
 
+static __inline const char *
+ieee80211_mgt_subtype_name(uint8_t subtype)
+{
+       return mgt_subtype_name[(subtype & IEEE80211_FC0_SUBTYPE_MASK) >>
+                  IEEE80211_FC0_SUBTYPE_SHIFT];
+}
+
+static __inline const char *
+ieee80211_ctl_subtype_name(uint8_t subtype)
+{
+       return ctl_subtype_name[(subtype & IEEE80211_FC0_SUBTYPE_MASK) >>
+                  IEEE80211_FC0_SUBTYPE_SHIFT];
+}
+
+const char *ieee80211_reason_to_string(uint16_t);
+
 void   ieee80211_proto_attach(struct ieee80211com *);
 void   ieee80211_proto_detach(struct ieee80211com *);
 void   ieee80211_proto_vattach(struct ieee80211vap *);
 void   ieee80211_proto_vdetach(struct ieee80211vap *);
 
-void   ieee80211_syncifflag_locked(struct ieee80211com *, int flag);
+#if defined(__DragonFly__)
+void   ieee80211_promisc(struct ieee80211vap *, int);
+void   ieee80211_allmulti(struct ieee80211vap *, int);
+#else
+void   ieee80211_promisc(struct ieee80211vap *, bool);
+void   ieee80211_allmulti(struct ieee80211vap *, bool);
+#endif
 void   ieee80211_syncflag(struct ieee80211vap *, int flag);
 void   ieee80211_syncflag_ht(struct ieee80211vap *, int flag);
 void   ieee80211_syncflag_ext(struct ieee80211vap *, int flag);
 
-#define        IEEE80211_R_NF          0x0000001       /* global NF value valid */
-#define        IEEE80211_R_RSSI        0x0000002       /* global RSSI value valid */
-#define        IEEE80211_R_C_CHAIN     0x0000004       /* RX chain count valid */
-#define        IEEE80211_R_C_NF        0x0000008       /* per-chain NF value valid */
-#define        IEEE80211_R_C_RSSI      0x0000010       /* per-chain RSSI value valid */
-#define        IEEE80211_R_C_EVM       0x0000020       /* per-chain EVM valid */
-#define        IEEE80211_R_C_HT40      0x0000040       /* RX'ed packet is 40mhz, pilots 4,5 valid */
-#define        IEEE80211_R_FREQ        0x0000080       /* Freq value populated, MHz */
-#define        IEEE80211_R_IEEE        0x0000100       /* IEEE value populated */
-#define        IEEE80211_R_BAND        0x0000200       /* Frequency band populated */
-
-struct ieee80211_rx_stats {
-       uint32_t r_flags;               /* IEEE80211_R_* flags */
-       uint8_t c_chain;                /* number of RX chains involved */
-       int16_t c_nf_ctl[IEEE80211_MAX_CHAINS]; /* per-chain NF */
-       int16_t c_nf_ext[IEEE80211_MAX_CHAINS]; /* per-chain NF */
-       int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS];       /* per-chain RSSI */
-       int16_t c_rssi_ext[IEEE80211_MAX_CHAINS];       /* per-chain RSSI */
-       uint8_t nf;                     /* global NF */
-       uint8_t rssi;                   /* global RSSI */
-       uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS];
-                                       /* per-chain, per-pilot EVM values */
-       uint16_t c_freq;
-       uint8_t c_ieee;
-};
-
 #if defined(__DragonFly__)
 struct route;
 #endif
@@ -119,7 +116,9 @@ int ieee80211_raw_output(struct ieee80211vap *, struct ieee80211_node *,
 void   ieee80211_send_setup(struct ieee80211_node *, struct mbuf *, int, int,
         const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN],
         const uint8_t [IEEE80211_ADDR_LEN]);
+#if defined(__DragonFly__)
 void   ieee80211_vap_start(struct ifnet *ifp, struct ifaltq_subque *ifsq);
+#endif
 int    ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m);
 void   ieee80211_vap_qflush(struct ifnet *ifp);
 int    ieee80211_send_nulldata(struct ieee80211_node *);
@@ -128,6 +127,7 @@ struct mbuf *ieee80211_mbuf_adjust(struct ieee80211vap *, int,
                struct ieee80211_key *, struct mbuf *);
 struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *,
                struct mbuf *);
+void   ieee80211_free_mbuf(struct mbuf *);
 int    ieee80211_send_mgmt(struct ieee80211_node *, int, int);
 struct ieee80211_appie;
 int    ieee80211_send_probereq(struct ieee80211_node *ni,
@@ -159,12 +159,14 @@ struct mbuf *ieee80211_alloc_cts(struct ieee80211com *,
 
 uint8_t *ieee80211_add_rates(uint8_t *, const struct ieee80211_rateset *);
 uint8_t *ieee80211_add_xrates(uint8_t *, const struct ieee80211_rateset *);
-uint8_t *ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len);
+uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
 uint8_t *ieee80211_add_wpa(uint8_t *, const struct ieee80211vap *);
 uint8_t *ieee80211_add_rsn(uint8_t *, const struct ieee80211vap *);
 uint8_t *ieee80211_add_qos(uint8_t *, const struct ieee80211_node *);
 uint16_t ieee80211_getcapinfo(struct ieee80211vap *,
                struct ieee80211_channel *);
+struct ieee80211_wme_state;
+uint8_t * ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme);
 
 void   ieee80211_reset_erp(struct ieee80211com *);
 void   ieee80211_set_shortslottime(struct ieee80211com *, int onoff);
@@ -291,10 +293,10 @@ struct chanAccParams {
 
 struct ieee80211_wme_state {
        u_int   wme_flags;
-#define        WME_F_AGGRMODE  0x00000001      /* STATUS: WME agressive mode */
+#define        WME_F_AGGRMODE  0x00000001      /* STATUS: WME aggressive mode */
        u_int   wme_hipri_traffic;      /* VI/VO frames in beacon interval */
-       u_int   wme_hipri_switch_thresh;/* agressive mode switch thresh */
-       u_int   wme_hipri_switch_hysteresis;/* agressive mode switch hysteresis */
+       u_int   wme_hipri_switch_thresh;/* aggressive mode switch thresh */
+       u_int   wme_hipri_switch_hysteresis;/* aggressive mode switch hysteresis */
 
        struct wmeParams wme_params[4];         /* from assoc resp for each AC*/
        struct chanAccParams wme_wmeChanParams; /* WME params applied to self */
@@ -339,6 +341,7 @@ void        ieee80211_stop(struct ieee80211vap *);
 void   ieee80211_stop_all(struct ieee80211com *);
 void   ieee80211_suspend_all(struct ieee80211com *);
 void   ieee80211_resume_all(struct ieee80211com *);
+void   ieee80211_restart_all(struct ieee80211com *);
 void   ieee80211_dturbo_switch(struct ieee80211vap *, int newflags);
 void   ieee80211_swbmiss(void *arg);
 void   ieee80211_beacon_miss(struct ieee80211com *);
@@ -379,8 +382,7 @@ struct ieee80211_beacon_offsets {
        uint8_t         *bo_meshconf;   /* start of MESHCONF element */
        uint8_t         *bo_spare[3];
 };
-struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *,
-               struct ieee80211_beacon_offsets *);
+struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *);
 
 /*
  * Beacon frame updates are signaled through calls to iv_update_beacon
@@ -408,7 +410,7 @@ enum {
        IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */
 };
 int    ieee80211_beacon_update(struct ieee80211_node *,
-               struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
+               struct mbuf *, int mcast);
 
 void   ieee80211_csa_startswitch(struct ieee80211com *,
                struct ieee80211_channel *, int mode, int count);
index da43084..82601c1 100644 (file)
@@ -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);
+}
index 4df1386..ced3c9b 100644 (file)
@@ -82,6 +82,27 @@ int  ieee80211_parse_athparams(struct ieee80211_node *, uint8_t *,
 void   ieee80211_ff_node_init(struct ieee80211_node *);
 void   ieee80211_ff_node_cleanup(struct ieee80211_node *);
 
+static inline int
+ieee80211_amsdu_tx_ok(struct ieee80211_node *ni)
+{
+
+       /* First: software A-MSDU transmit? */
+       if ((ni->ni_ic->ic_caps & IEEE80211_C_SWAMSDUTX) == 0)
+               return (0);
+
+       /* Next: does the VAP have AMSDU TX enabled? */
+       if ((ni->ni_vap->iv_flags_ht & IEEE80211_FHT_AMSDU_TX) == 0)
+               return (0);
+
+       /* Next: 11n node? (assumed that A-MSDU TX to HT nodes is ok */
+       if ((ni->ni_flags & IEEE80211_NODE_HT) == 0)
+               return (0);
+
+       /* ok, we can at least /do/ AMSDU to this node */
+       return (1);
+}
+
+struct mbuf * ieee80211_amsdu_check(struct ieee80211_node *ni, struct mbuf *m);
 struct mbuf *ieee80211_ff_check(struct ieee80211_node *, struct mbuf *);
 void   ieee80211_ff_age(struct ieee80211com *, struct ieee80211_stageq *,
             int quanta);
@@ -122,6 +143,8 @@ ieee80211_ff_age_all(struct ieee80211com *ic, int quanta)
 
 struct mbuf *ieee80211_ff_encap(struct ieee80211vap *, struct mbuf *,
            int, struct ieee80211_key *);
+struct mbuf * ieee80211_amsdu_encap(struct ieee80211vap *vap, struct mbuf *m1,
+           int hdrspace, struct ieee80211_key *key);
 
 struct mbuf *ieee80211_ff_decap(struct ieee80211_node *, struct mbuf *);
 
index 821c667..37cc7d7 100644 (file)
@@ -86,7 +86,8 @@
 
 #define        IEEE80211_MS_TO_TU(x)   (((x) * 1000) / 1024)
 #define        IEEE80211_TU_TO_MS(x)   (((x) * 1024) / 1000)
-#define        IEEE80211_TU_TO_TICKS(x)(((x) * 1024 * hz) / (1000 * 1000))
+/* XXX TODO: cap this at 1, in case hz is not 1000 */
+#define        IEEE80211_TU_TO_TICKS(x)(((uint64_t)(x) * 1024 * hz) / (1000 * 1000))
 
 /*
  * 802.11 control state is split into a common portion that maps
@@ -118,16 +119,15 @@ struct ieee80211_superg;
 struct ieee80211_frame;
 
 struct ieee80211com {
-       struct ifnet            *ic_ifp;        /* associated device */
        void                    *ic_softc;      /* driver softc */
        const char              *ic_name;       /* usually device name */
        ieee80211_com_lock_t    ic_comlock;     /* state update lock */
        ieee80211_tx_lock_t     ic_txlock;      /* ic/vap TX lock */
+       LIST_ENTRY(ieee80211com)   ic_next;     /* on global list */
        TAILQ_HEAD(, ieee80211vap) ic_vaps;     /* list of vap instances */
        int                     ic_headroom;    /* driver tx headroom needs */
        enum ieee80211_phytype  ic_phytype;     /* XXX wrong for multi-mode */
        enum ieee80211_opmode   ic_opmode;      /* operation mode */
-       struct ifmedia          ic_media;       /* interface media config */
        struct callout          ic_inact;       /* inactivity processing */
        struct taskqueue        *ic_tq;         /* deferred state thread */
        struct task             ic_parent_task; /* deferred parent processing */
@@ -136,6 +136,16 @@ struct ieee80211com {
        struct task             ic_chan_task;   /* deferred channel change */
        struct task             ic_bmiss_task;  /* deferred beacon miss hndlr */
        struct task             ic_chw_task;    /* deferred HT CHW update */
+       struct task             ic_wme_task;    /* deferred WME update */
+       struct task             ic_restart_task; /* deferred device restart */
+
+#if defined(__DragonFly__)
+       uint64_t                ic_ierrors;     /* input errors */
+       uint64_t                ic_oerrors;     /* output errors */
+#else
+       counter_u64_t           ic_ierrors;     /* input errors */
+       counter_u64_t           ic_oerrors;     /* output errors */
+#endif
 
        uint32_t                ic_flags;       /* state flags */
        uint32_t                ic_flags_ext;   /* extended state flags */
@@ -145,11 +155,13 @@ struct ieee80211com {
        uint32_t                ic_htcaps;      /* HT capabilities */
        uint32_t                ic_htextcaps;   /* HT extended capabilities */
        uint32_t                ic_cryptocaps;  /* crypto capabilities */
-       uint8_t                 ic_modecaps[2]; /* set of mode capabilities */
+                                               /* set of mode capabilities */
+       uint8_t                 ic_modecaps[IEEE80211_MODE_BYTES];
        uint8_t                 ic_promisc;     /* vap's needing promisc mode */
        uint8_t                 ic_allmulti;    /* vap's needing all multicast*/
        uint8_t                 ic_nrunning;    /* vap's marked running */
        uint8_t                 ic_curmode;     /* current mode */
+       uint8_t                 ic_macaddr[IEEE80211_ADDR_LEN];
        uint16_t                ic_bintval;     /* beacon interval */
        uint16_t                ic_lintval;     /* listen interval */
        uint16_t                ic_holdover;    /* PM hold over duration */
@@ -240,6 +252,11 @@ struct ieee80211com {
                                    const uint8_t [IEEE80211_ADDR_LEN],
                                    const uint8_t [IEEE80211_ADDR_LEN]);
        void                    (*ic_vap_delete)(struct ieee80211vap *);
+       /* device specific ioctls */
+       int                     (*ic_ioctl)(struct ieee80211com *,
+                                   u_long, void *);
+       /* start/stop device */
+       void                    (*ic_parent)(struct ieee80211com *);
        /* operating mode attachment */
        ieee80211vap_attach     ic_vattach[IEEE80211_OPMODE_MAX];
        /* return hardware/radio capabilities */
@@ -253,6 +270,9 @@ struct ieee80211com {
        int                     (*ic_set_quiet)(struct ieee80211_node *,
                                    u_int8_t *quiet_elm);
 
+       /* regular transmit */
+       int                     (*ic_transmit)(struct ieee80211com *,
+                                   struct mbuf *);
        /* send/recv 802.11 management frame */
        int                     (*ic_send_mgmt)(struct ieee80211_node *,
                                     int, int);
@@ -350,14 +370,16 @@ struct ieee80211vap {
 
        TAILQ_ENTRY(ieee80211vap) iv_next;      /* list of vap instances */
        struct ieee80211com     *iv_ic;         /* back ptr to common state */
+       /* MAC address: ifp or ic */
+       uint8_t                 iv_myaddr[IEEE80211_ADDR_LEN];
        uint32_t                iv_debug;       /* debug msg flags */
        struct ieee80211_stats  iv_stats;       /* statistics */
 
-       uint8_t                 iv_myaddr[IEEE80211_ADDR_LEN];
        uint32_t                iv_flags;       /* state flags */
        uint32_t                iv_flags_ext;   /* extended state flags */
        uint32_t                iv_flags_ht;    /* HT state flags */
        uint32_t                iv_flags_ven;   /* vendor state flags */
+       uint32_t                iv_ifflags;     /* ifnet flags */
        uint32_t                iv_caps;        /* capabilities */
        uint32_t                iv_htcaps;      /* HT capabilities */
        uint32_t                iv_htextcaps;   /* HT extended capabilities */
@@ -407,6 +429,7 @@ struct ieee80211vap {
        int                     iv_amsdu_limit; /* A-MSDU tx limit (bytes) */
        u_int                   iv_ampdu_mintraffic[WME_NUM_AC];
 
+       struct ieee80211_beacon_offsets iv_bcn_off;
        uint32_t                *iv_aid_bitmap; /* association id map */
        uint16_t                iv_max_aid;
        uint16_t                iv_sta_assoc;   /* stations associated */
@@ -449,8 +472,7 @@ struct ieee80211vap {
        int                     (*iv_key_delete)(struct ieee80211vap *, 
                                    const struct ieee80211_key *);
        int                     (*iv_key_set)(struct ieee80211vap *,
-                                   const struct ieee80211_key *,
-                                   const uint8_t mac[IEEE80211_ADDR_LEN]);
+                                   const struct ieee80211_key *);
        void                    (*iv_key_update_begin)(struct ieee80211vap *);
        void                    (*iv_key_update_end)(struct ieee80211vap *);
 
@@ -639,6 +661,7 @@ MALLOC_DECLARE(M_80211_VAP);
 #define        IEEE80211_C_DFS         0x00020000      /* CAPABILITY: DFS/radar avail*/
 #define        IEEE80211_C_MBSS        0x00040000      /* CAPABILITY: MBSS available */
 #define        IEEE80211_C_SWSLEEP     0x00080000      /* CAPABILITY: do sleep here */
+#define        IEEE80211_C_SWAMSDUTX   0x00100000      /* CAPABILITY: software A-MSDU TX */
 /* 0x7c0000 available */
 #define        IEEE80211_C_WPA1        0x00800000      /* CAPABILITY: WPA1 avail */
 #define        IEEE80211_C_WPA2        0x01000000      /* CAPABILITY: WPA2 avail */
@@ -685,24 +708,24 @@ MALLOC_DECLARE(M_80211_VAP);
        "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
 
 int    ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
-void   ieee80211_ifattach(struct ieee80211com *,
-               const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+void   ieee80211_ifattach(struct ieee80211com *);
 void   ieee80211_ifdetach(struct ieee80211com *);
 int    ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
                const char name[IFNAMSIZ], int unit,
                enum ieee80211_opmode opmode, int flags,
-               const uint8_t bssid[IEEE80211_ADDR_LEN],
-               const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+               const uint8_t bssid[IEEE80211_ADDR_LEN]);
 int    ieee80211_vap_attach(struct ieee80211vap *,
-               ifm_change_cb_t, ifm_stat_cb_t);
+               ifm_change_cb_t, ifm_stat_cb_t,
+               const uint8_t macaddr[IEEE80211_ADDR_LEN]);
 void   ieee80211_vap_detach(struct ieee80211vap *);
 const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic,
                const struct ieee80211_channel *);
 void   ieee80211_announce(struct ieee80211com *);
 void   ieee80211_announce_channels(struct ieee80211com *);
 void   ieee80211_drain(struct ieee80211com *);
-void   ieee80211_media_init(struct ieee80211com *);
+void   ieee80211_chan_init(struct ieee80211com *);
 struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
+struct ieee80211com *ieee80211_find_com(const char *name);
 int    ieee80211_media_change(struct ifnet *);
 void   ieee80211_media_status(struct ifnet *, struct ifmediareq *);
 #if defined(__DragonFly__)
@@ -717,6 +740,14 @@ int        ieee80211_mhz2ieee(u_int, u_int);
 int    ieee80211_chan2ieee(struct ieee80211com *,
                const struct ieee80211_channel *);
 u_int  ieee80211_ieee2mhz(u_int, u_int);
+int    ieee80211_add_channel(struct ieee80211_channel[], int, int *,
+           uint8_t, uint16_t, int8_t, uint32_t, const uint8_t[]);
+int    ieee80211_add_channel_ht40(struct ieee80211_channel[], int, int *,
+           uint8_t, int8_t, uint32_t);
+int    ieee80211_add_channel_list_2ghz(struct ieee80211_channel[], int, int *,
+           const uint8_t[], int, const uint8_t[], int);
+int    ieee80211_add_channel_list_5ghz(struct ieee80211_channel[], int, int *,
+           const uint8_t[], int, const uint8_t[], int);
 struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *,
                int freq, int flags);
 struct ieee80211_channel *ieee80211_find_channel_byieee(struct ieee80211com *,
index 681be4d..01afc2d 100644 (file)
@@ -35,8 +35,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-
+#include <sys/malloc.h>
 #include <sys/socket.h>
+#include <sys/sbuf.h>
 
 #include <machine/stdarg.h>
 
@@ -56,12 +57,6 @@ __FBSDID("$FreeBSD$");
 
 #include <net/bpf.h>
 
-#define IEEE80211_NMBCLUSTERS_DEFMIN   32
-#define IEEE80211_NMBCLUSTERS_DEFAULT  128
-
-static int ieee80211_nmbclusters_default = IEEE80211_NMBCLUSTERS_DEFAULT;
-TUNABLE_INT("net.link.ieee80211.nmbclusters", &ieee80211_nmbclusters_default);
-
 const char *ieee80211_phymode_name[IEEE80211_MODE_MAX] = {
        [IEEE80211_MODE_AUTO]     = "auto",
        [IEEE80211_MODE_11A]      = "11a",
@@ -98,10 +93,12 @@ 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 *);
+#if defined(__DragonFly__)
+#else
+static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter);
+#endif
 
 MALLOC_DEFINE(M_80211_VAP, "80211vap", "802.11 vap state");
 
@@ -127,7 +124,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g =
  * all available channels as active, and pick
  * a default channel if not already specified.
  */
-static void
+void
 ieee80211_chan_init(struct ieee80211com *ic)
 {
 #define        DEFAULTRATES(m, def) do { \
@@ -233,58 +230,17 @@ ieee80211_chan_init(struct ieee80211com *ic)
 static void
 null_update_mcast(struct ieee80211com *ic)
 {
+
        ic_printf(ic, "need multicast update callback\n");
 }
 
 static void
 null_update_promisc(struct ieee80211com *ic)
 {
-       ic_printf(ic, "need promiscuous mode update callback\n");
-}
-
-static int
-null_transmit(struct ifnet *ifp, struct mbuf *m)
-{
-       m_freem(m);
-       IFNET_STAT_INC(ifp, oerrors, 1);
-       return EACCES;          /* XXX EIO/EPERM? */
-}
 
-#if defined(__DragonFly__)
-static int
-null_output(struct ifnet *ifp, struct mbuf *m,
-           struct sockaddr *dst, struct rtentry *ro)
-#else
-static int
-null_output(struct ifnet *ifp, struct mbuf *m,
-       const struct sockaddr *dst, struct route *ro)
-#endif
-{
-       if_printf(ifp, "discard raw packet\n");
-       return null_transmit(ifp, m);
-}
-
-#if defined(__DragonFly__)
-
-static void
-null_input(struct ifnet *ifp, struct mbuf *m,
-          const struct pktinfo *pi, int cpuid)
-{
-       if_printf(ifp, "if_input should not be called\n");
-       m_freem(m);
-}
-
-#else
-
-static void
-null_input(struct ifnet *ifp, struct mbuf *m)
-{
-       if_printf(ifp, "if_input should not be called\n");
-       m_freem(m);
+       ic_printf(ic, "need promiscuous mode update callback\n");
 }
 
-#endif
-
 static void
 null_update_chw(struct ieee80211com *ic)
 {
@@ -295,6 +251,7 @@ null_update_chw(struct ieee80211com *ic)
 int
 ic_printf(struct ieee80211com *ic, const char * fmt, ...)
 {
+#if defined(__DragonFly__)
        osdep_va_list ap;
        int retval;
 
@@ -302,22 +259,84 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...)
        osdep_va_start(ap, fmt);
        retval += kvprintf(fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+       int retval;
+
+       retval = printf("%s: ", ic->ic_name);
+       va_start(ap, fmt);
+       retval += vprintf(fmt, ap);
+       va_end(ap);
+#endif
        return (retval);
 }
 
+static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head);
+#if defined(__DragonFly__)
+static struct lock ic_list_lock =
+                       LOCK_INITIALIZER("80211list", 0, LK_CANRECURSE);
+#else
+static struct mtx ic_list_mtx;
+MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF);
+#endif
+
+static int
+sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS)
+{
+       struct ieee80211com *ic;
+       struct sbuf sb;
+       char *sp;
+       int error;
+
+#if defined(__DragonFly__)
+#else
+       error = sysctl_wire_old_buffer(req, 0);
+       if (error)
+               return (error);
+#endif
+       sbuf_new_for_sysctl(&sb, NULL, 8, req);
+#if defined(__DragonFly__)
+#else
+       sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
+#endif
+       sp = "";
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_EXCLUSIVE);
+#else
+       mtx_lock(&ic_list_mtx);
+#endif
+       LIST_FOREACH(ic, &ic_head, ic_next) {
+               sbuf_printf(&sb, "%s%s", sp, ic->ic_name);
+               sp = " ";
+       }
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_RELEASE);
+#else
+       mtx_unlock(&ic_list_mtx);
+#endif
+       error = sbuf_finish(&sb);
+       sbuf_delete(&sb);
+       return (error);
+}
+
+#if defined(__DragonFly__)
+SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
+       CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
+       sysctl_ieee80211coms, "A", "names of available 802.11 devices");
+#else
+SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
+       CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+       sysctl_ieee80211coms, "A", "names of available 802.11 devices");
+#endif
+
+
 /*
  * 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,
-       const uint8_t macaddr[IEEE80211_ADDR_LEN])
+ieee80211_ifattach(struct ieee80211com *ic)
 {
-       struct ifnet *ifp = ic->ic_ifp;
-       struct sockaddr_dl *sdl;
-       struct ifaddr *ifa;
-
-       KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
 
        IEEE80211_LOCK_INIT(ic, ic->ic_name);
        IEEE80211_TX_LOCK_INIT(ic, ic->ic_name);
@@ -332,13 +351,15 @@ ieee80211_ifattach(struct ieee80211com *ic,
 #else
        taskqueue_start_threads(&ic->ic_tq, 1, PI_NET, "%s net80211 taskq",
            ic->ic_name);
+       ic->ic_ierrors = counter_u64_alloc(M_WAITOK);
+       ic->ic_oerrors = counter_u64_alloc(M_WAITOK);
 #endif
        /*
         * Fill in 802.11 available channel set, mark all
         * available channels as active, and pick a default
         * channel if not already specified.
         */
-       ieee80211_media_init(ic);
+       ieee80211_chan_init(ic);
 
        ic->ic_update_mcast = null_update_mcast;
        ic->ic_update_promisc = null_update_promisc;
@@ -363,57 +384,17 @@ ieee80211_ifattach(struct ieee80211com *ic,
 
        ieee80211_sysctl_attach(ic);
 
-       ifp->if_addrlen = IEEE80211_ADDR_LEN;
-       ifp->if_hdrlen = 0;
-
-       /*
-        * If driver does not configure # of mbuf clusters/jclusters
-        * that could sit on the device queues for quite some time,
-        * we then assume:
-        * - The device queues only consume mbuf clusters.
-        * - No more than ieee80211_nmbclusters_default (by default
-        *   128) mbuf clusters will sit on the device queues for
-        *   quite some time.
-        */
-       if (ifp->if_nmbclusters <= 0 && ifp->if_nmbjclusters <= 0) {
-               if (ieee80211_nmbclusters_default <
-                   IEEE80211_NMBCLUSTERS_DEFMIN) {
-                       kprintf("ieee80211 nmbclusters %d -> %d\n",
-                           ieee80211_nmbclusters_default,
-                           IEEE80211_NMBCLUSTERS_DEFAULT);
-                       ieee80211_nmbclusters_default =
-                           IEEE80211_NMBCLUSTERS_DEFAULT;
-               }
-               ifp->if_nmbclusters = ieee80211_nmbclusters_default;
-       }
-
-       CURVNET_SET(vnet0);
-
-       /*
-        * This function must _not_ be serialized by the WLAN serializer,
-        * since it could dead-lock the domsg to netisrs in if_attach().
-        */
-       wlan_serialize_exit();
 #if defined(__DragonFly__)
-       if_attach(ifp, &wlan_global_serializer);
+       lockmgr(&ic_list_lock, LK_EXCLUSIVE);
 #else
-       if_attach(ifp);
+       mtx_lock(&ic_list_mtx);
+#endif
+       LIST_INSERT_HEAD(&ic_head, ic, ic_next);
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_RELEASE);
+#else
+       mtx_unlock(&ic_list_mtx);
 #endif
-       wlan_serialize_enter();
-
-       ifp->if_mtu = IEEE80211_MTU_MAX;
-       ifp->if_broadcastaddr = ieee80211broadcastaddr;
-       ifp->if_output = null_output;
-       ifp->if_input = null_input;     /* just in case */
-       ifp->if_resolvemulti = NULL;    /* NB: callers check */
-
-       ifa = TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa;
-       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), macaddr);
-
-       CURVNET_RESTORE();
 }
 
 /*
@@ -425,42 +406,32 @@ ieee80211_ifattach(struct ieee80211com *ic,
 void
 ieee80211_ifdetach(struct ieee80211com *ic)
 {
-       struct ifnet *ifp = ic->ic_ifp;
        struct ieee80211vap *vap;
 
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_EXCLUSIVE);
+#else
+       mtx_lock(&ic_list_mtx);
+#endif
+       LIST_REMOVE(ic, ic_next);
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_RELEASE);
+#else
+       mtx_unlock(&ic_list_mtx);
+#endif
+
+#if defined(__DragonFly__)
+       taskqueue_drain(ic->ic_tq, &ic->ic_restart_task);
+#else
+       taskqueue_drain(taskqueue_thread, &ic->ic_restart_task);
+#endif
+
        /*
         * The VAP is responsible for setting and clearing
         * the VIMAGE context.
         */
        while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL)
                ieee80211_vap_destroy(vap);
-
-       /*
-        * WLAN serializer must _not_ be held for if_detach(),
-        * since it could dead-lock the domsg to netisrs.
-        *
-        * XXX
-        * This function actually should _not_ be serialized
-        * by the WLAN serializer, however, all 802.11 device
-        * drivers serialize it ...
-        */
-       wlan_serialize_exit();
-
-       /*
-        * This detaches the main interface, but not the vaps.
-        * Each VAP may be in a separate VIMAGE.
-        *
-        * Detach the main interface _after_ all vaps are
-        * destroyed, since the main interface is referenced
-        * on vaps' detach path.
-        */
-       CURVNET_SET(ifp->if_vnet);
-       if_detach(ifp);
-       CURVNET_RESTORE();
-
-       /* Re-hold WLAN serializer */
-       wlan_serialize_enter();
-
        ieee80211_waitfor_parent(ic);
 
        ieee80211_sysctl_detach(ic);
@@ -477,14 +448,40 @@ ieee80211_ifdetach(struct ieee80211com *ic)
        ieee80211_power_detach(ic);
        ieee80211_node_detach(ic);
 
-       /* XXX VNET needed? */
-       ifmedia_removeall(&ic->ic_media);
+#if defined(__DragonFly__)
+#else
+       counter_u64_free(ic->ic_ierrors);
+       counter_u64_free(ic->ic_oerrors);
+#endif
 
        taskqueue_free(ic->ic_tq);
        IEEE80211_TX_LOCK_DESTROY(ic);
        IEEE80211_LOCK_DESTROY(ic);
 }
 
+struct ieee80211com *
+ieee80211_find_com(const char *name)
+{
+       struct ieee80211com *ic;
+
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_EXCLUSIVE);
+#else
+       mtx_lock(&ic_list_mtx);
+#endif
+       LIST_FOREACH(ic, &ic_head, ic_next) {
+               if (strcmp(ic->ic_name, name) == 0)
+                       break;
+       }
+#if defined(__DragonFly__)
+       lockmgr(&ic_list_lock, LK_RELEASE);
+#else
+       mtx_unlock(&ic_list_mtx);
+#endif
+
+       return(ic);
+}
+
 /*
  * Default reset method for use with the ioctl support.  This
  * method is invoked after any state change in the 802.11
@@ -500,6 +497,35 @@ default_reset(struct ieee80211vap *vap, u_long cmd)
        return ENETRESET;
 }
 
+#if defined(__DragonFly__)
+#else
+/*
+ * Add underlying device errors to vap errors.
+ */
+static uint64_t
+ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+        struct ieee80211vap *vap = ifp->if_softc;
+        struct ieee80211com *ic = vap->iv_ic;
+        uint64_t rv;
+        rv = if_get_counter_default(ifp, cnt);
+        switch (cnt) {
+        case IFCOUNTER_OERRORS:
+                rv += counter_u64_fetch(ic->ic_oerrors);
+                break;
+        case IFCOUNTER_IERRORS:
+                rv += counter_u64_fetch(ic->ic_ierrors);
+                break;
+        default:
+                break;
+        }
+        return (rv);
+}
+
+#endif
+
 /*
  * Prepare a vap for use.  Drivers use this call to
  * setup net80211 state in new vap's prior attaching
@@ -508,8 +534,7 @@ default_reset(struct ieee80211vap *vap, u_long cmd)
 int
 ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
     const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode,
-    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
-    const uint8_t macaddr[IEEE80211_ADDR_LEN])
+    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN])
 {
        struct ifnet *ifp;
 
@@ -522,13 +547,18 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
        if_initname(ifp, name, unit);
        ifp->if_softc = vap;                    /* back pointer */
        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
+#if defined(__DragonFly__)
        ifp->if_start = ieee80211_vap_start;
-#if 0
+#else
        ifp->if_transmit = ieee80211_vap_transmit;
        ifp->if_qflush = ieee80211_vap_qflush;
 #endif
        ifp->if_ioctl = ieee80211_ioctl;
        ifp->if_init = ieee80211_init;
+#if defined(__DragonFly__)
+#else
+       ifp->if_get_counter = ieee80211_get_counter;
+#endif
 
        vap->iv_ifp = ifp;
        vap->iv_ic = ic;
@@ -540,6 +570,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
        vap->iv_htextcaps = ic->ic_htextcaps;
        vap->iv_opmode = opmode;
        vap->iv_caps |= ieee80211_opcap[opmode];
+       IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_macaddr);
        switch (opmode) {
        case IEEE80211_M_WDS:
                /*
@@ -588,11 +619,13 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
        if (vap->iv_caps & IEEE80211_C_BURST)
                vap->iv_flags |= IEEE80211_F_BURST;
        /* NB: bg scanning only makes sense for station mode right now */
-#if 0
+#if defined(__DragonFly__)
        /*
         * DISABLE BGSCAN BY DEFAULT, many issues can crop up including
         * the link going dead.
         */
+       /* empty */
+#else
        if (vap->iv_opmode == IEEE80211_M_STA &&
            (vap->iv_caps & IEEE80211_C_BGSCAN))
                vap->iv_flags |= IEEE80211_F_BGSCAN;
@@ -612,8 +645,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
         */
        vap->iv_reset = default_reset;
 
-       IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr);
-
        ieee80211_sysctl_vattach(vap);
        ieee80211_crypto_vattach(vap);
        ieee80211_node_vattach(vap);
@@ -637,20 +668,21 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
  * 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)
+ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
+       ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN])
 {
        struct ifnet *ifp = vap->iv_ifp;
        struct ieee80211com *ic = vap->iv_ic;
        struct ifmediareq imr;
        int maxrate;
 
+#if defined(__DragonFly__)
        /*
         * This function must _not_ be serialized by the WLAN serializer,
         * since it could dead-lock the domsg to netisrs in ether_ifattach().
         */
        wlan_assert_notserialized();
-
+#endif
        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],
@@ -673,10 +705,11 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
                ifp->if_baudrate = IF_Mbps(maxrate);
 
 #if defined(__DragonFly__)
-       ether_ifattach(ifp, vap->iv_myaddr, &wlan_global_serializer);
+       ether_ifattach(ifp, macaddr, &wlan_global_serializer);
 #else
-       ether_ifattach(ifp, vap->iv_myaddr);
+       ether_ifattach(ifp, macaddr);
 #endif
+       IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
        /* hook output method setup by ether_ifattach */
        vap->iv_output = ifp->if_output;
        ifp->if_output = ieee80211_output;
@@ -692,8 +725,6 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
        ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
        ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
        ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
-       ieee80211_syncifflag_locked(ic, IFF_PROMISC);
-       ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
        IEEE80211_UNLOCK(ic);
 
        return 1;
@@ -711,12 +742,13 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
        struct ieee80211com *ic = vap->iv_ic;
        struct ifnet *ifp = vap->iv_ifp;
 
+#if defined(__DragonFly__)
        /*
         * This function must _not_ be serialized by the WLAN serializer,
         * since it could dead-lock the domsg to netisrs in ether_ifdettach().
         */
        wlan_assert_notserialized();
-
+#endif
        CURVNET_SET(ifp->if_vnet);
 
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s parent %s\n",
@@ -733,7 +765,9 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
        ieee80211_draintask(ic, &vap->iv_nstate_task);
        ieee80211_draintask(ic, &vap->iv_swbmiss_task);
 
-#if !defined(__DragonFly__)
+#if defined(__DragonFly__)
+       /* XXX hmm, not sure what we should do here */
+#else
        /* XXX band-aid until ifnet handles this for us */
        taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
 #endif
@@ -751,8 +785,17 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
        ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
        /* NB: this handles the bpfdetach done below */
        ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
-       ieee80211_syncifflag_locked(ic, IFF_PROMISC);
-       ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+#if defined(__DragonFly__)
+       if (vap->iv_ifflags & IFF_PROMISC)
+               ieee80211_promisc(vap, 0);
+       if (vap->iv_ifflags & IFF_ALLMULTI)
+               ieee80211_allmulti(vap, 0);
+#else
+       if (vap->iv_ifflags & IFF_PROMISC)
+               ieee80211_promisc(vap, false);
+       if (vap->iv_ifflags & IFF_ALLMULTI)
+               ieee80211_allmulti(vap, false);
+#endif
        IEEE80211_UNLOCK(ic);
 
        ifmedia_removeall(&vap->iv_media);
@@ -777,48 +820,56 @@ ieee80211_vap_detach(struct ieee80211vap *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.
+ * Count number of vaps in promisc, and issue promisc on
+ * parent respectively.
  */
+#if defined(__DragonFly__)
 void
-ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
+ieee80211_promisc(struct ieee80211vap *vap, int on)
+#else
+void
+ieee80211_promisc(struct ieee80211vap *vap, bool on)
+#endif
 {
-       struct ifnet *ifp = ic->ic_ifp;
-       struct ieee80211vap *vap;
-       int bit, oflags;
+       struct ieee80211com *ic = vap->iv_ic;
 
        IEEE80211_LOCK_ASSERT(ic);
 
-       bit = 0;
-       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
-               if (vap->iv_ifp->if_flags & flag) {
-                       /*
-                        * XXX the bridge sets PROMISC but we don't want to
-                        * enable it on the device, discard here so all the
-                        * drivers don't need to special-case it
-                        */
-                       if (flag == IFF_PROMISC &&
-                           !(vap->iv_opmode == IEEE80211_M_MONITOR ||
-                             (vap->iv_opmode == IEEE80211_M_AHDEMO &&
-                              (vap->iv_caps & IEEE80211_C_TDMA) == 0)))
-                               continue;
-                       bit = 1;
-                       break;
-               }
-       oflags = ifp->if_flags;
-       if (bit)
-               ifp->if_flags |= flag;
-       else
-               ifp->if_flags &= ~flag;
-       if ((ifp->if_flags ^ oflags) & flag) {
-               /* XXX should we return 1/0 and let caller do this? */
-               if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-                       if (flag == IFF_PROMISC)
-                               ieee80211_runtask(ic, &ic->ic_promisc_task);
-                       else if (flag == IFF_ALLMULTI)
-                               ieee80211_runtask(ic, &ic->ic_mcast_task);
-               }
+       if (on) {
+               if (++ic->ic_promisc == 1)
+                       ieee80211_runtask(ic, &ic->ic_promisc_task);
+       } else {
+               KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc",
+                   __func__, ic));
+               if (--ic->ic_promisc == 0)
+                       ieee80211_runtask(ic, &ic->ic_promisc_task);
+       }
+}
+
+/*
+ * Count number of vaps in allmulti, and issue allmulti on
+ * parent respectively.
+ */
+#if defined(__DragonFly__)
+void
+ieee80211_allmulti(struct ieee80211vap *vap, int on)
+#else
+void
+ieee80211_allmulti(struct ieee80211vap *vap, bool on)
+#endif
+{
+       struct ieee80211com *ic = vap->iv_ic;
+
+       IEEE80211_LOCK_ASSERT(ic);
+
+       if (on) {
+               if (++ic->ic_allmulti == 1)
+                       ieee80211_runtask(ic, &ic->ic_mcast_task);
+       } else {
+               KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti",
+                   __func__, ic));
+               if (--ic->ic_allmulti == 0)
+                       ieee80211_runtask(ic, &ic->ic_mcast_task);
        }
 }
 
@@ -1053,6 +1104,264 @@ ieee80211_ieee2mhz(u_int chan, u_int flags)
        }
 }
 
+static __inline void
+set_extchan(struct ieee80211_channel *c)
+{
+       /*
+        * IEEE Std 802.11-2012, page 1738, subclause 20.3.15.4:
+        * "the secondary channel number shall be 'N + [1,-1] * 4'
+        */
+       if (c->ic_flags & IEEE80211_CHAN_HT40U)
+               c->ic_extieee = c->ic_ieee + 4;
+       else if (c->ic_flags & IEEE80211_CHAN_HT40D)
+               c->ic_extieee = c->ic_ieee - 4;
+       else
+               c->ic_extieee = 0;
+}
+
+static int
+addchan(struct ieee80211_channel chans[], int maxchans, int *nchans,
+    uint8_t ieee, uint16_t freq, int8_t maxregpower, uint32_t flags)
+{
+       struct ieee80211_channel *c;
+       if (*nchans >= maxchans)
+               return (ENOBUFS);
+       c = &chans[(*nchans)++];
+       c->ic_ieee = ieee;
+       c->ic_freq = freq != 0 ? freq : ieee80211_ieee2mhz(ieee, flags);
+       c->ic_maxregpower = maxregpower;
+       c->ic_maxpower = 2 * maxregpower;
+       c->ic_flags = flags;
+       set_extchan(c);
+       return (0);
+}
+
+static int
+copychan_prev(struct ieee80211_channel chans[], int maxchans, int *nchans,
+    uint32_t flags)
+{
+       struct ieee80211_channel *c;
+       KASSERT(*nchans > 0, ("channel list is empty\n"));
+       if (*nchans >= maxchans)
+               return (ENOBUFS);
+       c = &chans[(*nchans)++];
+       c[0] = c[-1];
+       c->ic_flags = flags;
+       set_extchan(c);
+       return (0);
+}
+
+static void
+getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+       int nmodes;
+       nmodes = 0;
+       if (isset(bands, IEEE80211_MODE_11B))
+               flags[nmodes++] = IEEE80211_CHAN_B;
+       if (isset(bands, IEEE80211_MODE_11G))
+               flags[nmodes++] = IEEE80211_CHAN_G;
+       if (isset(bands, IEEE80211_MODE_11NG))
+               flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT20;
+       if (ht40) {
+               flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U;
+               flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D;
+       }
+       flags[nmodes] = 0;
+}
+
+static void
+getflags_5ghz(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+       int nmodes;
+       nmodes = 0;
+       if (isset(bands, IEEE80211_MODE_11A))
+               flags[nmodes++] = IEEE80211_CHAN_A;
+       if (isset(bands, IEEE80211_MODE_11NA))
+               flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT20;
+       if (ht40) {
+               flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U;
+               flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D;
+       }
+       flags[nmodes] = 0;
+}
+
+static void
+getflags(const uint8_t bands[], uint32_t flags[], int ht40)
+{
+       flags[0] = 0;
+       if (isset(bands, IEEE80211_MODE_11A) ||
+           isset(bands, IEEE80211_MODE_11NA)) {
+               if (isset(bands, IEEE80211_MODE_11B) ||
+                   isset(bands, IEEE80211_MODE_11G) ||
+                   isset(bands, IEEE80211_MODE_11NG))
+                       return;
+               getflags_5ghz(bands, flags, ht40);
+       } else
+               getflags_2ghz(bands, flags, ht40);
+}
+
+/*
+ * Add one 20 MHz channel into specified channel list.
+ */
+int
+ieee80211_add_channel(struct ieee80211_channel chans[], int maxchans,
+    int *nchans, uint8_t ieee, uint16_t freq, int8_t maxregpower,
+    uint32_t chan_flags, const uint8_t bands[])
+{
+       uint32_t flags[IEEE80211_MODE_MAX];
+       int i, error;
+       getflags(bands, flags, 0);
+       KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+       error = addchan(chans, maxchans, nchans, ieee, freq, maxregpower,
+           flags[0] | chan_flags);
+       for (i = 1; flags[i] != 0 && error == 0; i++) {
+               error = copychan_prev(chans, maxchans, nchans,
+                   flags[i] | chan_flags);
+       }
+       return (error);
+}
+static struct ieee80211_channel *
+findchannel(struct ieee80211_channel chans[], int nchans, uint16_t freq,
+    uint32_t flags)
+{
+       struct ieee80211_channel *c;
+       int i;
+       flags &= IEEE80211_CHAN_ALLTURBO;
+       /* brute force search */
+       for (i = 0; i < nchans; i++) {
+               c = &chans[i];
+               if (c->ic_freq == freq &&
+                   (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
+                       return c;
+       }
+       return NULL;
+}
+
+/*
+ * Add 40 MHz channel pair into specified channel list.
+ */
+int
+ieee80211_add_channel_ht40(struct ieee80211_channel chans[], int maxchans,
+    int *nchans, uint8_t ieee, int8_t maxregpower, uint32_t flags)
+{
+       struct ieee80211_channel *cent, *extc;
+       uint16_t freq;
+       int error;
+       freq = ieee80211_ieee2mhz(ieee, flags);
+       /*
+        * Each entry defines an HT40 channel pair; find the
+        * center channel, then the extension channel above.
+        */
+       flags |= IEEE80211_CHAN_HT20;
+       cent = findchannel(chans, *nchans, freq, flags);
+       if (cent == NULL)
+               return (EINVAL);
+       extc = findchannel(chans, *nchans, freq + 20, flags);
+       if (extc == NULL)
+               return (ENOENT);
+       flags &= ~IEEE80211_CHAN_HT;
+       error = addchan(chans, maxchans, nchans, cent->ic_ieee, cent->ic_freq,
+           maxregpower, flags | IEEE80211_CHAN_HT40U);
+       if (error != 0)
+               return (error);
+       error = addchan(chans, maxchans, nchans, extc->ic_ieee, extc->ic_freq,
+           maxregpower, flags | IEEE80211_CHAN_HT40D);
+       return (error);
+}
+
+/*
+ * Adds channels into specified channel list (ieee[] array must be sorted).
+ * Channels are already sorted.
+ */
+static int
+add_chanlist(struct ieee80211_channel chans[], int maxchans, int *nchans,
+    const uint8_t ieee[], int nieee, uint32_t flags[])
+{
+       uint16_t freq;
+       int i, j, error;
+#if defined(__DragonFly__)
+       error = 0;      /* work-around GCC uninitialized variable warning */
+#endif
+       for (i = 0; i < nieee; i++) {
+               freq = ieee80211_ieee2mhz(ieee[i], flags[0]);
+               for (j = 0; flags[j] != 0; j++) {
+                       if (flags[j] & IEEE80211_CHAN_HT40D)
+                               if (i == 0 || ieee[i] < ieee[0] + 4 ||
+                                   freq - 20 !=
+                                   ieee80211_ieee2mhz(ieee[i] - 4, flags[j]))
+                                       continue;
+                       if (flags[j] & IEEE80211_CHAN_HT40U)
+                               if (i == nieee - 1 ||
+                                   ieee[i] + 4 > ieee[nieee - 1] ||
+                                   freq + 20 !=
+                                   ieee80211_ieee2mhz(ieee[i] + 4, flags[j]))
+                                       continue;
+                       if (j == 0) {
+                               error = addchan(chans, maxchans, nchans,
+                                   ieee[i], freq, 0, flags[j]);
+                       } else {
+                               error = copychan_prev(chans, maxchans, nchans,
+                                   flags[j]);
+                       }
+                       if (error != 0)
+                               return (error);
+               }
+       }
+       return (error);
+}
+
+int
+ieee80211_add_channel_list_2ghz(struct ieee80211_channel chans[], int maxchans,
+    int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[],
+    int ht40)
+{
+       uint32_t flags[IEEE80211_MODE_MAX];
+       getflags_2ghz(bands, flags, ht40);
+       KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+       return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags));
+}
+
+int
+ieee80211_add_channel_list_5ghz(struct ieee80211_channel chans[], int maxchans,
+    int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[],
+    int ht40)
+{
+       uint32_t flags[IEEE80211_MODE_MAX];
+       getflags_5ghz(bands, flags, ht40);
+       KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__));
+       return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags));
+}
+
 /*
  * Locate a channel given a frequency+flags.  We cache
  * the previous lookup to optimize switching between two
@@ -1062,7 +1371,6 @@ struct ieee80211_channel *
 ieee80211_find_channel(struct ieee80211com *ic, int freq, int flags)
 {
        struct ieee80211_channel *c;
-       int i;
 
        flags &= IEEE80211_CHAN_ALLTURBO;
        c = ic->ic_prevchan;
@@ -1070,13 +1378,7 @@ ieee80211_find_channel(struct ieee80211com *ic, int freq, int flags)
            (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
                return c;
        /* brute force search */
-       for (i = 0; i < ic->ic_nchans; i++) {
-               c = &ic->ic_channels[i];
-               if (c->ic_freq == freq &&
-                   (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
-                       return c;
-       }
-       return NULL;
+       return (findchannel(ic->ic_channels, ic->ic_nchans, freq, flags));
 }
 
 /*
@@ -1308,39 +1610,6 @@ ieee80211_media_setup(struct ieee80211com *ic,
        return maxrate;
 }
 
-void
-ieee80211_media_init(struct ieee80211com *ic)
-{
-       struct ifnet *ifp = ic->ic_ifp;
-       int maxrate;
-
-       /* NB: this works because the structure is initialized to zero */
-       if (!LIST_EMPTY(&ic->ic_media.ifm_list)) {
-               /*
-                * We are re-initializing the channel list; clear
-                * the existing media state as the media routines
-                * don't suppress duplicates.
-                */
-               ifmedia_removeall(&ic->ic_media);
-       }
-       ieee80211_chan_init(ic);
-
-       /*
-        * Recalculate media settings in case new channel list changes
-        * the set of available modes.
-        */
-       maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1,
-               ieee80211com_media_change, ieee80211com_media_status);
-       /* NB: strip explicit mode; we're actually in autoselect */
-       ifmedia_set(&ic->ic_media,
-           media_status(ic->ic_opmode, ic->ic_curchan) &~
-               (IFM_MMASK | IFM_IEEE80211_TURBO));
-       if (maxrate)
-               ifp->if_baudrate = IF_Mbps(maxrate);
-
-       /* XXX need to propagate new media settings to vap's */
-}
-
 /* XXX inline or eliminate? */
 const struct ieee80211_rateset *
 ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
@@ -1468,15 +1737,6 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode)
        return 1;
 }
 
-/*
- * Handle a media change request on the underlying interface.
- */
-static int
-ieee80211com_media_change(struct ifnet *ifp)
-{
-       return EINVAL;
-}
-
 /*
  * Handle a media change request on the vap interface.
  */
@@ -1554,23 +1814,6 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan)
        return status;
 }
 
-static void
-ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr)
-{
-       struct ieee80211com *ic = ifp->if_l2com;
-       struct ieee80211vap *vap;
-
-       imr->ifm_status = IFM_AVALID;
-       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
-               if (vap->iv_ifp->if_flags & IFF_UP) {
-                       imr->ifm_status |= IFM_ACTIVE;
-                       break;
-               }
-       imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
-       if (imr->ifm_status & IFM_ACTIVE)
-               imr->ifm_current = imr->ifm_active;
-}
-
 void
 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 {
@@ -1727,7 +1970,7 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode m
                {   6 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM3 },
                {   9 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM4 },
                {  54 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM27 },
-               /* NB: OFDM72 doesn't realy exist so we don't handle it */
+               /* NB: OFDM72 doesn't really exist so we don't handle it */
        };
        static const struct ratemedia htrates[] = {
                {   0, IFM_IEEE80211_MCS },
index ddd2c39..d3f9fbf 100644 (file)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/systm.h> 
  
 #include <sys/socket.h>
index 807388b..e63691e 100644 (file)
@@ -302,7 +302,6 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
        int hdrspace, need_tap = 1;     /* mbuf need to be tapped. */   
        uint8_t dir, type, subtype, qos;
        uint8_t *bssid;
-       uint16_t rxseq;
 
        if (m->m_flags & M_AMPDU_MPDU) {
                /*
@@ -372,10 +371,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
                /*
                 * Validate the bssid.
                 */
-               if (!(type == IEEE80211_FC0_TYPE_MGT &&
-                    (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
-                     subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) &&
-                   !IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
+               if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
                    !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
                        /* not interested in */
                        IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
@@ -421,24 +417,8 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
                        if (IEEE80211_QOS_HAS_SEQ(wh) &&
                            TID_TO_WME_AC(tid) >= WME_AC_VI)
                                ic->ic_wme.wme_hipri_traffic++;
-                       rxseq = le16toh(*(uint16_t *)wh->i_seq);
-                       if (! ieee80211_check_rxseq(ni, wh)) {
-                               /* duplicate, discard */
-                               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
-                                   bssid, "duplicate",
-                                   "seqno <%u,%u> fragno <%u,%u> tid %u",
-                                   rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
-                                   ni->ni_rxseqs[tid] >>
-                                       IEEE80211_SEQ_SEQ_SHIFT,
-                                   rxseq & IEEE80211_SEQ_FRAG_MASK,
-                                   ni->ni_rxseqs[tid] &
-                                       IEEE80211_SEQ_FRAG_MASK,
-                                   tid);
-                               vap->iv_stats.is_rx_dup++;
-                               IEEE80211_NODE_STAT(ni, rx_dup);
+                       if (! ieee80211_check_rxseq(ni, wh, bssid))
                                goto out;
-                       }
-                       ni->ni_rxseqs[tid] = rxseq;
                }
        }
 
@@ -633,8 +613,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
                if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) ||
                    ieee80211_msg_dumppkts(vap)) {
                        if_printf(ifp, "received %s from %s rssi %d\n",
-                           ieee80211_mgt_subtype_name[subtype >>
-                               IEEE80211_FC0_SUBTYPE_SHIFT],
+                           ieee80211_mgt_subtype_name(subtype),
                            ether_sprintf(wh->i_addr2), rssi);
                }
 #endif
@@ -660,7 +639,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
                break;
        }
 err:
-       IFNET_STAT_INC(ifp, ierrors, 1);
+       if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 out:
        if (m != NULL) {
                if (need_tap && ieee80211_radiotap_active_vap(vap))
@@ -796,7 +775,7 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                         *
                         * Since there's no (current) way to inform
                         * the driver that a channel width change has
-                        * occured for a single node, just stub this
+                        * occurred for a single node, just stub this
                         * out.
                         */
 #if 0
@@ -875,7 +854,8 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
 
        case IEEE80211_FC0_SUBTYPE_ACTION:
        case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
-               if (ni == vap->iv_bss) {
+               if ((ni == vap->iv_bss) &&
+                   !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
                        IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
                            wh, NULL, "%s", "unknown node");
                        vap->iv_stats.is_rx_mgtdiscard++;
@@ -899,6 +879,7 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
        case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+       case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
        case IEEE80211_FC0_SUBTYPE_ATIM:
        case IEEE80211_FC0_SUBTYPE_DISASSOC:
        case IEEE80211_FC0_SUBTYPE_AUTH:
@@ -941,6 +922,7 @@ ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
                case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
                case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+               case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
                case IEEE80211_FC0_SUBTYPE_BEACON:
                case IEEE80211_FC0_SUBTYPE_ATIM:
                case IEEE80211_FC0_SUBTYPE_DISASSOC:
index db1d8db..e0cd0c3 100644 (file)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h> 
 #include <sys/kernel.h>
+#include <sys/malloc.h>
  
 #include <sys/socket.h>
 
index 36d7ed5..8c7d07d 100644 (file)
@@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/module.h>
+#include <sys/sbuf.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 
@@ -74,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;
@@ -90,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);
@@ -113,8 +117,13 @@ amrr_init(struct ieee80211vap *vap)
 
        KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__));
 
+#if defined(__DragonFly__)
        amrr = vap->iv_rs = kmalloc(sizeof(struct ieee80211_amrr),
            M_80211_RATECTL, M_INTWAIT|M_ZERO);
+#else
+       amrr = vap->iv_rs = IEEE80211_MALLOC(sizeof(struct ieee80211_amrr),
+           M_80211_RATECTL, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (amrr == NULL) {
                if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
                return;
@@ -128,7 +137,7 @@ amrr_init(struct ieee80211vap *vap)
 static void
 amrr_deinit(struct ieee80211vap *vap)
 {
-       kfree(vap->iv_rs, M_80211_RATECTL);
+       IEEE80211_FREE(vap->iv_rs, M_80211_RATECTL);
 }
 
 /*
@@ -160,8 +169,13 @@ amrr_node_init(struct ieee80211_node *ni)
        uint8_t rate;
 
        if (ni->ni_rctls == NULL) {
+#if defined(__DragonFly__)
                ni->ni_rctls = amn = kmalloc(sizeof(struct ieee80211_amrr_node),
                    M_80211_RATECTL, M_INTWAIT|M_ZERO);
+#else
+               ni->ni_rctls = amn = IEEE80211_MALLOC(sizeof(struct ieee80211_amrr_node),
+                   M_80211_RATECTL, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                if (amn == NULL) {
                        if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
                            "structure\n");
@@ -225,7 +239,7 @@ amrr_node_init(struct ieee80211_node *ni)
 static void
 amrr_node_deinit(struct ieee80211_node *ni)
 {
-       kfree(ni->ni_rctls, M_80211_RATECTL);
+       IEEE80211_FREE(ni->ni_rctls, M_80211_RATECTL);
 }
 
 static int
@@ -409,3 +423,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);
+}
index 6d213d2..f09e3c8 100644 (file)
@@ -89,8 +89,7 @@ null_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
        return 1;
 }
 static         int
-null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
-       const uint8_t mac[IEEE80211_ADDR_LEN])
+null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
 {
        return 1;
 }
@@ -132,7 +131,7 @@ dev_key_delete(struct ieee80211vap *vap,
 static __inline int
 dev_key_set(struct ieee80211vap *vap, const struct ieee80211_key *key)
 {
-       return vap->iv_key_set(vap, key, key->wk_macaddr);
+       return vap->iv_key_set(vap, key);
 }
 
 /*
@@ -521,17 +520,21 @@ ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key)
        return dev_key_set(vap, key);
 }
 
-/*
- * Add privacy headers appropriate for the specified key.
- */
+uint8_t
+ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k)
+{
+       if (k >= &vap->iv_nw_keys[0] &&
+           k <  &vap->iv_nw_keys[IEEE80211_WEP_NKID])
+               return (k - vap->iv_nw_keys);
+       else
+               return (0);
+}
+
 struct ieee80211_key *
-ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
+ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m)
 {
        struct ieee80211vap *vap = ni->ni_vap;
-       struct ieee80211_key *k;
        struct ieee80211_frame *wh;
-       const struct ieee80211_cipher *cip;
-       uint8_t keyid;
 
        /*
         * Multicast traffic always uses the multicast key.
@@ -550,14 +553,27 @@ ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
                        vap->iv_stats.is_tx_nodefkey++;
                        return NULL;
                }
-               keyid = vap->iv_def_txkey;
-               k = &vap->iv_nw_keys[vap->iv_def_txkey];
-       } else {
-               keyid = 0;
-               k = &ni->ni_ucastkey;
+               return &vap->iv_nw_keys[vap->iv_def_txkey];
        }
-       cip = k->wk_cipher;
-       return (cip->ic_encap(k, m, keyid<<6) ? k : NULL);
+
+       return &ni->ni_ucastkey;
+}
+
+/*
+ * Add privacy headers appropriate for the specified key.
+ */
+struct ieee80211_key *
+ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
+{
+       struct ieee80211_key *k;
+       const struct ieee80211_cipher *cip;
+
+       if ((k = ieee80211_crypto_get_txkey(ni, m)) != NULL) {
+               cip = k->wk_cipher;
+               return (cip->ic_encap(k, m) ? k : NULL);
+       }
+
+       return NULL;
 }
 
 /*
index da799a9..cb5dacc 100644 (file)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h> 
+#include <sys/malloc.h> 
 #include <sys/systm.h> 
 #include <sys/mbuf.h>   
 #include <sys/module.h>
@@ -48,7 +49,8 @@ __FBSDID("$FreeBSD$");
 static void *none_attach(struct ieee80211vap *, struct ieee80211_key *);
 static void none_detach(struct ieee80211_key *);
 static int none_setkey(struct ieee80211_key *);
-static int none_encap(struct ieee80211_key *, struct mbuf *, uint8_t);
+static void none_setiv(struct ieee80211_key *, uint8_t *);
+static int none_encap(struct ieee80211_key *, struct mbuf *);
 static int none_decap(struct ieee80211_key *, struct mbuf *, int);
 static int none_enmic(struct ieee80211_key *, struct mbuf *, int);
 static int none_demic(struct ieee80211_key *, struct mbuf *, int);
@@ -62,6 +64,7 @@ const struct ieee80211_cipher ieee80211_cipher_none = {
        .ic_attach      = none_attach,
        .ic_detach      = none_detach,
        .ic_setkey      = none_setkey,
+       .ic_setiv       = none_setiv,
        .ic_encap       = none_encap,
        .ic_decap       = none_decap,
        .ic_enmic       = none_enmic,
@@ -87,20 +90,28 @@ none_setkey(struct ieee80211_key *k)
        return 1;
 }
 
+static void
+none_setiv(struct ieee80211_key *k, uint8_t *ivp)
+{
+}
+
 static int
-none_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
+none_encap(struct ieee80211_key *k, struct mbuf *m)
 {
        struct ieee80211vap *vap = k->wk_private;
 #ifdef IEEE80211_DEBUG
        struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
 #endif
+       uint8_t keyid;
+
+       keyid = ieee80211_crypto_get_keyid(vap, k);
 
        /*
         * The specified key is not setup; this can
         * happen, at least, when changing keys.
         */
        IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1,
-           "key id %u is not set (encap)", keyid>>6);
+           "key id %u is not set (encap)", keyid);
        vap->iv_stats.is_tx_badcipher++;
        return 0;
 }
index b77c6ba..24a3d6f 100644 (file)
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h> 
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/socket.h>
 
 #include <net/if.h>
@@ -44,7 +45,10 @@ __FBSDID("$FreeBSD$");
 #include <net/if_media.h>
 #include <net/if_types.h>
 #include <net/ethernet.h>
-/*#include <net/vnet.h>*/
+#if defined(__DragonFly__)
+#else
+#include <net/vnet.h>
+#endif
 
 #include <netproto/802_11/ieee80211_var.h>
 #ifdef IEEE80211_SUPPORT_TDMA
@@ -158,7 +162,9 @@ DB_SHOW_COMMAND(com, db_show_com)
        _db_show_com(ic, showvaps, showsta, showmesh, showprocs);
 }
 
-#if !defined(__DragonFly__)
+#if defined(__DragonFly__)
+/* EMPTY */
+#else
 
 DB_SHOW_ALL_COMMAND(vaps, db_show_all_vaps)
 {
@@ -524,7 +530,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
        TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
                db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap);
        db_printf("\n");
-       db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname);
+       db_printf("\tsoftc %p", ic->ic_softc);
        db_printf("\tname %s", ic->ic_name);
        db_printf(" comlock %p", &ic->ic_comlock);
        db_printf("\n");
@@ -532,7 +538,6 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
        db_printf(" phytype %d", ic->ic_phytype);
        db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
        db_printf("\n");
-       db_printf("\tmedia %p", &ic->ic_media);
        db_printf(" inact %p", &ic->ic_inact);
        db_printf("\n");
 
@@ -890,9 +895,14 @@ _db_show_mesh(const struct ieee80211_mesh_state *ms)
        db_printf("routing table:\n");
        i = 0;
        TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
+#if defined(__DragonFly__)
                db_printf("entry %d:\tdest: %s nexthop: %s metric: %u", i,
                    ether_sprintf(rt->rt_dest), ether_sprintf(rt->rt_nexthop),
                    rt->rt_metric);
+#else
+               db_printf("entry %d:\tdest: %6D nexthop: %6D metric: %u", i,
+                   rt->rt_dest, ":", rt->rt_nexthop, ":", rt->rt_metric);
+#endif
 
                db_printf("\tlifetime: %u lastseq: %u priv: %p\n",
                    ieee80211_mesh_rt_update(rt, 0),
index 2d1c4f6..eeb0c9b 100644 (file)
@@ -243,7 +243,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) {
                                        /*
@@ -265,8 +265,12 @@ dfs_timeout(void *arg)
        }
        if (oldest != now) {
                /* arrange to process next channel up for a status change */
+#if defined(__DragonFly__)
                callout_schedule_dfly(&dfs->nol_timer, oldest + NOL_TIMEOUT - now,
                                dfs_timeout, ic);
+#else
+               callout_schedule(&dfs->nol_timer, oldest + NOL_TIMEOUT - now);
+#endif
        }
 }
 
@@ -366,7 +370,11 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch
                announce_radar(ic, chan, dfs->newchan);
 
                if (callout_pending(&dfs->cac_timer))
+#if defined(__DragonFly__)
                        callout_schedule_dfly(&dfs->cac_timer, 0, cac_timeout, dfs->cac_timer.c_arg);
+#else
+                       callout_schedule(&dfs->cac_timer, 0);
+#endif
                else if (dfs->newchan != NULL) {
                        /* XXX mode 1, switch count 2 */
                        /* XXX calculate switch count based on max
index 1e1fba2..b64d224 100644 (file)
@@ -78,66 +78,29 @@ static struct if_clone wlan_cloner =
 
 struct lwkt_serialize wlan_global_serializer = LWKT_SERIALIZE_INITIALIZER;
 
-/*
- * Allocate/free com structure in conjunction with ifnet;
- * these routines are registered with if_register_com_alloc
- * below and are called automatically by the ifnet code
- * when the ifnet of the parent device is created.
- */
-static void *
-wlan_alloc(u_char type, struct ifnet *ifp)
-{
-       struct ieee80211com *ic;
-
-       ic = kmalloc(sizeof(struct ieee80211com), M_80211_COM, M_WAITOK|M_ZERO);
-       ic->ic_ifp = ifp;
-
-       return (ic);
-}
-
-static void
-wlan_free(void *ic, u_char type)
-{
-       kfree(ic, M_80211_COM);
-}
-
 static int
 wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
 {
        struct ieee80211_clone_params cp;
        struct ieee80211vap *vap;
        struct ieee80211com *ic;
-       struct ifnet *ifp;
        int error;
 
        error = copyin(params, &cp, sizeof(cp));
        if (error)
                return error;
 
-       ifnet_lock();
-
-       ifp = ifunit(cp.icp_parent);
-       if (ifp == NULL) {
-               ifnet_unlock();
-               return ENXIO;
-       }
-       /* XXX move printfs to DIAGNOSTIC before release */
-       if (ifp->if_type != IFT_IEEE80211) {
-               if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
-               ifnet_unlock();
+       ic = ieee80211_find_com(cp.icp_parent);
+       if (ic == NULL)
                return ENXIO;
-       }
        if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
-               if_printf(ifp, "%s: invalid opmode %d\n",
-                   __func__, cp.icp_opmode);
-               ifnet_unlock();
+               ic_printf(ic, "%s: invalid opmode %d\n", __func__,
+                   cp.icp_opmode);
                return EINVAL;
        }
-       ic = ifp->if_l2com;
        if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
-               if_printf(ifp, "%s mode not supported\n",
+               ic_printf(ic, "%s mode not supported\n",
                    ieee80211_opmode_name[cp.icp_opmode]);
-               ifnet_unlock();
                return EOPNOTSUPP;
        }
        if ((cp.icp_flags & IEEE80211_CLONE_TDMA) &&
@@ -147,16 +110,14 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
            (1)
 #endif
        ) {
-               if_printf(ifp, "TDMA not supported\n");
-               ifnet_unlock();
+               ic_printf(ic, "TDMA not supported\n");
                return EOPNOTSUPP;
        }
        vap = ic->ic_vap_create(ic, ifc->ifc_name, unit,
                        cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
                        cp.icp_flags & IEEE80211_CLONE_MACADDR ?
-                           cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
+                           cp.icp_macaddr : ic->ic_macaddr);
 
-       ifnet_unlock();
 
        return (vap == NULL ? EIO : 0);
 }
@@ -276,6 +237,44 @@ wlan_cv_signal(struct cv *cv, int broadcast)
 
 #endif
 
+/*
+ * Add RX parameters to the given mbuf.
+ *
+ * Returns 1 if OK, 0 on error.
+ */
+int
+ieee80211_add_rx_params(struct mbuf *m, const struct ieee80211_rx_stats *rxs)
+{
+       struct m_tag *mtag;
+       struct ieee80211_rx_params *rx;
+
+       mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
+               sizeof(struct ieee80211_rx_stats), M_NOWAIT);
+       if (mtag == NULL)
+               return (0);
+
+       rx = (struct ieee80211_rx_params *)(mtag + 1);
+       memcpy(&rx->params, rxs, sizeof(*rxs));
+       m_tag_prepend(m, mtag);
+       return (1);
+}
+
+int
+ieee80211_get_rx_params(struct mbuf *m, struct ieee80211_rx_stats *rxs)
+{
+       struct m_tag *mtag;
+       struct ieee80211_rx_params *rx;
+       mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_RECV_PARAMS,
+           NULL);
+       if (mtag == NULL)
+               return (-1);
+       rx = (struct ieee80211_rx_params *)(mtag + 1);
+       memcpy(rxs, &rx->params, sizeof(*rxs));
+       return (0);
+}
+
+#if 0
 /*
  * Misc
  */
@@ -300,27 +299,30 @@ ieee80211_vap_xmitpkt(struct ieee80211vap *vap, struct mbuf *m)
 
        return error;
 }
+#endif
 
 int
 ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
 {
-       struct ifnet *parent = ic->ic_ifp;
-       struct ifaltq_subque *ifsq = ifq_get_subq_default(&parent->if_snd);
        int error;
-       int wst;
 
        /*
         * Assert the IC TX lock is held - this enforces the
         * processing -> queuing order is maintained
         */
        IEEE80211_TX_LOCK_ASSERT(ic);
+       error = ic->ic_transmit(ic, m);
+       if (error) {
+               struct ieee80211_node *ni;
 
-       error = ifsq_enqueue(ifsq, m, NULL);
-       wst = wlan_serialize_push();
-       parent->if_start(parent, ifsq);
-       wlan_serialize_pop(wst);
+               ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
 
-       return error;
+               /* XXX number of fragments */
+               IFNET_STAT_INC(ni->ni_vap->iv_ifp, oerrors, 1);
+               ieee80211_free_node(ni);
+               ieee80211_free_mbuf(m);
+       }
+       return (error);
 }
 
 void
@@ -567,7 +569,7 @@ ieee80211_flush_ifq(struct ifaltq *ifq, struct ieee80211vap *vap)
  */
 #define        MC_ALIGN(m, len)                                                \
 do {                                                                   \
-       (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1);        \
+       (m)->m_data += rounddown2(MCLBYTES - (len), sizeof(long));      \
 } while (/* CONSTCOND */ 0)
 
 /*
@@ -1094,27 +1096,17 @@ ether_sprintf(const u_char *buf)
        return (ptr);
 }
 
+/*
+ * Change MAC address on the vap (if was not started).
+ */
 static void
 wlan_iflladdr_event(void *arg __unused, struct ifnet *ifp)
 {
-       struct ieee80211com *ic = ifp->if_l2com;
-       struct ieee80211vap *vap, *next;
-
-       if (ifp->if_type != IFT_IEEE80211 || ic == NULL) {
-               return;
-       }
-
-       TAILQ_FOREACH_MUTABLE(vap, &ic->ic_vaps, iv_next, next) {
-               /*
-                * If the MAC address has changed on the parent and it was
-                * copied to the vap on creation then re-sync.
-                */
-               if (vap->iv_ic == ic &&
-                   (vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
-                       IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
-                       if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
-                                    IEEE80211_ADDR_LEN);
-               }
+       /* NB: identify vap's by if_init */
+       if (ifp->if_init == ieee80211_init &&
+           (ifp->if_flags & IFF_UP) == 0) {
+               struct ieee80211vap *vap = ifp->if_softc;
+               IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
        }
 }
 
@@ -1139,11 +1131,9 @@ wlan_modevent(module_t mod, int type, void *unused)
                                        wlan_iflladdr_event, NULL,
                                        EVENTHANDLER_PRI_ANY);
                if_clone_attach(&wlan_cloner);
-               if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
                error = 0;
                break;
        case MOD_UNLOAD:
-               if_deregister_com_alloc(IFT_IEEE80211);
                if_clone_detach(&wlan_cloner);
                EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
                EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
index f30c472..70732cc 100644 (file)
@@ -369,7 +369,7 @@ hostap_deliver_data(struct ieee80211vap *vap,
        /*
         * Do accounting.
         */
-       IFNET_STAT_INC(ifp, ipackets, 1);
+       if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
        IEEE80211_NODE_STAT(ni, rx_data);
        IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
@@ -385,7 +385,7 @@ hostap_deliver_data(struct ieee80211vap *vap,
                if (m->m_flags & M_MCAST) {
                        mcopy = m_dup(m, M_NOWAIT);
                        if (mcopy == NULL)
-                               IFNET_STAT_INC(ifp, oerrors, 1);
+                               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
                        else
                                mcopy->m_flags |= M_MCAST;
                } else {
@@ -423,7 +423,7 @@ hostap_deliver_data(struct ieee80211vap *vap,
                        if (err) {
                                /* NB: IFQ_HANDOFF reclaims mcopy */
                        } else {
-                               IFNET_STAT_INC(ifp, opackets, 1);
+                               if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
                        }
                }
        }
@@ -449,7 +449,11 @@ hostap_deliver_data(struct ieee80211vap *vap,
 #endif
                        m->m_flags |= M_VLANTAG;
                }
+#if defined(__DragonFly__)
                ifp->if_input(ifp, m, NULL, -1);
+#else
+               ifp->if_input(ifp, m);
+#endif
        }
 }
 
@@ -494,7 +498,6 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
        int hdrspace, need_tap = 1;     /* mbuf need to be tapped. */
        uint8_t dir, type, subtype, qos;
        uint8_t *bssid;
-       uint16_t rxseq;
 
        if (m->m_flags & M_AMPDU_MPDU) {
                /*
@@ -582,24 +585,8 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
                        if (IEEE80211_QOS_HAS_SEQ(wh) &&
                            TID_TO_WME_AC(tid) >= WME_AC_VI)
                                ic->ic_wme.wme_hipri_traffic++;
-                       rxseq = le16toh(*(uint16_t *)wh->i_seq);
-                       if (! ieee80211_check_rxseq(ni, wh)) {
-                               /* duplicate, discard */
-                               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
-                                   bssid, "duplicate",
-                                   "seqno <%u,%u> fragno <%u,%u> tid %u",
-                                   rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
-                                   ni->ni_rxseqs[tid] >>
-                                       IEEE80211_SEQ_SEQ_SHIFT,
-                                   rxseq & IEEE80211_SEQ_FRAG_MASK,
-                                   ni->ni_rxseqs[tid] &
-                                       IEEE80211_SEQ_FRAG_MASK,
-                                   tid);
-                               vap->iv_stats.is_rx_dup++;
-                               IEEE80211_NODE_STAT(ni, rx_dup);
+                       if (! ieee80211_check_rxseq(ni, wh, bssid))
                                goto out;
-                       }
-                       ni->ni_rxseqs[tid] = rxseq;
                }
        }
 
@@ -857,8 +844,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
                if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) ||
                    ieee80211_msg_dumppkts(vap)) {
                        if_printf(ifp, "received %s from %s rssi %d\n",
-                           ieee80211_mgt_subtype_name[subtype >>
-                               IEEE80211_FC0_SUBTYPE_SHIFT],
+                           ieee80211_mgt_subtype_name(subtype),
                            ether_sprintf(wh->i_addr2), rssi);
                }
 #endif
@@ -915,7 +901,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
                break;
        }
 err:
-       IFNET_STAT_INC(ifp, ierrors, 1);
+       if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 out:
        if (m != NULL) {
                if (need_tap && ieee80211_radiotap_active_vap(vap))
@@ -944,7 +930,7 @@ hostap_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh,
                 * open auth is attempted.
                 */
                if (ni->ni_challenge != NULL) {
-                       kfree(ni->ni_challenge, M_80211_NODE);
+                       IEEE80211_FREE(ni->ni_challenge, M_80211_NODE);
                        ni->ni_challenge = NULL;
                }
                /* XXX hack to workaround calling convention */
@@ -1191,7 +1177,7 @@ static int
 wpa_cipher(const uint8_t *sel, uint8_t *keylen)
 {
 #define        WPA_SEL(x)      (((x)<<24)|WPA_OUI)
-       uint32_t w = LE_READ_4(sel);
+       uint32_t w = le32dec(sel);
 
        switch (w) {
        case WPA_SEL(WPA_CSE_NULL):
@@ -1221,7 +1207,7 @@ static int
 wpa_keymgmt(const uint8_t *sel)
 {
 #define        WPA_SEL(x)      (((x)<<24)|WPA_OUI)
-       uint32_t w = LE_READ_4(sel);
+       uint32_t w = le32dec(sel);
 
        switch (w) {
        case WPA_SEL(WPA_ASE_8021X_UNSPEC):
@@ -1268,7 +1254,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm,
        }
        frm += 6, len -= 4;             /* NB: len is payload only */
        /* NB: iswpaoui already validated the OUI and type */
-       w = LE_READ_2(frm);
+       w = le16dec(frm);
        if (w != WPA_VERSION) {
                IEEE80211_DISCARD_IE(vap,
                    IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
@@ -1284,7 +1270,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm,
        frm += 4, len -= 4;
 
        /* unicast ciphers */
-       n = LE_READ_2(frm);
+       n = le16dec(frm);
        frm += 2, len -= 2;
        if (len < n*4+2) {
                IEEE80211_DISCARD_IE(vap,
@@ -1304,7 +1290,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm,
                rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
 
        /* key management algorithms */
-       n = LE_READ_2(frm);
+       n = le16dec(frm);
        frm += 2, len -= 2;
        if (len < n*4) {
                IEEE80211_DISCARD_IE(vap,
@@ -1324,7 +1310,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm,
                rsn->rsn_keymgmt = WPA_ASE_8021X_PSK;
 
        if (len > 2)            /* optional capabilities */
-               rsn->rsn_caps = LE_READ_2(frm);
+               rsn->rsn_caps = le16dec(frm);
 
        return 0;
 }
@@ -1338,7 +1324,7 @@ static int
 rsn_cipher(const uint8_t *sel, uint8_t *keylen)
 {
 #define        RSN_SEL(x)      (((x)<<24)|RSN_OUI)
-       uint32_t w = LE_READ_4(sel);
+       uint32_t w = le32dec(sel);
 
        switch (w) {
        case RSN_SEL(RSN_CSE_NULL):
@@ -1370,7 +1356,7 @@ static int
 rsn_keymgmt(const uint8_t *sel)
 {
 #define        RSN_SEL(x)      (((x)<<24)|RSN_OUI)
-       uint32_t w = LE_READ_4(sel);
+       uint32_t w = le32dec(sel);
 
        switch (w) {
        case RSN_SEL(RSN_ASE_8021X_UNSPEC):
@@ -1415,7 +1401,7 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, const uint8_t *frm,
                return IEEE80211_REASON_IE_INVALID;
        }
        frm += 2;
-       w = LE_READ_2(frm);
+       w = le16dec(frm);
        if (w != RSN_VERSION) {
                IEEE80211_DISCARD_IE(vap,
                    IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
@@ -1431,7 +1417,7 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, const uint8_t *frm,
        frm += 4, len -= 4;
 
        /* unicast ciphers */
-       n = LE_READ_2(frm);
+       n = le16dec(frm);
        frm += 2, len -= 2;
        if (len < n*4+2) {
                IEEE80211_DISCARD_IE(vap,
@@ -1451,7 +1437,7 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, const uint8_t *frm,
                rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
 
        /* key management algorithms */
-       n = LE_READ_2(frm);
+       n = le16dec(frm);
        frm += 2, len -= 2;
        if (len < n*4) {
                IEEE80211_DISCARD_IE(vap,
@@ -1472,14 +1458,14 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, const uint8_t *frm,
 
        /* optional RSN capabilities */
        if (len > 2)
-               rsn->rsn_caps = LE_READ_2(frm);
+               rsn->rsn_caps = le16dec(frm);
        /* XXXPMKID */
 
        return 0;
 }
 
 /*
- * WPA/802.11i assocation request processing.
+ * WPA/802.11i association request processing.
  */
 static int
 wpa_assocreq(struct ieee80211_node *ni, struct ieee80211_rsnparms *rsnparms,
@@ -1703,19 +1689,21 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
        efrm = mtod(m0, uint8_t *) + m0->m_len;
        switch (subtype) {
        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
-       case IEEE80211_FC0_SUBTYPE_BEACON: {
-               struct ieee80211_scanparams scan;
                /*
                 * We process beacon/probe response frames when scanning;
                 * otherwise we check beacon frames for overlapping non-ERP
                 * BSS in 11g and/or overlapping legacy BSS when in HT.
-                */ 
-               if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
-                   subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
+                */
+               if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
                        vap->iv_stats.is_rx_mgtdiscard++;
                        return;
                }
+               /* FALLTHROUGH */
+       case IEEE80211_FC0_SUBTYPE_BEACON: {
+               struct ieee80211_scanparams scan;
+
                /* NB: accept off-channel frames */
+               /* XXX TODO: use rxstatus to determine off-channel details */
                if (ieee80211_parse_beacon(ni, m0, ic->ic_curchan, &scan) &~ IEEE80211_BPARSE_OFFCHAN)
                        return;
                /*
@@ -2046,7 +2034,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                        return;
                /* discard challenge after association */
                if (ni->ni_challenge != NULL) {
-                       kfree(ni->ni_challenge, M_80211_NODE);
+                       IEEE80211_FREE(ni->ni_challenge, M_80211_NODE);
                        ni->ni_challenge = NULL;
                }
                /* NB: 802.11 spec says to ignore station's privacy bit */
@@ -2103,8 +2091,8 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                } else if (ni->ni_flags & IEEE80211_NODE_HT)
                        ieee80211_ht_node_cleanup(ni);
 #ifdef IEEE80211_SUPPORT_SUPERG
-               else if (ni->ni_ath_flags & IEEE80211_NODE_ATH)
-                       ieee80211_ff_node_cleanup(ni);
+               /* Always do ff node cleanup; for A-MSDU */
+               ieee80211_ff_node_cleanup(ni);
 #endif
                /*
                 * Allow AMPDU operation only with unencrypted traffic
@@ -2122,6 +2110,10 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                            "capinfo 0x%x ucastcipher %d", capinfo,
                            rsnparms.rsn_ucastcipher);
                        ieee80211_ht_node_cleanup(ni);
+#ifdef IEEE80211_SUPPORT_SUPERG
+                       /* Always do ff node cleanup; for A-MSDU */
+                       ieee80211_ff_node_cleanup(ni);
+#endif
                        vap->iv_stats.is_ht_assoc_downgrade++;
                }
                /*
@@ -2203,8 +2195,9 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
                        IEEE80211_NODE_STAT(ni, rx_disassoc);
                }
                IEEE80211_NOTE(vap, IEEE80211_MSG_AUTH, ni,
-                   "recv %s (reason %d)", ieee80211_mgt_subtype_name[subtype >>
-                       IEEE80211_FC0_SUBTYPE_SHIFT], reason);
+                   "recv %s (reason: %d (%s))",
+                   ieee80211_mgt_subtype_name(subtype),
+                   reason, ieee80211_reason_to_string(reason));
                if (ni != vap->iv_bss)
                        ieee80211_node_leave(ni);
                break;
@@ -2234,6 +2227,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
 
        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+       case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
        case IEEE80211_FC0_SUBTYPE_ATIM:
                IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
                    wh, NULL, "%s", "not handled");
@@ -2335,12 +2329,11 @@ ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
 
        /*
         * Do the right thing; if it's an encap'ed frame then
-        * call ieee80211_parent_xmitpkt() (and free the ref) else
+        * call ieee80211_parent_xmitpkt() else
         * call ieee80211_vap_xmitpkt().
         */
        if (m->m_flags & M_ENCAP) {
-               if (ieee80211_parent_xmitpkt(ic, m) != 0)
-                       ieee80211_free_node(ni);
+               (void) ieee80211_parent_xmitpkt(ic, m);
        } else {
                (void) ieee80211_vap_xmitpkt(vap, m);
        }
index af2a9f0..c3bb2f7 100644 (file)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/systm.h> 
 #include <sys/endian.h>
  
@@ -135,12 +136,10 @@ const struct ieee80211_mcs_rates ieee80211_htrates[IEEE80211_HTRATE_MAXSIZE] = {
        { 429, 477,  891,  990 },       /* MCS 76 */
 };
 
-#ifdef IEEE80211_AMPDU_AGE
 static int ieee80211_ampdu_age = -1;   /* threshold for ampdu reorder q (ms) */
 SYSCTL_PROC(_net_wlan, OID_AUTO, ampdu_age, CTLTYPE_INT | CTLFLAG_RW,
        &ieee80211_ampdu_age, 0, ieee80211_sysctl_msecs_ticks, "I",
        "AMPDU max reorder age (ms)");
-#endif
 
 static int ieee80211_recv_bar_ena = 1;
 SYSCTL_INT(_net_wlan, OID_AUTO, recv_bar, CTLFLAG_RW, &ieee80211_recv_bar_ena,
@@ -177,9 +176,7 @@ ieee80211_ht_init(void)
        /*
         * Setup HT parameters that depends on the clock frequency.
         */
-#ifdef IEEE80211_AMPDU_AGE
        ieee80211_ampdu_age = msecs_to_ticks(500);
-#endif
        ieee80211_addba_timeout = msecs_to_ticks(250);
        ieee80211_addba_backoff = msecs_to_ticks(10*1000);
        ieee80211_bar_timeout = msecs_to_ticks(250);
@@ -296,6 +293,11 @@ ieee80211_ht_vattach(struct ieee80211vap *vap)
                vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_RX;
                if (vap->iv_htcaps & IEEE80211_HTC_AMSDU)
                        vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_TX;
+
+               if (vap->iv_htcaps & IEEE80211_HTCAP_TXSTBC)
+                       vap->iv_flags_ht |= IEEE80211_FHT_STBC_TX;
+               if (vap->iv_htcaps & IEEE80211_HTCAP_RXSTBC)
+                       vap->iv_flags_ht |= IEEE80211_FHT_STBC_RX;
        }
        /* NB: disable default legacy WDS, too many issues right now */
        if (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)
@@ -557,6 +559,43 @@ ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap,
        return 0;
 }
 
+/*
+ * Public function; manually setup the RX ampdu state.
+ */
+int
+ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int baw)
+{
+       struct ieee80211_rx_ampdu *rap;
+
+       /* XXX TODO: sanity check tid, seq, baw */
+
+       rap = &ni->ni_rx_ampdu[tid];
+
+       if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) {
+               /*
+                * AMPDU previously setup and not terminated with a DELBA,
+                * flush the reorder q's in case anything remains.
+                */
+               ampdu_rx_purge(rap);
+       }
+
+       memset(rap, 0, sizeof(*rap));
+       rap->rxa_wnd = (baw== 0) ?
+           IEEE80211_AGGR_BAWMAX : min(baw, IEEE80211_AGGR_BAWMAX);
+       rap->rxa_start = seq;
+       rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
+
+       IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
+           "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x\n",
+           __func__,
+           tid,
+           seq,
+           rap->rxa_wnd,
+           rap->rxa_flags);
+
+       return 0;
+}
+
 /*
  * Stop A-MPDU rx processing for the specified TID.
  */
@@ -633,7 +672,6 @@ ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni)
        vap->iv_stats.is_ampdu_rx_oor += i;
 }
 
-#ifdef IEEE80211_AMPDU_AGE
 /*
  * Dispatch all frames in the A-MPDU re-order queue.
  */
@@ -658,7 +696,6 @@ ampdu_rx_flush(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
                        break;
        }
 }
-#endif /* IEEE80211_AMPDU_AGE */
 
 /*
  * Dispatch all frames in the A-MPDU re-order queue
@@ -826,7 +863,7 @@ again:
                 * Common case (hopefully): in the BA window.
                 * Sec 9.10.7.6.2 a) (p.137)
                 */
-#ifdef IEEE80211_AMPDU_AGE
+
                /* 
                 * Check for frames sitting too long in the reorder queue.
                 * This should only ever happen if frames are not delivered
@@ -865,7 +902,7 @@ again:
                         */
                        rap->rxa_age = ticks;
                }
-#endif /* IEEE80211_AMPDU_AGE */
+
                /* save packet */
                if (rap->rxa_m[off] == NULL) {
                        rap->rxa_m[off] = m;
@@ -1025,8 +1062,9 @@ ieee80211_ht_node_init(struct ieee80211_node *ni)
 
        IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
            ni,
-           "%s: called",
-           __func__);
+           "%s: called (%p)",
+           __func__,
+           ni);
 
        if (ni->ni_flags & IEEE80211_NODE_HT) {
                /*
@@ -1036,15 +1074,15 @@ ieee80211_ht_node_init(struct ieee80211_node *ni)
                 */
                IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
                    ni,
-                   "%s: calling cleanup",
-                   __func__);
+                   "%s: calling cleanup (%p)",
+                   __func__, ni);
                ieee80211_ht_node_cleanup(ni);
        }
        for (tid = 0; tid < WME_NUM_TID; tid++) {
                tap = &ni->ni_tx_ampdu[tid];
                tap->txa_tid = tid;
                tap->txa_ni = ni;
-               tap->txa_lastsample = ticks;
+               ieee80211_txampdu_init_pps(tap);
                /* NB: further initialization deferred */
        }
        ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
@@ -1062,8 +1100,8 @@ ieee80211_ht_node_cleanup(struct ieee80211_node *ni)
 
        IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
            ni,
-           "%s: called",
-           __func__);
+           "%s: called (%p)",
+           __func__, ni);
 
        KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT node"));
 
@@ -1086,14 +1124,11 @@ ieee80211_ht_node_cleanup(struct ieee80211_node *ni)
 void
 ieee80211_ht_node_age(struct ieee80211_node *ni)
 {
-#ifdef IEEE80211_AMPDU_AGE
        struct ieee80211vap *vap = ni->ni_vap;
        uint8_t tid;
-#endif
 
        KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
 
-#ifdef IEEE80211_AMPDU_AGE
        for (tid = 0; tid < WME_NUM_TID; tid++) {
                struct ieee80211_rx_ampdu *rap;
 
@@ -1116,7 +1151,6 @@ ieee80211_ht_node_age(struct ieee80211_node *ni)
                        ampdu_rx_flush(ni, rap);
                }
        }
-#endif /* IEEE80211_AMPDU_AGE */
 }
 
 static struct ieee80211_channel *
@@ -1214,7 +1248,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni)
        for (tid = 0; tid < WME_NUM_TID; tid++) {
                tap = &ni->ni_tx_ampdu[tid];
                tap->txa_tid = tid;
-               tap->txa_lastsample = ticks;
+               ieee80211_txampdu_init_pps(tap);
        }
        /* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */
        ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
@@ -1368,7 +1402,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");
@@ -1378,12 +1412,6 @@ ieee80211_ht_timeout(struct ieee80211com *ic)
        }
 }
 
-/* unalligned little endian access */     
-#define LE_READ_2(p)                                   \
-       ((uint16_t)                                     \
-        ((((const uint8_t *)(p))[0]      ) |           \
-         (((const uint8_t *)(p))[1] <<  8)))
-
 /*
  * Process an 802.11n HT capabilities ie.
  */
@@ -1401,7 +1429,7 @@ ieee80211_parse_htcap(struct ieee80211_node *ni, const uint8_t *ie)
        } else
                ni->ni_flags &= ~IEEE80211_NODE_HTCOMPAT;
 
-       ni->ni_htcap = LE_READ_2(ie +
+       ni->ni_htcap = le16dec(ie +
                __offsetof(struct ieee80211_ie_htcap, hc_cap));
        ni->ni_htparam = ie[__offsetof(struct ieee80211_ie_htcap, hc_param)];
 }
@@ -1414,9 +1442,9 @@ htinfo_parse(struct ieee80211_node *ni,
 
        ni->ni_htctlchan = htinfo->hi_ctrlchannel;
        ni->ni_ht2ndchan = SM(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN);
-       w = LE_READ_2(&htinfo->hi_byte2);
+       w = le16dec(&htinfo->hi_byte2);
        ni->ni_htopmode = SM(w, IEEE80211_HTINFO_OPMODE);
-       w = LE_READ_2(&htinfo->hi_byte45);
+       w = le16dec(&htinfo->hi_byte45);
        ni->ni_htstbc = SM(w, IEEE80211_HTINFO_BASIC_STBCMCS);
 }
 
@@ -1688,7 +1716,11 @@ ieee80211_setup_basic_htrates(struct ieee80211_node *ni, const uint8_t *ie)
 static void
 ampdu_tx_setup(struct ieee80211_tx_ampdu *tap)
 {
+#if defined(__DragonFly__)
        callout_init_mp(&tap->txa_timer);
+#else
+       callout_init(&tap->txa_timer, 1);
+#endif
        tap->txa_flags |= IEEE80211_AGGR_SETUP;
        tap->txa_lastsample = ticks;
 }
@@ -1721,8 +1753,7 @@ ampdu_tx_stop(struct ieee80211_tx_ampdu *tap)
        /*
         * Reset packet estimate.
         */
-       tap->txa_lastsample = ticks;
-       tap->txa_avgpps = 0;
+       ieee80211_txampdu_init_pps(tap);
 
        /* NB: clearing NAK means we may re-send ADDBA */ 
        tap->txa_flags &= ~(IEEE80211_AGGR_SETUP | IEEE80211_AGGR_NAK);
@@ -1795,6 +1826,55 @@ ieee80211_addba_request(struct ieee80211_node *ni,
        return 1;
 }
 
+/*
+ * Called by drivers that wish to request an ADDBA session be
+ * setup.  This brings it up and starts the request timer.
+ */
+int
+ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid)
+{
+       struct ieee80211_tx_ampdu *tap;
+
+       if (tid < 0 || tid > 15)
+               return (0);
+       tap = &ni->ni_tx_ampdu[tid];
+
+       /* XXX locking */
+       if ((tap->txa_flags & IEEE80211_AGGR_SETUP) == 0) {
+               /* do deferred setup of state */
+               ampdu_tx_setup(tap);
+       }
+       /* XXX hack for not doing proper locking */
+       tap->txa_flags &= ~IEEE80211_AGGR_NAK;
+       addba_start_timeout(tap);
+       return (1);
+}
+
+/*
+ * Called by drivers that have marked a session as active.
+ */
+int
+ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni, int tid,
+    int status)
+{
+       struct ieee80211_tx_ampdu *tap;
+
+       if (tid < 0 || tid > 15)
+               return (0);
+       tap = &ni->ni_tx_ampdu[tid];
+
+       /* XXX locking */
+       addba_stop_timeout(tap);
+       if (status == 1) {
+               tap->txa_flags |= IEEE80211_AGGR_RUNNING;
+               tap->txa_attempts = 0;
+       } else {
+               /* mark tid so we don't try again */
+               tap->txa_flags |= IEEE80211_AGGR_NAK;
+       }
+       return (1);
+}
+
 /*
  * Default method for processing an A-MPDU tx aggregation
  * response.  We shutdown any pending timer and update the
@@ -1861,9 +1941,9 @@ ht_recv_action_ba_addba_request(struct ieee80211_node *ni,
        int tid;
 
        dialogtoken = frm[2];
-       baparamset = LE_READ_2(frm+3);
-       batimeout = LE_READ_2(frm+5);
-       baseqctl = LE_READ_2(frm+7);
+       baparamset = le16dec(frm+3);
+       batimeout = le16dec(frm+5);
+       baseqctl = le16dec(frm+7);
 
        tid = MS(baparamset, IEEE80211_BAPS_TID);
 
@@ -1926,12 +2006,12 @@ ht_recv_action_ba_addba_response(struct ieee80211_node *ni,
        int tid, bufsiz;
 
        dialogtoken = frm[2];
-       code = LE_READ_2(frm+3);
-       baparamset = LE_READ_2(frm+5);
+       code = le16dec(frm+3);
+       baparamset = le16dec(frm+5);
        tid = MS(baparamset, IEEE80211_BAPS_TID);
        bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
        policy = MS(baparamset, IEEE80211_BAPS_POLICY);
-       batimeout = LE_READ_2(frm+7);
+       batimeout = le16dec(frm+7);
 
        tap = &ni->ni_tx_ampdu[tid];
        if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
@@ -1998,8 +2078,8 @@ ht_recv_action_ba_delba(struct ieee80211_node *ni,
        uint16_t baparamset, code;
        int tid;
 
-       baparamset = LE_READ_2(frm+2);
-       code = LE_READ_2(frm+4);
+       baparamset = le16dec(frm+2);
+       code = le16dec(frm+4);
 
        tid = MS(baparamset, IEEE80211_DELBAPS_TID);
 
@@ -2086,7 +2166,7 @@ ieee80211_ampdu_enable(struct ieee80211_node *ni,
                return 0;
        /* XXX check rssi? */
        if (tap->txa_attempts >= ieee80211_addba_maxtries &&
-           ticks < tap->txa_nextrequest) {
+           ieee80211_time_after(ticks, tap->txa_nextrequest)) {
                /*
                 * Don't retry too often; txa_nextrequest is set
                 * to the minimum interval we'll retry after
@@ -2095,9 +2175,9 @@ ieee80211_ampdu_enable(struct ieee80211_node *ni,
                return 0;
        }
        IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
-           "enable AMPDU on tid %d (%s), avgpps %d pkts %d",
+           "enable AMPDU on tid %d (%s), avgpps %d pkts %d attempt %d",
            tap->txa_tid, ieee80211_wme_acnames[TID_TO_WME_AC(tap->txa_tid)],
-           tap->txa_avgpps, tap->txa_pkts);
+           tap->txa_avgpps, tap->txa_pkts, tap->txa_attempts);
        return 1;
 }
 
@@ -2172,8 +2252,9 @@ ieee80211_ampdu_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
        tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
        if (IEEE80211_AMPDU_RUNNING(tap)) {
                IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
-                   ni, "%s: stop BA stream for TID %d (reason %d)",
-                   __func__, tap->txa_tid, reason);
+                   ni, "%s: stop BA stream for TID %d (reason: %d (%s))",
+                   __func__, tap->txa_tid, reason,
+                   ieee80211_reason_to_string(reason));
                vap->iv_stats.is_ampdu_stop++;
 
                ic->ic_addba_stop(ni, tap);
@@ -2184,8 +2265,9 @@ ieee80211_ampdu_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
                        IEEE80211_ACTION_BA_DELBA, args);
        } else {
                IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
-                   ni, "%s: BA stream for TID %d not running (reason %d)",
-                   __func__, tap->txa_tid, reason);
+                   ni, "%s: BA stream for TID %d not running "
+                   "(reason: %d (%s))", __func__, tap->txa_tid, reason,
+                   ieee80211_reason_to_string(reason));
                vap->iv_stats.is_ampdu_stop_failed++;
        }
 }
@@ -2220,7 +2302,7 @@ bar_timeout(void *arg)
                 * to make sure we notify the driver that a BAR
                 * TX did occur and fail.  This gives the driver
                 * a chance to undo any queue pause that may
-                * have occured.
+                * have occurred.
                 */
                ic->ic_bar_response(ni, tap, 1);
                ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
@@ -2513,8 +2595,8 @@ ht_send_action_ba_delba(struct ieee80211_node *ni,
                   | args[1]
                   ;
        IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
-           "send DELBA action: tid %d, initiator %d reason %d",
-           args[0], args[1], args[2]);
+           "send DELBA action: tid %d, initiator %d reason %d (%s)",
+           args[0], args[1], args[2], ieee80211_reason_to_string(args[2]));
 
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
            "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
@@ -2664,6 +2746,14 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
                rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU);
                density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
 
+               IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
+                   "%s: advertised rxmax=%d, density=%d, vap rxmax=%d, density=%d\n",
+                   __func__,
+                   rxmax,
+                   density,
+                   vap->iv_ampdu_rxmax,
+                   vap->iv_ampdu_density);
+
                /* Cap at VAP rxmax */
                if (rxmax > vap->iv_ampdu_rxmax)
                        rxmax = vap->iv_ampdu_rxmax;
@@ -2705,6 +2795,13 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
        if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 ||
            (caps & IEEE80211_HTCAP_CHWIDTH40) == 0)
                caps &= ~IEEE80211_HTCAP_SHORTGI40;
+
+       /* adjust STBC based on receive capabilities */
+       if ((vap->iv_flags_ht & IEEE80211_FHT_STBC_RX) == 0)
+               caps &= ~IEEE80211_HTCAP_RXSTBC;
+
+       /* XXX TODO: adjust LDPC based on receive capabilities */
+
        ADDSHORT(frm, caps);
 
        /* HT parameters */
index 8e09b9c..1cac766 100644 (file)
@@ -118,18 +118,6 @@ static void        hwmp_peerdown(struct ieee80211_node *);
 static struct timeval ieee80211_hwmp_preqminint = { 0, 100000 };
 static struct timeval ieee80211_hwmp_perrminint = { 0, 100000 };
 
-/* unalligned little endian access */
-#define LE_WRITE_2(p, v) do {                          \
-       ((uint8_t *)(p))[0] = (v) & 0xff;               \
-       ((uint8_t *)(p))[1] = ((v) >> 8) & 0xff;        \
-} while (0)
-#define LE_WRITE_4(p, v) do {                          \
-       ((uint8_t *)(p))[0] = (v) & 0xff;               \
-       ((uint8_t *)(p))[1] = ((v) >> 8) & 0xff;        \
-       ((uint8_t *)(p))[2] = ((v) >> 16) & 0xff;       \
-       ((uint8_t *)(p))[3] = ((v) >> 24) & 0xff;       \
-} while (0)
-
 
 /* NB: the Target Address set in a Proactive PREQ is the broadcast address. */
 static const uint8_t   broadcastaddr[IEEE80211_ADDR_LEN] =
@@ -268,14 +256,23 @@ hwmp_vattach(struct ieee80211vap *vap)
        KASSERT(vap->iv_opmode == IEEE80211_M_MBSS,
            ("not a mesh vap, opmode %d", vap->iv_opmode));
 
+#if defined(__DragonFly__)
        hs = kmalloc(sizeof(struct ieee80211_hwmp_state), M_80211_VAP,
-           M_INTWAIT | M_ZERO);
+               M_INTWAIT | M_ZERO);
+#else
+       hs = IEEE80211_MALLOC(sizeof(struct ieee80211_hwmp_state), M_80211_VAP,
+               IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (hs == NULL) {
                kprintf("%s: couldn't alloc HWMP state\n", __func__);
                return;
        }
        hs->hs_maxhops = IEEE80211_HWMP_DEFAULT_MAXHOPS;
+#if defined(__DragonFly__)
        callout_init_mp(&hs->hs_roottimer);
+#else
+       callout_init(&hs->hs_roottimer, 1);
+#endif
        vap->iv_hwmp = hs;
 }
 
@@ -285,7 +282,7 @@ hwmp_vdetach(struct ieee80211vap *vap)
        struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 
        callout_drain(&hs->hs_roottimer);
-       kfree(vap->iv_hwmp, M_80211_VAP);
+       IEEE80211_FREE(vap->iv_hwmp, M_80211_VAP);
        vap->iv_hwmp = NULL;
 } 
 
@@ -429,9 +426,16 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                vap->iv_stats.is_rx_mgtdiscard++;
                                break;
                        }
+#if defined(__DragonFly__)
                        preq = kmalloc(sizeof(*preq) +
                            (ndest - 1) * sizeof(*preq->preq_targets),
                            M_80211_MESH_PREQ, M_INTWAIT | M_ZERO);
+#else
+                       preq = IEEE80211_MALLOC(sizeof(*preq) +
+                           (ndest - 1) * sizeof(*preq->preq_targets),
+                           M_80211_MESH_PREQ,
+                           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                        KASSERT(preq != NULL, ("preq == NULL"));
 
                        preq->preq_ie = *iefrm_t++;
@@ -439,18 +443,18 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                        preq->preq_flags = *iefrm_t++;
                        preq->preq_hopcount = *iefrm_t++;
                        preq->preq_ttl = *iefrm_t++;
-                       preq->preq_id = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       preq->preq_id = le32dec(iefrm_t); iefrm_t += 4;
                        IEEE80211_ADDR_COPY(preq->preq_origaddr, iefrm_t);
                        iefrm_t += 6;
-                       preq->preq_origseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       preq->preq_origseq = le32dec(iefrm_t); iefrm_t += 4;
                        /* NB: may have Originator Proxied Address */
                        if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE)  {
                                IEEE80211_ADDR_COPY(
                                    preq->preq_orig_ext_addr, iefrm_t);
                                iefrm_t += 6;
                        }
-                       preq->preq_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4;
-                       preq->preq_metric = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       preq->preq_lifetime = le32dec(iefrm_t); iefrm_t += 4;
+                       preq->preq_metric = le32dec(iefrm_t); iefrm_t += 4;
                        preq->preq_tcount = *iefrm_t++;
 
                        for (i = 0; i < preq->preq_tcount; i++) {
@@ -459,12 +463,12 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                    preq->preq_targets[i].target_addr, iefrm_t);
                                iefrm_t += 6;
                                preq->preq_targets[i].target_seq =
-                                   LE_READ_4(iefrm_t);
+                                   le32dec(iefrm_t);
                                iefrm_t += 4;
                        }
 
                        hwmp_recv_preq(vap, ni, wh, preq);
-                       kfree(preq, M_80211_MESH_PREQ);
+                       IEEE80211_FREE(preq, M_80211_MESH_PREQ);
                        found++;
                        break;
                }
@@ -476,8 +480,14 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                vap->iv_stats.is_rx_mgtdiscard++;
                                break;
                        }
+#if defined(__DragonFly__)
                        prep = kmalloc(sizeof(*prep),
                            M_80211_MESH_PREP, M_INTWAIT | M_ZERO);
+#else
+                       prep = IEEE80211_MALLOC(sizeof(*prep),
+                           M_80211_MESH_PREP,
+                           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                        KASSERT(prep != NULL, ("prep == NULL"));
 
                        prep->prep_ie = *iefrm_t++;
@@ -487,21 +497,21 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                        prep->prep_ttl = *iefrm_t++;
                        IEEE80211_ADDR_COPY(prep->prep_targetaddr, iefrm_t);
                        iefrm_t += 6;
-                       prep->prep_targetseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       prep->prep_targetseq = le32dec(iefrm_t); iefrm_t += 4;
                        /* NB: May have Target Proxied Address */
                        if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE)  {
                                IEEE80211_ADDR_COPY(
                                    prep->prep_target_ext_addr, iefrm_t);
                                iefrm_t += 6;
                        }
-                       prep->prep_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4;
-                       prep->prep_metric = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       prep->prep_lifetime = le32dec(iefrm_t); iefrm_t += 4;
+                       prep->prep_metric = le32dec(iefrm_t); iefrm_t += 4;
                        IEEE80211_ADDR_COPY(prep->prep_origaddr, iefrm_t);
                        iefrm_t += 6;
-                       prep->prep_origseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+                       prep->prep_origseq = le32dec(iefrm_t); iefrm_t += 4;
 
                        hwmp_recv_prep(vap, ni, wh, prep);
-                       kfree(prep, M_80211_MESH_PREP);
+                       IEEE80211_FREE(prep, M_80211_MESH_PREP);
                        found++;
                        break;
                }
@@ -515,9 +525,16 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                vap->iv_stats.is_rx_mgtdiscard++;
                                break;
                        }
+#if defined(__DragonFly__)
                        perr = kmalloc(sizeof(*perr) +
                            (ndest - 1) * sizeof(*perr->perr_dests),
                            M_80211_MESH_PERR, M_INTWAIT | M_ZERO);
+#else
+                       perr = IEEE80211_MALLOC(sizeof(*perr) +
+                           (ndest - 1) * sizeof(*perr->perr_dests),
+                           M_80211_MESH_PERR,
+                           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                        KASSERT(perr != NULL, ("perr == NULL"));
 
                        perr->perr_ie = *iefrm_t++;
@@ -530,7 +547,7 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                IEEE80211_ADDR_COPY(
                                    perr->perr_dests[i].dest_addr, iefrm_t);
                                iefrm_t += 6;
-                               perr->perr_dests[i].dest_seq = LE_READ_4(iefrm_t);
+                               perr->perr_dests[i].dest_seq = le32dec(iefrm_t);
                                iefrm_t += 4;
                                /* NB: May have Target Proxied Address */
                                if (perr->perr_dests[i].dest_flags &
@@ -541,12 +558,12 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                        iefrm_t += 6;
                                }
                                perr->perr_dests[i].dest_rcode =
-                                   LE_READ_2(iefrm_t);
+                                   le16dec(iefrm_t);
                                iefrm_t += 2;
                        }
 
                        hwmp_recv_perr(vap, ni, wh, perr);
-                       kfree(perr, M_80211_MESH_PERR);
+                       IEEE80211_FREE(perr, M_80211_MESH_PERR);
                        found++;
                        break;
                }
@@ -563,9 +580,9 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
                                return 1;
                        }
                        memcpy(&rann, mrann, sizeof(rann));
-                       rann.rann_seq = LE_READ_4(&mrann->rann_seq);
-                       rann.rann_interval = LE_READ_4(&mrann->rann_interval);
-                       rann.rann_metric = LE_READ_4(&mrann->rann_metric);
+                       rann.rann_seq = le32dec(&mrann->rann_seq);
+                       rann.rann_interval = le32dec(&mrann->rann_interval);
+                       rann.rann_metric = le32dec(&mrann->rann_metric);
                        hwmp_recv_rann(vap, ni, wh, &rann);
                        found++;
                        break;
@@ -679,12 +696,11 @@ hwmp_send_action(struct ieee80211vap *vap,
 }
 
 #define ADDSHORT(frm, v) do {          \
-       frm[0] = (v) & 0xff;            \
-       frm[1] = (v) >> 8;              \
+       le16enc(frm, v);                \
        frm += 2;                       \
 } while (0)
 #define ADDWORD(frm, v) do {           \
-       LE_WRITE_4(frm, v);             \
+       le32enc(frm, v);                \
        frm += 4;                       \
 } while (0)
 /*
@@ -917,9 +933,15 @@ hwmp_update_transmitter(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (rttran == NULL) {
                rttran = ieee80211_mesh_rt_add(vap, ni->ni_macaddr);
                if (rttran == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "unable to add path to transmitter %s of %s",
                            ether_sprintf(ni->ni_macaddr), hwmp_frame);
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "unable to add path to transmitter %6D of %s",
+                           ni->ni_macaddr, ":", hwmp_frame);
+#endif
                        vap->iv_stats.is_mesh_rtaddfailed++;
                        return;
                }
@@ -928,12 +950,20 @@ hwmp_update_transmitter(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (!(rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) ||
            rttran->rt_metric > metric)
        {
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "%s path to transmitter %s of %s, metric %d:%d",
                    rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
                    "prefer" : "update", ether_sprintf(ni->ni_macaddr),
                    hwmp_frame,
                    rttran->rt_metric, metric);
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "%s path to transmiter %6D of %s, metric %d:%d",
+                   rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+                   "prefer" : "update", ni->ni_macaddr, ":", hwmp_frame,
+                   rttran->rt_metric, metric);
+#endif
                IEEE80211_ADDR_COPY(rttran->rt_nexthop, ni->ni_macaddr);
                rttran->rt_metric = metric;
                rttran->rt_nhops  = 1;
@@ -967,10 +997,16 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (IEEE80211_ADDR_EQ(vap->iv_myaddr, preq->preq_origaddr))
                return;
 
+#if defined(__DragonFly__)
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
            "received PREQ, orig %s, targ(0) %s",
            ether_sprintf(preq->preq_origaddr),
            ether_sprintf(PREQ_TADDR(0)));
+#else
+       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+       "received PREQ, orig %6D, targ(0) %6D", preq->preq_origaddr, ":",
+       PREQ_TADDR(0), ":");
+#endif
 
        /*
         * Acceptance criteria: (if the PREQ is not for us or not broadcast,
@@ -999,10 +1035,17 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if(preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AM &&
            rttarg == NULL &&
            !IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
+#if defined(__DragonFly__)
                IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
                    preq->preq_origaddr, NULL,
                    "unicast addressed PREQ of unknown target %s",
                    ether_sprintf(PREQ_TADDR(0)));
+#else
+               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+                   preq->preq_origaddr, NULL,
+                   "unicast addressed PREQ of unknown target %6D",
+                   PREQ_TADDR(0), ":");
+#endif
                return;
        }
 
@@ -1012,15 +1055,26 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (rtorig == NULL) {
                rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
                if (rtorig == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "unable to add orig path to %s",
                            ether_sprintf(preq->preq_origaddr));
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                       "unable to add orig path to %6D",
+                       preq->preq_origaddr, ":");
+#endif
                        vap->iv_stats.is_mesh_rtaddfailed++;
                        return;
                }
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "adding originator %s",
                    ether_sprintf(preq->preq_origaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "adding originator %6D", preq->preq_origaddr, ":");
+#endif
        }
        hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
 
@@ -1049,12 +1103,21 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
            !HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0))) ||
            (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID &&
            preqid >= preq->preq_id)) {
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "discard PREQ from %s, old seqno %u <= %u,"
                    " or old preqid %u < %u",
                    ether_sprintf(preq->preq_origaddr),
                    preq->preq_origseq, hrorig->hr_seq,
                    preq->preq_id, preqid);
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "discard PREQ from %6D, old seqno %u <= %u,"
+                   " or old preqid %u < %u",
+                   preq->preq_origaddr, ":",
+                   preq->preq_origseq, hrorig->hr_seq,
+                   preq->preq_id, preqid);
+#endif
                return;
        }
 
@@ -1083,9 +1146,14 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
                IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
                if (rttarg != NULL && /* if NULL it means we are the target */
                    rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "reply for proxy %s",
                            ether_sprintf(rttarg->rt_dest));
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "reply for proxy %6D", rttarg->rt_dest, ":");
+#endif
                        prep.prep_flags |= IEEE80211_MESHPREP_FLAGS_AE;
                        IEEE80211_ADDR_COPY(prep.prep_target_ext_addr,
                            rttarg->rt_dest);
@@ -1104,8 +1172,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
                IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr);
                prep.prep_origseq = preq->preq_origseq;
 
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "reply to %s", ether_sprintf(preq->preq_origaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+               "reply to %6D", preq->preq_origaddr, ":");
+#endif
                hwmp_send_prep(vap, wh->i_addr2, &prep);
                return;
        }
@@ -1117,9 +1190,15 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
                        rtorig_ext = ieee80211_mesh_rt_add(vap,
                            preq->preq_orig_ext_addr);
                        if (rtorig_ext == NULL) {
+#if defined(__DragonFly__)
                                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                                    "unable to add orig ext proxy to %s",
                                    ether_sprintf(preq->preq_orig_ext_addr));
+#else
+                               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                                   "unable to add orig ext proxy to %6D",
+                                   preq->preq_orig_ext_addr, ":");
+#endif
                                vap->iv_stats.is_mesh_rtaddfailed++;
                                return;
                        }
@@ -1135,9 +1214,14 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
         */
        if (IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr) &&
            (PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO)) {
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "root mesh station @ %s",
                    ether_sprintf(preq->preq_origaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "root mesh station @ %6D", preq->preq_origaddr, ":");
+#endif
 
                /* Check if root is a mesh gate, mark it */
                if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_GATE) {
@@ -1195,9 +1279,15 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
                            !IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr)) {
                                struct ieee80211_meshprep_ie prep;
 
+#if defined(__DragonFly__)
                                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                                    "intermediate reply for PREQ from %s",
                                    ether_sprintf(preq->preq_origaddr));
+#else
+                               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                                   "intermediate reply for PREQ from %6D",
+                                   preq->preq_origaddr, ":");
+#endif
                                prep.prep_flags = 0;
                                prep.prep_hopcount = rttarg->rt_nhops;
                                prep.prep_ttl = ms->ms_ttl;
@@ -1220,9 +1310,15 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
                        }
                }
 
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "forward PREQ from %s",
                    ether_sprintf(preq->preq_origaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "forward PREQ from %6D",
+                   preq->preq_origaddr, ":");
+#endif
                ppreq.preq_hopcount += 1;
                ppreq.preq_ttl -= 1;
                ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
@@ -1286,10 +1382,16 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
        uint32_t metric = 0;
        const uint8_t *addr;
 
+#if defined(__DragonFly__)
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
            "received PREP, orig %s, targ %s",
            ether_sprintf(prep->prep_origaddr),
            ether_sprintf(prep->prep_targetaddr));
+#else
+       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+           "received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":",
+           prep->prep_targetaddr, ":");
+#endif
 
        /*
         * Acceptance criteria: (If the corresponding PREP was not generated
@@ -1300,9 +1402,15 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) ||
            (rtorig != NULL && IS_PROXY(rtorig) && !PROXIED_BY_US(rtorig))) &&
            !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)){
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "discard PREP, orig(%s) not proxied or generated by us",
                    ether_sprintf(prep->prep_origaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "discard PREP, orig(%6D) not proxied or generated by us",
+                   prep->prep_origaddr, ":");
+#endif
                return;
        }
 
@@ -1319,35 +1427,61 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (rt == NULL) {
                rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
                if (rt == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "unable to add PREP path to %s",
                            ether_sprintf(prep->prep_targetaddr));
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "unable to add PREP path to %6D",
+                           prep->prep_targetaddr, ":");
+#endif
                        vap->iv_stats.is_mesh_rtaddfailed++;
                        return;
                }
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "adding target %s", ether_sprintf(prep->prep_targetaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "adding target %6D", prep->prep_targetaddr, ":");
+#endif
        }
        hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
        /* update path metric */
        metric = prep->prep_metric + ms->ms_pmetric->mpm_metric(ni);
        if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
                if (HWMP_SEQ_LT(prep->prep_targetseq, hr->hr_seq)) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "discard PREP from %s, old seq no %u < %u",
                            ether_sprintf(prep->prep_targetaddr),
                            prep->prep_targetseq, hr->hr_seq);
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "discard PREP from %6D, old seq no %u < %u",
+                           prep->prep_targetaddr, ":",
+                           prep->prep_targetseq, hr->hr_seq);
+#endif
                        return;
                } else if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
                    metric > rt->rt_metric) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "discard PREP from %s, new metric %u > %u",
                            ether_sprintf(prep->prep_targetaddr),
                            metric, rt->rt_metric);
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "discard PREP from %6D, new metric %u > %u",
+                           prep->prep_targetaddr, ":",
+                           metric, rt->rt_metric);
+#endif
                        return;
                }
        }
 
+#if defined(__DragonFly__)
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
            "%s path to %s, hopcount %d:%d metric %d:%d",
            rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
@@ -1355,6 +1489,15 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
            ether_sprintf(prep->prep_targetaddr),
            rt->rt_nhops, prep->prep_hopcount + 1,
            rt->rt_metric, metric);
+#else
+       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+           "%s path to %6D, hopcount %d:%d metric %d:%d",
+           rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+           "prefer" : "update",
+           prep->prep_targetaddr, ":",
+           rt->rt_nhops, prep->prep_hopcount + 1,
+           rt->rt_metric, metric);
+#endif
 
        hr->hr_seq = prep->prep_targetseq;
        hr->hr_preqretries = 0;
@@ -1385,15 +1528,27 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
                 * XXX: for now just ignore.
                 */
                if (rtorig == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                            "received PREP for an unknown orig(%s)",
                            ether_sprintf(prep->prep_origaddr));
+#else
+                       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                           "received PREP for an unknown orig(%6D)",
+                           prep->prep_origaddr, ":");
+#endif
                        return;
                }
 
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "propagate PREP from %s",
                    ether_sprintf(prep->prep_targetaddr));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "propagate PREP from %6D",
+                   prep->prep_targetaddr, ":");
+#endif
 
                memcpy(&pprep, prep, sizeof(pprep));
                pprep.prep_hopcount += 1;
@@ -1416,13 +1571,20 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
                        rtext = ieee80211_mesh_rt_add(vap,
                                prep->prep_target_ext_addr);
                        if (rtext == NULL) {
+#if defined(__DragonFly__)
                                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                                    "unable to add PREP path to proxy %s",
                                    ether_sprintf(prep->prep_targetaddr));
+#else
+                               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                                   "unable to add PREP path to proxy %6D",
+                                   prep->prep_targetaddr, ":");
+#endif
                                vap->iv_stats.is_mesh_rtaddfailed++;
                                return;
                        }
                }
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "%s path to %s, hopcount %d:%d metric %d:%d",
                    rtext->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
@@ -1430,6 +1592,15 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
                    ether_sprintf(prep->prep_target_ext_addr),
                    rtext->rt_nhops, prep->prep_hopcount + 1,
                    rtext->rt_metric, metric);
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "%s path to %6D, hopcount %d:%d metric %d:%d",
+                   rtext->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
+                   "prefer" : "update",
+                   prep->prep_target_ext_addr, ":",
+                   rtext->rt_nhops, prep->prep_hopcount + 1,
+                   rtext->rt_metric, metric);
+#endif
 
                rtext->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY |
                        IEEE80211_MESHRT_FLAGS_VALID;
@@ -1554,16 +1725,26 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
        struct ieee80211_meshperr_ie *pperr = NULL;
        int i, j = 0, forward = 0;
 
+#if defined(__DragonFly__)
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
            "received PERR from %s", ether_sprintf(wh->i_addr2));
+#else
+       IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+           "received PERR from %6D", wh->i_addr2, ":");
+#endif
 
        /*
         * if forwarding is true, prepare pperr
         */
        if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) {
                forward = 1;
+#if defined(__DragonFly__)
                pperr = kmalloc(sizeof(*perr) + 31*sizeof(*perr->perr_dests),
                    M_80211_MESH_PERR, M_INTWAIT); /* XXX: magic number, 32 err dests */
+#else
+               pperr = IEEE80211_MALLOC(sizeof(*perr) + 31*sizeof(*perr->perr_dests),
+                   M_80211_MESH_PERR, IEEE80211_M_NOWAIT); /* XXX: magic number, 32 err dests */
+#endif
        }
 
        /*
@@ -1630,15 +1811,20 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
         * Propagate the PERR if we previously found it on our routing table.
         */
        if (forward && perr->perr_ttl > 1) {
+#if defined(__DragonFly__)
                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
                    "propagate PERR from %s", ether_sprintf(wh->i_addr2));
+#else
+               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+                   "propagate PERR from %6D", wh->i_addr2, ":");
+#endif
                pperr->perr_ndests = j;
                pperr->perr_ttl--;
                hwmp_send_perr(vap, broadcastaddr, pperr);
        }
 done:
        if (pperr != NULL)
-               kfree(pperr, M_80211_MESH_PERR);
+               IEEE80211_FREE(pperr, M_80211_MESH_PERR);
 }
 #undef PERR_DFLAGS
 #undef PERR_DADDR
@@ -1787,9 +1973,15 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
        if (rt == NULL) {
                rt = ieee80211_mesh_rt_add(vap, rann->rann_addr);
                if (rt == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
                            "unable to add mac for RANN root %s",
                            ether_sprintf(rann->rann_addr));
+#else
+                       IEEE80211_DISCARD(vap, IEEE80211_MSG_HWMP, wh, NULL,
+                           "unable to add mac for RANN root %6D",
+                           rann->rann_addr, ":");
+#endif
                            vap->iv_stats.is_mesh_rtaddfailed++;
                        return;
                }
@@ -1940,9 +2132,15 @@ hwmp_discover(struct ieee80211vap *vap,
                if (rt == NULL) {
                        rt = ieee80211_mesh_rt_add(vap, dest);
                        if (rt == NULL) {
+#if defined(__DragonFly__)
                                IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
                                    ni, "unable to add discovery path to %s",
                                    ether_sprintf(dest));
+#else
+                               IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
+                                   ni, "unable to add discovery path to %6D",
+                                   dest, ":");
+#endif
                                vap->iv_stats.is_mesh_rtaddfailed++;
                                goto done;
                        }
index fcd10d7..4e88dd9 100644 (file)
@@ -43,7 +43,11 @@ __FBSDID("$FreeBSD$");
 #include <net/if_var.h>
 #include <net/if_llc.h>
 #include <net/if_media.h>
+#if defined(__DragonFly__)
 #include <net/vlan/if_vlan_var.h>
+#else
+#include <net/if_vlan_var.h>
+#endif
 
 #include <netproto/802_11/ieee80211_var.h>
 #include <netproto/802_11/ieee80211_input.h>
@@ -86,10 +90,21 @@ int
 ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m,
     struct ieee80211_rx_stats *rx)
 {
+       struct ieee80211_rx_stats rxs;
+
+       if (rx) {
+               memcpy(&rxs, rx, sizeof(*rx));
+       } else {
+               /* try to read from mbuf */
+               bzero(&rxs, sizeof(rxs));
+               ieee80211_get_rx_params(m, &rxs);
+       }
+
        /* XXX should assert IEEE80211_R_NF and IEEE80211_R_RSSI are set */
-       ieee80211_process_mimo(ni, rx);
+       ieee80211_process_mimo(ni, &rxs);
+
        //return ieee80211_input(ni, m, rx->rssi, rx->nf);
-       return ni->ni_vap->iv_input(ni, m, rx, rx->rssi, rx->nf);
+       return ni->ni_vap->iv_input(ni, m, &rxs, rxs.rssi, rxs.nf);
 }
 
 int
@@ -107,11 +122,20 @@ int
 ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m,
     struct ieee80211_rx_stats *rx)
 {
+       struct ieee80211_rx_stats rxs;
        struct ieee80211vap *vap;
        int type = -1;
 
        m->m_flags |= M_BCAST;          /* NB: mark for bpf tap'ing */
 
+       if (rx) {
+               memcpy(&rxs, rx, sizeof(*rx));
+       } else {
+               /* try to read from mbuf */
+               bzero(&rxs, sizeof(rxs));
+               ieee80211_get_rx_params(m, &rxs);
+       }
+
        /* XXX locking */
        TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
                struct ieee80211_node *ni;
@@ -143,7 +167,7 @@ ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m,
                        m = NULL;
                }
                ni = ieee80211_ref_node(vap->iv_bss);
-               type = ieee80211_input_mimo(ni, mcopy, rx);
+               type = ieee80211_input_mimo(ni, mcopy, &rxs);
                ieee80211_free_node(ni);
        }
        if (m != NULL)                  /* no vaps, reclaim mbuf */
@@ -229,9 +253,13 @@ ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace)
                mfrag = m;
        } else {                                /* concatenate */
                m_adj(m, hdrspace);             /* strip header */
+#if defined(__DragonFly__)
                m_cat(mfrag, m);
                /* NB: m_cat doesn't update the packet header */
                mfrag->m_pkthdr.len += m->m_pkthdr.len;
+#else
+               m_catpkt(mfrag, m);
+#endif
                /* track last seqnum and fragno */
                lwh = mtod(mfrag, struct ieee80211_frame *);
                *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
@@ -253,7 +281,8 @@ ieee80211_deliver_data(struct ieee80211vap *vap,
 
        /* clear driver/net80211 flags before passing up */
        m->m_flags &= ~(M_MCAST | M_BCAST);
-#if !defined(__DragonFly__)
+#if defined(__DragonFly__)
+#else
        m_clrprotoflags(m);
 #endif
 
@@ -262,7 +291,7 @@ ieee80211_deliver_data(struct ieee80211vap *vap,
        /*
         * Do accounting.
         */
-       IFNET_STAT_INC(ifp, ipackets, 1);
+       if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
        IEEE80211_NODE_STAT(ni, rx_data);
        IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
@@ -281,7 +310,11 @@ ieee80211_deliver_data(struct ieee80211vap *vap,
 #endif
                m->m_flags |= M_VLANTAG;
        }
+#if defined(__DragonFly__)
        ifp->if_input(ifp, m, NULL, -1);
+#else
+       ifp->if_input(ifp, m);
+#endif
 }
 
 struct mbuf *
@@ -453,8 +486,14 @@ int
 ieee80211_alloc_challenge(struct ieee80211_node *ni)
 {
        if (ni->ni_challenge == NULL)
+#if defined(__DragonFly__)
                ni->ni_challenge = (uint32_t *) kmalloc(IEEE80211_CHALLENGE_LEN,
                    M_80211_NODE, M_INTWAIT);
+#else
+               ni->ni_challenge = (uint32_t *)
+                   IEEE80211_MALLOC(IEEE80211_CHALLENGE_LEN,
+                       M_80211_NODE, IEEE80211_M_NOWAIT);
+#endif
        if (ni->ni_challenge == NULL) {
                IEEE80211_NOTE(ni->ni_vap,
                    IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,
@@ -536,7 +575,7 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
                        break;
                case IEEE80211_ELEMID_FHPARMS:
                        if (ic->ic_phytype == IEEE80211_T_FH) {
-                               scan->fhdwell = LE_READ_2(&frm[2]);
+                               scan->fhdwell = le16dec(&frm[2]);
                                scan->chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
                                scan->fhindex = frm[6];
                        }
@@ -557,6 +596,8 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
                case IEEE80211_ELEMID_IBSSPARMS:
                case IEEE80211_ELEMID_CFPARMS:
                case IEEE80211_ELEMID_PWRCNSTR:
+               case IEEE80211_ELEMID_BSSLOAD:
+               case IEEE80211_ELEMID_APCHANREP:
                        /* NB: avoid debugging complaints */
                        break;
                case IEEE80211_ELEMID_XRATES:
@@ -589,6 +630,9 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
                        scan->meshconf = frm;
                        break;
 #endif
+               /* Extended capabilities; nothing handles it for now */
+               case IEEE80211_ELEMID_EXTCAP:
+                       break;
                case IEEE80211_ELEMID_VENDOR:
                        if (iswpaoui(frm))
                                scan->wpa = frm;
@@ -865,11 +909,19 @@ void
 ieee80211_note(const struct ieee80211vap *vap, const char *fmt, ...)
 {
        char buf[128];          /* XXX */
+#if defined(__DragonFly__)
        osdep_va_list ap;
 
        osdep_va_start(ap, fmt);
        kvsnprintf(buf, sizeof(buf), fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+#endif
 
        if_printf(vap->iv_ifp, "%s", buf);      /* NB: no \n */
 }
@@ -880,11 +932,19 @@ ieee80211_note_frame(const struct ieee80211vap *vap,
        const char *fmt, ...)
 {
        char buf[128];          /* XXX */
+#if defined(__DragonFly__)
        osdep_va_list ap;
 
        osdep_va_start(ap, fmt);
        kvsnprintf(buf, sizeof(buf), fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+#endif
        if_printf(vap->iv_ifp, "[%s] %s\n",
                ether_sprintf(ieee80211_getbssid(vap, wh)), buf);
 }
@@ -895,11 +955,19 @@ ieee80211_note_mac(const struct ieee80211vap *vap,
        const char *fmt, ...)
 {
        char buf[128];          /* XXX */
+#if defined(__DragonFly__)
        osdep_va_list ap;
 
        osdep_va_start(ap, fmt);
        kvsnprintf(buf, sizeof(buf), fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+#endif
        if_printf(vap->iv_ifp, "[%s] %s\n", ether_sprintf(mac), buf);
 }
 
@@ -908,19 +976,27 @@ ieee80211_discard_frame(const struct ieee80211vap *vap,
        const struct ieee80211_frame *wh,
        const char *type, const char *fmt, ...)
 {
+#if defined(__DragonFly__)
        osdep_va_list ap;
 
        if_printf(vap->iv_ifp, "[%s] discard ",
                ether_sprintf(ieee80211_getbssid(vap, wh)));
-       if (type == NULL) {
-               kprintf("%s frame, ", ieee80211_mgt_subtype_name[
-                       (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
-                       IEEE80211_FC0_SUBTYPE_SHIFT]);
-       } else
-               kprintf("%s frame, ", type);
+       kprintf("%s frame, ", type != NULL ? type :
+           ieee80211_mgt_subtype_name(wh->i_fc[0]));
        osdep_va_start(ap, fmt);
        kvprintf(fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+
+       if_printf(vap->iv_ifp, "[%s] discard ",
+               ether_sprintf(ieee80211_getbssid(vap, wh)));
+       printf("%s frame, ", type != NULL ? type :
+           ieee80211_mgt_subtype_name(wh->i_fc[0]));
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+#endif
        kprintf("\n");
 }
 
@@ -931,6 +1007,7 @@ ieee80211_discard_ie(const struct ieee80211vap *vap,
 {
        osdep_va_list ap;
 
+#if defined(__DragonFly__)
        if_printf(vap->iv_ifp, "[%s] discard ",
                ether_sprintf(ieee80211_getbssid(vap, wh)));
        if (type != NULL)
@@ -941,6 +1018,18 @@ ieee80211_discard_ie(const struct ieee80211vap *vap,
        kvprintf(fmt, ap);
        osdep_va_end(ap);
        kprintf("\n");
+#else
+       if_printf(vap->iv_ifp, "[%s] discard ",
+               ether_sprintf(ieee80211_getbssid(vap, wh)));
+       if (type != NULL)
+               printf("%s information element, ", type);
+       else
+               printf("information element, ");
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+       printf("\n");
+#endif
 }
 
 void
@@ -948,6 +1037,7 @@ ieee80211_discard_mac(const struct ieee80211vap *vap,
        const uint8_t mac[IEEE80211_ADDR_LEN],
        const char *type, const char *fmt, ...)
 {
+#if defined(__DragonFly__)
        osdep_va_list ap;
 
        if_printf(vap->iv_ifp, "[%s] discard ", ether_sprintf(mac));
@@ -958,6 +1048,18 @@ ieee80211_discard_mac(const struct ieee80211vap *vap,
        osdep_va_start(ap, fmt);
        kvprintf(fmt, ap);
        osdep_va_end(ap);
+#else
+       va_list ap;
+
+       if_printf(vap->iv_ifp, "[%s] discard ", ether_sprintf(mac));
+       if (type != NULL)
+               printf("%s frame, ", type);
+       else
+               printf("frame, ");
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+#endif
        kprintf("\n");
 }
 #endif /* IEEE80211_DEBUG */
index 3022a65..359d5e7 100644 (file)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/endian.h>
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -68,7 +69,7 @@ static struct ieee80211_channel *findchannel(struct ieee80211com *,
 static int ieee80211_scanreq(struct ieee80211vap *,
                struct ieee80211_scan_req *);
 
-static __noinline int
+static int
 ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -124,7 +125,7 @@ ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return copyout(&ik, ireq->i_data, sizeof(ik));
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -134,7 +135,7 @@ ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -148,36 +149,44 @@ ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return copyout(&ic->ic_nchans, ireq->i_data, space);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getwpaie(struct ieee80211vap *vap,
        struct ieee80211req *ireq, int req)
 {
        struct ieee80211_node *ni;
-       struct ieee80211req_wpaie2 wpaie;
+       struct ieee80211req_wpaie2 *wpaie;
        int error;
 
        if (ireq->i_len < IEEE80211_ADDR_LEN)
                return EINVAL;
-       error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
+#if defined(__DragonFly__)
+       wpaie = kmalloc(sizeof(*wpaie), M_TEMP, M_INTWAIT | M_ZERO);
+#else
+       wpaie = IEEE80211_MALLOC(sizeof(*wpaie), M_TEMP,
+           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
+       if (wpaie == NULL)
+               return ENOMEM;
+       error = copyin(ireq->i_data, wpaie->wpa_macaddr, IEEE80211_ADDR_LEN);
        if (error != 0)
-               return error;
-       ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr);
-       if (ni == NULL)
-               return ENOENT;
-       memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
+               goto bad;
+       ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie->wpa_macaddr);
+       if (ni == NULL) {
+               error = ENOENT;
+               goto bad;
+       }
        if (ni->ni_ies.wpa_ie != NULL) {
                int ielen = ni->ni_ies.wpa_ie[1] + 2;
-               if (ielen > sizeof(wpaie.wpa_ie))
-                       ielen = sizeof(wpaie.wpa_ie);
-               memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen);
+               if (ielen > sizeof(wpaie->wpa_ie))
+                       ielen = sizeof(wpaie->wpa_ie);
+               memcpy(wpaie->wpa_ie, ni->ni_ies.wpa_ie, ielen);
        }
        if (req == IEEE80211_IOC_WPAIE2) {
-               memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
                if (ni->ni_ies.rsn_ie != NULL) {
                        int ielen = ni->ni_ies.rsn_ie[1] + 2;
-                       if (ielen > sizeof(wpaie.rsn_ie))
-                               ielen = sizeof(wpaie.rsn_ie);
-                       memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen);
+                       if (ielen > sizeof(wpaie->rsn_ie))
+                               ielen = sizeof(wpaie->rsn_ie);
+                       memcpy(wpaie->rsn_ie, ni->ni_ies.rsn_ie, ielen);
                }
                if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
                        ireq->i_len = sizeof(struct ieee80211req_wpaie2);
@@ -186,18 +195,21 @@ ieee80211_ioctl_getwpaie(struct ieee80211vap *vap,
                /* XXX check ic_flags? */
                if (ni->ni_ies.rsn_ie != NULL) {
                        int ielen = ni->ni_ies.rsn_ie[1] + 2;
-                       if (ielen > sizeof(wpaie.wpa_ie))
-                               ielen = sizeof(wpaie.wpa_ie);
-                       memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen);
+                       if (ielen > sizeof(wpaie->wpa_ie))
+                               ielen = sizeof(wpaie->wpa_ie);
+                       memcpy(wpaie->wpa_ie, ni->ni_ies.rsn_ie, ielen);
                }
                if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
                        ireq->i_len = sizeof(struct ieee80211req_wpaie);
        }
        ieee80211_free_node(ni);
-       return copyout(&wpaie, ireq->i_data, ireq->i_len);
+       error = copyout(wpaie, ireq->i_data, ireq->i_len);
+bad:
+       IEEE80211_FREE(wpaie, M_TEMP);
+       return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -252,7 +264,7 @@ get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
        req->space += scan_space(se, &ielen);
 }
 
-static __noinline void
+static void
 get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
 {
        struct scanreq *req = arg;
@@ -302,7 +314,7 @@ get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
        req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
        struct ieee80211req *ireq)
 {
@@ -323,14 +335,19 @@ ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
 
                space = req.space;
                /* XXX M_WAITOK after driver lock released */
+#if defined(__DragonFly__)
                p = kmalloc(space, M_TEMP, M_INTWAIT | M_ZERO);
+#else
+               p = IEEE80211_MALLOC(space, M_TEMP,
+                       IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                if (p == NULL)
                        return ENOMEM;
                req.sr = p;
                ieee80211_scan_iterate(vap, get_scan_result, &req);
                ireq->i_len = space - req.space;
                error = copyout(p, ireq->i_data, ireq->i_len);
-               kfree(p, M_TEMP);
+               IEEE80211_FREE(p, M_TEMP);
        } else
                ireq->i_len = 0;
 
@@ -365,7 +382,7 @@ get_sta_space(void *arg, struct ieee80211_node *ni)
        req->space += sta_space(ni, &ielen);
 }
 
-static __noinline void
+static void
 get_sta_info(void *arg, struct ieee80211_node *ni)
 {
        struct stainforeq *req = arg;
@@ -451,7 +468,7 @@ get_sta_info(void *arg, struct ieee80211_node *ni)
        req->space -= len;
 }
 
-static __noinline int
+static int
 getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
        struct ieee80211_node *ni, size_t off)
 {
@@ -473,7 +490,12 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
        if (req.space > 0) {
                space = req.space;
                /* XXX M_WAITOK after driver lock released */
+#if defined(__DragonFly__)
                p = kmalloc(space, M_TEMP, M_INTWAIT | M_ZERO);
+#else
+               p = IEEE80211_MALLOC(space, M_TEMP,
+                       IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                if (p == NULL) {
                        error = ENOMEM;
                        goto bad;
@@ -485,7 +507,7 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
                        get_sta_info(&req, ni);
                ireq->i_len = space - req.space;
                error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
-               kfree(p, M_TEMP);
+               IEEE80211_FREE(p, M_TEMP);
        } else
                ireq->i_len = 0;
 bad:
@@ -494,7 +516,7 @@ bad:
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        uint8_t macaddr[IEEE80211_ADDR_LEN];
@@ -517,7 +539,7 @@ ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return getstainfo_common(vap, ireq, ni, off);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -538,7 +560,7 @@ ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -581,7 +603,7 @@ ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return 0;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        const struct ieee80211_aclator *acl = vap->iv_acl;
@@ -589,7 +611,7 @@ ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq));
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -646,7 +668,7 @@ ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return EINVAL;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getregdomain(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -658,7 +680,7 @@ ieee80211_ioctl_getregdomain(struct ieee80211vap *vap,
            sizeof(ic->ic_regdomain));
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getroam(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -669,7 +691,7 @@ ieee80211_ioctl_getroam(struct ieee80211vap *vap,
        return copyout(vap->iv_roamparms, ireq->i_data, len);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_gettxparams(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -680,7 +702,7 @@ ieee80211_ioctl_gettxparams(struct ieee80211vap *vap,
        return copyout(vap->iv_txparms, ireq->i_data, len);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
        const struct ieee80211req *ireq)
 {
@@ -696,8 +718,14 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
        /* constrain max request size, 2K channels is ~24Kbytes */
        if (maxchans > 2048)
                maxchans = 2048;
+#if defined(__DragonFly__)
        dc = (struct ieee80211_devcaps_req *)
            kmalloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_INTWAIT | M_ZERO);
+#else
+       dc = (struct ieee80211_devcaps_req *)
+           IEEE80211_MALLOC(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP,
+               IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (dc == NULL)
                return ENOMEM;
        dc->dc_drivercaps = ic->ic_caps;
@@ -709,11 +737,11 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
            ("nchans %d maxchans %d", ci->ic_nchans, maxchans));
        ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
        error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
-       kfree(dc, M_TEMP);
+       IEEE80211_FREE(dc, M_TEMP);
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -762,23 +790,7 @@ ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return EINVAL;
 }
 
-/*
- * When building the kernel with -O2 on the i386 architecture, gcc
- * seems to want to inline this function into ieee80211_ioctl()
- * (which is the only routine that calls it). When this happens,
- * ieee80211_ioctl() ends up consuming an additional 2K of stack
- * space. (Exactly why it needs so much is unclear.) The problem
- * is that it's possible for ieee80211_ioctl() to invoke other
- * routines (including driver init functions) which could then find
- * themselves perilously close to exhausting the stack.
- *
- * To avoid this, we deliberately prevent gcc from inlining this
- * routine. Another way to avoid this is to use less agressive
- * optimization when compiling this file (i.e. -O instead of -O2)
- * but special-casing the compilation of this one module in the
- * build system would be awkward.
- */
-static __noinline int
+static int
 ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
     struct ieee80211req *ireq)
 {
@@ -929,8 +941,6 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
                            ireq->i_len);
                break;
        case IEEE80211_IOC_WPAIE:
-               error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
-               break;
        case IEEE80211_IOC_WPAIE2:
                error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
                break;
@@ -954,7 +964,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
        case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
        case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
        case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
-       case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (bss only) */
+       case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (!bss only) */
                error = ieee80211_ioctl_getwmeparam(vap, ireq);
                break;
        case IEEE80211_IOC_DTIM_PERIOD:
@@ -1027,6 +1037,10 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
                if (vap->iv_opmode == IEEE80211_M_HOSTAP)
                        ireq->i_val = vap->iv_ampdu_rxmax;
                else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
+                       /*
+                        * XXX TODO: this isn't completely correct, as we've
+                        * negotiated the higher of the two.
+                        */
                        ireq->i_val = MS(vap->iv_bss->ni_htparam,
                            IEEE80211_HTCAP_MAXRXAMPDU);
                else
@@ -1035,6 +1049,10 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
        case IEEE80211_IOC_AMPDU_DENSITY:
                if (vap->iv_opmode == IEEE80211_M_STA &&
                    (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
+                       /*
+                        * XXX TODO: this isn't completely correct, as we've
+                        * negotiated the higher of the two.
+                        */
                        ireq->i_val = MS(vap->iv_bss->ni_htparam,
                            IEEE80211_HTCAP_MPDUDENSITY);
                else
@@ -1127,6 +1145,13 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
                        ireq->i_val =
                            (vap->iv_flags_ht & IEEE80211_FHT_RIFS) != 0;
                break;
+       case IEEE80211_IOC_STBC:
+               ireq->i_val = 0;
+               if (vap->iv_flags_ht & IEEE80211_FHT_STBC_TX)
+                       ireq->i_val |= 1;
+               if (vap->iv_flags_ht & IEEE80211_FHT_STBC_RX)
+                       ireq->i_val |= 2;
+               break;
        default:
                error = ieee80211_ioctl_getdefault(vap, ireq);
                break;
@@ -1135,7 +1160,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
 #undef MS
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211req_key ik;
@@ -1209,7 +1234,7 @@ ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211req_del_key dk;
@@ -1280,18 +1305,20 @@ mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
        if (op == IEEE80211_MLME_AUTH) {
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL |
                    IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac,
-                   "station authenticate %s via MLME (reason %d)",
+                   "station authenticate %s via MLME (reason: %d (%s))",
                    reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT",
-                   reason);
+                   reason, ieee80211_reason_to_string(reason));
        } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) {
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac,
-                   "unknown MLME request %d (reason %d)", op, reason);
+                   "unknown MLME request %d (reason: %d (%s))", op, reason,
+                   ieee80211_reason_to_string(reason));
        } else if (reason == IEEE80211_STATUS_SUCCESS) {
                IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
                    "station %s via MLME", ops[op].opstr);
        } else {
                IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
-                   "station %s via MLME (reason %d)", ops[op].opstr, reason);
+                   "station %s via MLME (reason: %d (%s))", ops[op].opstr,
+                   reason, ieee80211_reason_to_string(reason));
        }
 #endif /* IEEE80211_DEBUG */
 }
@@ -1326,13 +1353,12 @@ static int
 setmlme_dropsta(struct ieee80211vap *vap,
        const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
 {
-       struct ieee80211com *ic = vap->iv_ic;
-       struct ieee80211_node_table *nt = &ic->ic_sta;
+       struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
        struct ieee80211_node *ni;
        int error = 0;
 
        /* NB: the broadcast address means do 'em all */
-       if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
+       if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
                IEEE80211_NODE_LOCK(nt);
                ni = ieee80211_find_node_locked(nt, mac);
                IEEE80211_NODE_UNLOCK(nt);
@@ -1352,7 +1378,7 @@ setmlme_dropsta(struct ieee80211vap *vap,
        return error;
 }
 
-static __noinline int
+static int
 setmlme_common(struct ieee80211vap *vap, int op,
        const uint8_t mac[IEEE80211_ADDR_LEN], int reason)
 {
@@ -1513,7 +1539,7 @@ mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
        look->se = se;
 }
 
-static __noinline int
+static int
 setmlme_assoc_sta(struct ieee80211vap *vap,
        const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len,
        const uint8_t ssid[IEEE80211_NWID_LEN])
@@ -1538,12 +1564,13 @@ setmlme_assoc_sta(struct ieee80211vap *vap,
        return 0;
 }
 
-static __noinline int
+static int
 setmlme_assoc_adhoc(struct ieee80211vap *vap,
        const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len,
        const uint8_t ssid[IEEE80211_NWID_LEN])
 {
-       struct ieee80211_scan_req sr;
+       struct ieee80211_scan_req *sr;
+       int error;
 
        KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
            vap->iv_opmode == IEEE80211_M_AHDEMO,
@@ -1553,23 +1580,34 @@ setmlme_assoc_adhoc(struct ieee80211vap *vap,
        if (ssid_len == 0)
                return EINVAL;
 
+#if defined(__DragonFly__)
+       sr = kmalloc(sizeof(*sr), M_TEMP, M_INTWAIT | M_ZERO);
+#else
+       sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP,
+            IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
+       if (sr == NULL)
+               return ENOMEM;
+
        /* NB: IEEE80211_IOC_SSID call missing for ap_scan=2. */
        memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
        vap->iv_des_ssid[0].len = ssid_len;
        memcpy(vap->iv_des_ssid[0].ssid, ssid, ssid_len);
        vap->iv_des_nssid = 1;
 
-       memset(&sr, 0, sizeof(sr));
-       sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE;
-       sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
-       memcpy(sr.sr_ssid[0].ssid, ssid, ssid_len);
-       sr.sr_ssid[0].len = ssid_len;
-       sr.sr_nssid = 1;
+       sr->sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE;
+       sr->sr_duration = IEEE80211_IOC_SCAN_FOREVER;
+       memcpy(sr->sr_ssid[0].ssid, ssid, ssid_len);
+       sr->sr_ssid[0].len = ssid_len;
+       sr->sr_nssid = 1;
+
+       error = ieee80211_scanreq(vap, sr);
 
-       return ieee80211_scanreq(vap, &sr);
+       IEEE80211_FREE(sr, M_TEMP);
+       return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211req_mlme mlme;
@@ -1594,7 +1632,7 @@ ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq)
                    mlme.im_macaddr, mlme.im_reason);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        uint8_t mac[IEEE80211_ADDR_LEN];
@@ -1619,7 +1657,7 @@ ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return 0;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        const struct ieee80211_aclator *acl = vap->iv_acl;
@@ -1657,7 +1695,7 @@ ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return 0;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -1666,13 +1704,18 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
 
        if (ireq->i_len > sizeof(ic->ic_chan_active))
                ireq->i_len = sizeof(ic->ic_chan_active);
+#if defined(__DragonFly__)
        list = kmalloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
            M_INTWAIT | M_ZERO);
+#else
+       list = IEEE80211_MALLOC(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
+           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (list == NULL)
                return ENOMEM;
        error = copyin(ireq->i_data, list, ireq->i_len);
        if (error) {
-               kfree(list, M_TEMP);
+               IEEE80211_FREE(list, M_TEMP);
                return error;
        }
        nchan = 0;
@@ -1691,7 +1734,7 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
                }
        }
        if (nchan == 0) {
-               kfree(list, M_TEMP);
+               IEEE80211_FREE(list, M_TEMP);
                return EINVAL;
        }
        if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&    /* XXX */
@@ -1699,11 +1742,11 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
                ic->ic_bsschan = IEEE80211_CHAN_ANYC;
        memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES);
        ieee80211_scan_flush(vap);
-       kfree(list, M_TEMP);
+       IEEE80211_FREE(list, M_TEMP);
        return ENETRESET;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -1729,7 +1772,7 @@ ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return 0;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -1749,19 +1792,20 @@ ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
        struct ieee80211_wme_state *wme = &ic->ic_wme;
        struct wmeParams *wmep, *chanp;
-       int isbss, ac;
+       int isbss, ac, aggrmode;
 
        if ((ic->ic_caps & IEEE80211_C_WME) == 0)
                return EOPNOTSUPP;
 
        isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
        ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
+       aggrmode = (wme->wme_flags & WME_F_AGGRMODE);
        if (ac >= WME_NUM_AC)
                ac = WME_AC_BE;
        if (isbss) {
@@ -1773,47 +1817,28 @@ ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
        }
        switch (ireq->i_type) {
        case IEEE80211_IOC_WME_CWMIN:           /* WME: CWmin */
-               if (isbss) {
-                       wmep->wmep_logcwmin = ireq->i_val;
-                       if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
-                               chanp->wmep_logcwmin = ireq->i_val;
-               } else {
-                       wmep->wmep_logcwmin = chanp->wmep_logcwmin =
-                               ireq->i_val;
-               }
+               wmep->wmep_logcwmin = ireq->i_val;
+               if (!isbss || !aggrmode)
+                       chanp->wmep_logcwmin = ireq->i_val;
                break;
        case IEEE80211_IOC_WME_CWMAX:           /* WME: CWmax */
-               if (isbss) {
-                       wmep->wmep_logcwmax = ireq->i_val;
-                       if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
-                               chanp->wmep_logcwmax = ireq->i_val;
-               } else {
-                       wmep->wmep_logcwmax = chanp->wmep_logcwmax =
-                               ireq->i_val;
-               }
+               wmep->wmep_logcwmax = ireq->i_val;
+               if (!isbss || !aggrmode)
+                       chanp->wmep_logcwmax = ireq->i_val;
                break;
        case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
-               if (isbss) {
-                       wmep->wmep_aifsn = ireq->i_val;
-                       if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
-                               chanp->wmep_aifsn = ireq->i_val;
-               } else {
-                       wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
-               }
+               wmep->wmep_aifsn = ireq->i_val;
+               if (!isbss || !aggrmode)
+                       chanp->wmep_aifsn = ireq->i_val;
                break;
        case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
-               if (isbss) {
-                       wmep->wmep_txopLimit = ireq->i_val;
-                       if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
-                               chanp->wmep_txopLimit = ireq->i_val;
-               } else {
-                       wmep->wmep_txopLimit = chanp->wmep_txopLimit =
-                               ireq->i_val;
-               }
+               wmep->wmep_txopLimit = ireq->i_val;
+               if (!isbss || !aggrmode)
+                       chanp->wmep_txopLimit = ireq->i_val;
                break;
        case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
                wmep->wmep_acm = ireq->i_val;
-               if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
+               if (!aggrmode)
                        chanp->wmep_acm = ireq->i_val;
                break;
        case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (!bss only)*/
@@ -1993,7 +2018,7 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
  * Old api for setting the current channel; this is
  * deprecated because channel numbers are ambiguous.
  */
-static __noinline int
+static int
 ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -2072,7 +2097,7 @@ ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
  * channel description is provide so there is no ambiguity in
  * identifying the channel.
  */
-static __noinline int
+static int
 ieee80211_ioctl_setcurchan(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -2096,7 +2121,7 @@ ieee80211_ioctl_setcurchan(struct ieee80211vap *vap,
        return setcurchan(vap, c);
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -2111,8 +2136,14 @@ ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
                    ireq->i_len, nchans);
                return EINVAL;
        }
+#if defined(__DragonFly__)
        reg = (struct ieee80211_regdomain_req *)
            kmalloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_INTWAIT);
+#else
+       reg = (struct ieee80211_regdomain_req *)
+           IEEE80211_MALLOC(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP,
+               IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (reg == NULL) {
                IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
                    "%s: no memory, nchans %d\n", __func__, nchans);
@@ -2129,7 +2160,7 @@ ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
                } else
                        error = ieee80211_setregdomain(vap, reg);
        }
-       kfree(reg, M_TEMP);
+       IEEE80211_FREE(reg, M_TEMP);
 
        return (error == 0 ? ENETRESET : error);
 }
@@ -2169,7 +2200,7 @@ checkmcs(int mcs)
        return (mcs & 0x7f) <= 15;      /* XXX could search ht rate set */
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -2246,7 +2277,7 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
        if (ireq->i_len == 0) {         /* delete any existing ie */
                if (app != NULL) {
                        *aie = NULL;    /* XXX racey */
-                       kfree(app, M_80211_NODE_IE);
+                       IEEE80211_FREE(app, M_80211_NODE_IE);
                }
                return 0;
        }
@@ -2260,20 +2291,26 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
         *
         * XXX bad bad bad
         */
+#if defined(__DragonFly__)
        napp = (struct ieee80211_appie *) kmalloc(
            sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_INTWAIT);
+#else
+       napp = (struct ieee80211_appie *) IEEE80211_MALLOC(
+           sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE,
+           IEEE80211_M_NOWAIT);
+#endif
        if (napp == NULL)
                return ENOMEM;
        /* XXX holding ic lock */
        error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
        if (error) {
-               kfree(napp, M_80211_NODE_IE);
+               IEEE80211_FREE(napp, M_80211_NODE_IE);
                return error;
        }
        napp->ie_len = ireq->i_len;
        *aie = napp;
        if (app != NULL)
-               kfree(app, M_80211_NODE_IE);
+               IEEE80211_FREE(app, M_80211_NODE_IE);
        return 0;
 }
 
@@ -2289,7 +2326,7 @@ setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space)
                vap->iv_rsn_ie = ie;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap,
        const struct ieee80211req *ireq, int fc0)
 {
@@ -2367,7 +2404,7 @@ ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap,
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setappie(struct ieee80211vap *vap,
        const struct ieee80211req *ireq)
 {
@@ -2385,7 +2422,7 @@ ieee80211_ioctl_setappie(struct ieee80211vap *vap,
        return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -2521,26 +2558,32 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
 #undef IEEE80211_IOC_SCAN_FLAGS
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
-       struct ieee80211com *ic = vap->iv_ic;
-       struct ieee80211_scan_req sr;           /* XXX off stack? */
+       struct ieee80211_scan_req *sr;
        int error;
 
-       /* NB: parent must be running */
-       if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-               return ENXIO;
-
-       if (ireq->i_len != sizeof(sr))
+       if (ireq->i_len != sizeof(*sr))
                return EINVAL;
-       error = copyin(ireq->i_data, &sr, sizeof(sr));
+#if defined(__DragonFly__)
+       sr = kmalloc(sizeof(*sr), M_TEMP, M_INTWAIT | M_ZERO);
+#else
+       sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP,
+            IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
+       if (sr == NULL)
+               return ENOMEM;
+       error = copyin(ireq->i_data, sr, sizeof(*sr));
        if (error != 0)
-               return error;
-       return ieee80211_scanreq(vap, &sr);
+               goto bad;
+       error = ieee80211_scanreq(vap, sr);
+bad:
+       IEEE80211_FREE(sr, M_TEMP);
+       return error;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
 {
        struct ieee80211_node *ni;
@@ -2604,7 +2647,7 @@ ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
        return EINVAL;
 }
 
-static __noinline int
+static int
 ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
 {
        struct ieee80211com *ic = vap->iv_ic;
@@ -2826,6 +2869,9 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
                /* XXX verify ciphers available */
                flags = vap->iv_flags & ~IEEE80211_F_WPA;
                switch (ireq->i_val) {
+               case 0:
+                       /* wpa_supplicant calls this to clear the WPA config */
+                       break;
                case 1:
                        if (!(vap->iv_caps & IEEE80211_C_WPA1))
                                return EOPNOTSUPP;
@@ -2946,7 +2992,7 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
        case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
        case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
        case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
-       case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (bss only) */
+       case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (!bss only) */
                error = ieee80211_ioctl_setwmeparam(vap, ireq);
                break;
        case IEEE80211_IOC_DTIM_PERIOD:
@@ -3266,6 +3312,31 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
                if (isvapht(vap))
                        error = ERESTART;
                break;
+       case IEEE80211_IOC_STBC:
+               /* Check if we can do STBC TX/RX before changing the setting */
+               if ((ireq->i_val & 1) &&
+                   ((vap->iv_htcaps & IEEE80211_HTCAP_TXSTBC) == 0))
+                       return EOPNOTSUPP;
+               if ((ireq->i_val & 2) &&
+                   ((vap->iv_htcaps & IEEE80211_HTCAP_RXSTBC) == 0))
+                       return EOPNOTSUPP;
+
+               /* TX */
+               if (ireq->i_val & 1)
+                       vap->iv_flags_ht |= IEEE80211_FHT_STBC_TX;
+               else
+                       vap->iv_flags_ht &= ~IEEE80211_FHT_STBC_TX;
+
+               /* RX */
+               if (ireq->i_val & 2)
+                       vap->iv_flags_ht |= IEEE80211_FHT_STBC_RX;
+               else
+                       vap->iv_flags_ht &= ~IEEE80211_FHT_STBC_RX;
+
+               /* NB: reset only if we're operating on an 11n channel */
+               if (isvapht(vap))
+                       error = ERESTART;
+               break;
        default:
                error = ieee80211_ioctl_setdefault(vap, ireq);
                break;
@@ -3295,41 +3366,6 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
        return error;
 }
 
-/*
- * Rebuild the parent's multicast address list after an add/del
- * of a multicast address for a vap.  We have no way to tell
- * what happened above to optimize the work so we purge the entire
- * list and rebuild from scratch.  This is way expensive.
- * Note also the half-baked workaround for if_addmulti calling
- * back to the parent device; there's no way to insert mcast
- * entries quietly and/or cheaply.
- */
-static void
-ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
-{
-       struct ifnet *parent = ic->ic_ifp;
-       struct ieee80211vap *vap;
-       void *ioctl;
-
-       IEEE80211_LOCK(ic);
-       if_delallmulti_serialized(parent);
-       ioctl = parent->if_ioctl;       /* XXX WAR if_allmulti */
-       parent->if_ioctl = NULL;
-       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
-               struct ifnet *ifp = vap->iv_ifp;
-               struct ifmultiaddr *ifma;
-
-               TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-                       if (ifma->ifma_addr->sa_family != AF_LINK)
-                               continue;
-                       (void) if_addmulti_serialized(parent, ifma->ifma_addr, NULL);
-               }
-       }
-       parent->if_ioctl = ioctl;
-       ieee80211_runtask(ic, &ic->ic_mcast_task);
-       IEEE80211_UNLOCK(ic);
-}
-
 #if defined(__DragonFly__)
 int
 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *ucred)
@@ -3340,15 +3376,34 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
        struct ieee80211vap *vap = ifp->if_softc;
        struct ieee80211com *ic = vap->iv_ic;
-       int error = 0;
+       int error = 0, wait = 0;
        struct ifreq *ifr;
        struct ifaddr *ifa;                     /* XXX */
 
        switch (cmd) {
        case SIOCSIFFLAGS:
                IEEE80211_LOCK(ic);
-               ieee80211_syncifflag_locked(ic, IFF_PROMISC);
-               ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+               if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC) {
+                       /*
+                        * Enable promiscuous mode when:
+                        * 1. Interface is not a member of bridge, or
+                        * 2. Requested by user, or
+                        * 3. In monitor (or adhoc-demo) mode.
+                        */
+                       if (ifp->if_bridge == NULL ||
+                           (ifp->if_flags & IFF_PPROMISC) != 0 ||
+                           vap->iv_opmode == IEEE80211_M_MONITOR ||
+                           (vap->iv_opmode == IEEE80211_M_AHDEMO &&
+                           (vap->iv_caps & IEEE80211_C_TDMA) == 0)) {
+                               ieee80211_promisc(vap,
+                                   ifp->if_flags & IFF_PROMISC);
+                               vap->iv_ifflags ^= IFF_PROMISC;
+                       }
+               }
+               if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI) {
+                       ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
+                       vap->iv_ifflags ^= IFF_ALLMULTI;
+               }
                if (ifp->if_flags & IFF_UP) {
                        /*
                         * Bring ourself up unless we're already operational.
@@ -3356,30 +3411,46 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                         * then it will automatically be brought up as a
                         * side-effect of bringing ourself up.
                         */
-                       if (vap->iv_state == IEEE80211_S_INIT)
+                       if (vap->iv_state == IEEE80211_S_INIT) {
+                               if (ic->ic_nrunning == 0)
+                                       wait = 1;
                                ieee80211_start_locked(vap);
+                       }
                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
                        /*
                         * Stop ourself.  If we are the last vap to be
                         * marked down the parent will also be taken down.
                         */
+                       if (ic->ic_nrunning == 1)
+                               wait = 1;
                        ieee80211_stop_locked(vap);
                }
                IEEE80211_UNLOCK(ic);
                /* Wait for parent ioctl handler if it was queued */
+               if (wait) {
 #if defined(__DragonFly__)
-               /* DragonFly: release serializer to avoid deadlock */
-               wlan_serialize_exit();
-               ieee80211_waitfor_parent(ic);
-               wlan_serialize_enter();
-#else
-               ieee80211_waitfor_parent(ic);
+                       /* DragonFly: release serializer to avoid deadlock */
+                       wlan_serialize_exit();
+#endif
+                       ieee80211_waitfor_parent(ic);
+
+                       /*
+                        * Check if the MAC address was changed
+                        * via SIOCSIFLLADDR ioctl.
+                        */
+                       if ((ifp->if_flags & IFF_UP) == 0 &&
+                           !IEEE80211_ADDR_EQ(vap->iv_myaddr, IF_LLADDR(ifp)))
+                               IEEE80211_ADDR_COPY(vap->iv_myaddr,
+                                   IF_LLADDR(ifp));
+#if defined(__DragonFly__)
+                       wlan_serialize_enter();
 #endif
+               }
                break;
        case SIOCADDMULTI:
        case SIOCDELMULTI:
                /* DragonFly: serializer must be held */
-               ieee80211_ioctl_updatemulti(ic);
+               ieee80211_runtask(ic, &ic->ic_mcast_task);
                break;
        case SIOCSIFMEDIA:
        case SIOCGIFMEDIA:
@@ -3411,10 +3482,10 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                break;
        case SIOCSIFADDR:
                /*
-                * XXX Handle this directly so we can supress if_init calls.
+                * XXX Handle this directly so we can suppress if_init calls.
                 * XXX This should be done in ether_ioctl but for the moment
                 * XXX there are too many other parts of the system that
-                * XXX set IFF_UP and so supress if_init being called when
+                * XXX set IFF_UP and so suppress if_init being called when
                 * XXX it should be.
                 */
                ifa = (struct ifaddr *) data;
@@ -3436,24 +3507,17 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                        break;
                }
                break;
-       /* Pass NDIS ioctls up to the driver */
-       case SIOCGDRVSPEC:
-       case SIOCSDRVSPEC:
-       case SIOCGPRIVATE_0: {
-               struct ifnet *parent = vap->iv_ic->ic_ifp;
-#if defined(__DragonFly__)
-               /* DragonFly: serializer must be held */
-               error = parent->if_ioctl(parent, cmd, data, ucred);
-#else
-               error = parent->if_ioctl(parent, cmd, data);
-#endif
-               break;
-       }
        default:
+               /*
+                * Pass unknown ioctls first to the driver, and if it
+                * returns ENOTTY, then to the generic Ethernet handler.
+                */
+               if (ic->ic_ioctl != NULL &&
+                   (error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
+                       break;
                /* DragonFly: serializer must be held */
                error = ether_ioctl(ifp, cmd, data);
                break;
        }
-
-       return error;
+       return (error);
 }
index 1923400..ec0332e 100644 (file)
@@ -203,14 +203,24 @@ mesh_rt_add_locked(struct ieee80211vap *vap,
 
        MESH_RT_LOCK_ASSERT(ms);
 
+#if defined(__DragonFly__)
        rt = kmalloc(ALIGN(sizeof(struct ieee80211_mesh_route)) +
            ms->ms_ppath->mpp_privlen, M_80211_MESH_RT, M_INTWAIT | M_ZERO);
+#else
+       rt = IEEE80211_MALLOC(ALIGN(sizeof(struct ieee80211_mesh_route)) +
+           ms->ms_ppath->mpp_privlen, M_80211_MESH_RT,
+           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (rt != NULL) {
                rt->rt_vap = vap;
                IEEE80211_ADDR_COPY(rt->rt_dest, dest);
                rt->rt_priv = (void *)ALIGN(&rt[1]);
                MESH_RT_ENTRY_LOCK_INIT(rt, "MBSS_RT");
+#if defined(__DragonFly__)
                callout_init_mp(&rt->rt_discovery);
+#else
+               callout_init(&rt->rt_discovery, 1);
+#endif
                rt->rt_updtime = ticks; /* create time */
                TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
        }
@@ -352,7 +362,7 @@ mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
        MESH_RT_ENTRY_LOCK(rt);
        callout_drain(&rt->rt_discovery);
        MESH_RT_ENTRY_LOCK_DESTROY(rt);
-       kfree(rt, M_80211_MESH_RT);
+       IEEE80211_FREE(rt, M_80211_MESH_RT);
 }
 
 void
@@ -433,13 +443,12 @@ mesh_rt_flush_invalid(struct ieee80211vap *vap)
        MESH_RT_UNLOCK(ms);
 }
 
-#define        N(a)    (sizeof(a) / sizeof(a[0]))
 int
 ieee80211_mesh_register_proto_path(const struct ieee80211_mesh_proto_path *mpp)
 {
        int i, firstempty = -1;
 
-       for (i = 0; i < N(mesh_proto_paths); i++) {
+       for (i = 0; i < nitems(mesh_proto_paths); i++) {
                if (strncmp(mpp->mpp_descr, mesh_proto_paths[i].mpp_descr,
                    IEEE80211_MESH_PROTO_DSZ) == 0)
                        return EEXIST;
@@ -459,7 +468,7 @@ ieee80211_mesh_register_proto_metric(const struct
 {
        int i, firstempty = -1;
 
-       for (i = 0; i < N(mesh_proto_metrics); i++) {
+       for (i = 0; i < nitems(mesh_proto_metrics); i++) {
                if (strncmp(mpm->mpm_descr, mesh_proto_metrics[i].mpm_descr,
                    IEEE80211_MESH_PROTO_DSZ) == 0)
                        return EEXIST;
@@ -479,7 +488,7 @@ mesh_select_proto_path(struct ieee80211vap *vap, const char *name)
        struct ieee80211_mesh_state *ms = vap->iv_mesh;
        int i;
 
-       for (i = 0; i < N(mesh_proto_paths); i++) {
+       for (i = 0; i < nitems(mesh_proto_paths); i++) {
                if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
                        ms->ms_ppath = &mesh_proto_paths[i];
                        return 0;
@@ -494,7 +503,7 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
        struct ieee80211_mesh_state *ms = vap->iv_mesh;
        int i;
 
-       for (i = 0; i < N(mesh_proto_metrics); i++) {
+       for (i = 0; i < nitems(mesh_proto_metrics); i++) {
                if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
                        ms->ms_pmetric = &mesh_proto_metrics[i];
                        return 0;
@@ -502,7 +511,6 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
        }
        return ENOENT;
 }
-#undef N
 
 static void
 mesh_gatemode_setup(struct ieee80211vap *vap)
@@ -646,7 +654,7 @@ mesh_vdetach(struct ieee80211vap *vap)
        ieee80211_mesh_rt_flush(vap);
        MESH_RT_LOCK_DESTROY(ms);
        ms->ms_ppath->mpp_vdetach(vap);
-       kfree(vap->iv_mesh, M_80211_VAP);
+       IEEE80211_FREE(vap->iv_mesh, M_80211_VAP);
        vap->iv_mesh = NULL;
 }
 
@@ -659,8 +667,13 @@ mesh_vattach(struct ieee80211vap *vap)
        vap->iv_opdetach = mesh_vdetach;
        vap->iv_recv_mgmt = mesh_recv_mgmt;
        vap->iv_recv_ctl = mesh_recv_ctl;
+#if defined(__DragonFly__)
        ms = kmalloc(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
            M_INTWAIT | M_ZERO);
+#else
+       ms = IEEE80211_MALLOC(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
+           IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (ms == NULL) {
                kprintf("%s: couldn't alloc MBSS state\n", __func__);
                return;
@@ -672,8 +685,13 @@ mesh_vattach(struct ieee80211vap *vap)
        TAILQ_INIT(&ms->ms_known_gates);
        TAILQ_INIT(&ms->ms_routes);
        MESH_RT_LOCK_INIT(ms, "MBSS");
+#if defined(__DragonFly__)
        callout_init_mp(&ms->ms_cleantimer);
        callout_init_mp(&ms->ms_gatetimer);
+#else
+       callout_init(&ms->ms_cleantimer, 1);
+       callout_init(&ms->ms_gatetimer, 1);
+#endif
        ms->ms_gateseq = 0;
        mesh_select_proto_metric(vap, "AIRTIME");
        KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
@@ -877,8 +895,14 @@ ieee80211_mesh_mark_gate(struct ieee80211vap *vap, const uint8_t *addr,
                /* New mesh gate add it to known table. */
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, addr,
                    "%s", "stored new gate information from pro-PREQ.");
+#if defined(__DragonFly__)
                gr = kmalloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
                    M_80211_MESH_GT_RT, M_INTWAIT | M_ZERO);
+#else
+               gr = IEEE80211_MALLOC(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
+                   M_80211_MESH_GT_RT,
+                   IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                IEEE80211_ADDR_COPY(gr->gr_addr, addr);
                TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
        }
@@ -1040,7 +1064,7 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m,
 
        ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest);
        if (ni == NULL) {
-               IFNET_STAT_INC(ifp, oerrors, 1);
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
                m_freem(m);
                return;
        }
@@ -1087,10 +1111,16 @@ ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap,
        TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, gr_next) {
                rt_gate = gr->gr_route;
                if (rt_gate == NULL) {
+#if defined(__DragonFly__)
                        IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
                                rt_dest->rt_dest,
                                "mesh gate with no path %s",
                                ether_sprintf(gr->gr_addr));
+#else
+                       IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
+                               "mesh gate with no path %6D",
+                               gr->gr_addr, ":");
+#endif
                        continue;
                }
                if ((rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
@@ -1155,7 +1185,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
        IEEE80211_TX_UNLOCK_ASSERT(ic);
 
        /*
-        * mesh ttl of 1 means we are the last one receving it,
+        * mesh ttl of 1 means we are the last one receiving it,
         * according to amendment we decrement and then check if
         * 0, if so we dont forward.
         */
@@ -1176,7 +1206,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
                IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
                    "%s", "frame not fwd'd, cannot dup");
                vap->iv_stats.is_mesh_fwd_nobuf++;
-               IFNET_STAT_INC(ifp, oerrors, 1);
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
                return;
        }
        mcopy = m_pullup(mcopy, ieee80211_hdrspace(ic, wh) +
@@ -1185,7 +1215,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
                IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
                    "%s", "frame not fwd'd, too short");
                vap->iv_stats.is_mesh_fwd_tooshort++;
-               IFNET_STAT_INC(ifp, oerrors, 1);
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
                m_freem(mcopy);
                return;
        }
@@ -1239,12 +1269,8 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
        IEEE80211_TX_LOCK(ic);
        err = ieee80211_parent_xmitpkt(ic, mcopy);
        IEEE80211_TX_UNLOCK(ic);
-       if (err != 0) {
-               /* NB: IFQ_HANDOFF reclaims mbuf */
-               ieee80211_free_node(ni);
-       } else {
-               IFNET_STAT_INC(ifp, opackets, 1);
-       }
+       if (!err)
+               if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
 }
 
 static struct mbuf *
@@ -1391,8 +1417,13 @@ mesh_recv_indiv_data_to_fwrd(struct ieee80211vap *vap, struct mbuf *m,
        /* set lifetime of addr3 (meshDA) to initial value */
        rt_meshda = ieee80211_mesh_rt_find(vap, qwh->i_addr3);
        if (rt_meshda == NULL) {
+#if defined(__DragonFly__)
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, qwh->i_addr2,
                    "no route to meshDA(%s)", ether_sprintf(qwh->i_addr3));
+#else
+               IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, qwh->i_addr2,
+                   "no route to meshDA(%6D)", qwh->i_addr3, ":");
+#endif
                /*
                 * [Optional] any of the following three actions:
                 * o silently discard                           [X]
@@ -1478,10 +1509,16 @@ mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m,
                 * All other cases: forward of MSDUs from the MBSS to DS indiv.
                 * addressed according to 13.11.3.2.
                 */
+#if defined(__DragonFly__)
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2,
                    "forward frame to DS, SA(%s) DA(%s)",
                    ether_sprintf(mc10->mc_addr6),
                    ether_sprintf(mc10->mc_addr5));
+#else
+               IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2,
+                   "forward frame to DS, SA(%6D) DA(%6D)",
+                   mc10->mc_addr6, ":", mc10->mc_addr5, ":");
+#endif
        }
        return (0); /* process locally */
 }
@@ -1542,7 +1579,6 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m,
        uint32_t seq;
        const uint8_t *addr;
        uint8_t qos[2];
-       ieee80211_seq rxseq;
 
        KASSERT(ni != NULL, ("null node"));
        ni->ni_inact = ni->ni_inact_reload;
@@ -1587,24 +1623,8 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m,
                        if (IEEE80211_QOS_HAS_SEQ(wh) &&
                            TID_TO_WME_AC(tid) >= WME_AC_VI)
                                ic->ic_wme.wme_hipri_traffic++;
-                       rxseq = le16toh(*(uint16_t *)wh->i_seq);
-                       if (! ieee80211_check_rxseq(ni, wh)) {
-                               /* duplicate, discard */
-                               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
-                                   wh->i_addr1, "duplicate",
-                                   "seqno <%u,%u> fragno <%u,%u> tid %u",
-                                   rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
-                                   ni->ni_rxseqs[tid] >>
-                                   IEEE80211_SEQ_SEQ_SHIFT,
-                                   rxseq & IEEE80211_SEQ_FRAG_MASK,
-                                   ni->ni_rxseqs[tid] &
-                                   IEEE80211_SEQ_FRAG_MASK,
-                                   tid);
-                               vap->iv_stats.is_rx_dup++;
-                               IEEE80211_NODE_STAT(ni, rx_dup);
+                       if (! ieee80211_check_rxseq(ni, wh, wh->i_addr1))
                                goto out;
-                       }
-                       ni->ni_rxseqs[tid] = rxseq;
                }
        }
 #ifdef IEEE80211_DEBUG
@@ -1732,7 +1752,7 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m,
                }
                /* XXX: are we sure there is no reallocating after m_pullup? */
 
-               seq = LE_READ_4(mc->mc_seq);
+               seq = le32dec(mc->mc_seq);
                if (IEEE80211_IS_MULTICAST(wh->i_addr1))
                        addr = wh->i_addr3;
                else if (ae == IEEE80211_MESH_AE_01)
@@ -1815,8 +1835,7 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m,
                    (vap->iv_ic->ic_flags & IEEE80211_F_SCAN)) ||
                    ieee80211_msg_dumppkts(vap)) {
                        if_printf(ifp, "received %s from %s rssi %d\n",
-                           ieee80211_mgt_subtype_name[subtype >>
-                           IEEE80211_FC0_SUBTYPE_SHIFT],
+                           ieee80211_mgt_subtype_name(subtype),
                            ether_sprintf(wh->i_addr2), rssi);
                }
 #endif
@@ -1839,7 +1858,7 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m,
                break;
        }
 err:
-       IFNET_STAT_INC(ifp, ierrors, 1);
+       if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 out:
        if (m != NULL) {
                if (need_tap && ieee80211_radiotap_active_vap(vap))
@@ -2098,6 +2117,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
        case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
        case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
        case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+       case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
        case IEEE80211_FC0_SUBTYPE_ATIM:
        case IEEE80211_FC0_SUBTYPE_DISASSOC:
        case IEEE80211_FC0_SUBTYPE_AUTH:
@@ -2156,12 +2176,12 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni,
                        mpie = (const struct ieee80211_meshpeer_ie *) frm;
                        memset(mp, 0, sizeof(*mp));
                        mp->peer_len = mpie->peer_len;
-                       mp->peer_proto = LE_READ_2(&mpie->peer_proto);
-                       mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
+                       mp->peer_proto = le16dec(&mpie->peer_proto);
+                       mp->peer_llinkid = le16dec(&mpie->peer_llinkid);
                        switch (subtype) {
                        case IEEE80211_ACTION_MESHPEERING_CONFIRM:
                                mp->peer_linkid =
-                                   LE_READ_2(&mpie->peer_linkid);
+                                   le16dec(&mpie->peer_linkid);
                                break;
                        case IEEE80211_ACTION_MESHPEERING_CLOSE:
                                /* NB: peer link ID is optional */
@@ -2169,12 +2189,12 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni,
                                    (IEEE80211_MPM_BASE_SZ + 2)) {
                                        mp->peer_linkid = 0;
                                        mp->peer_rcode =
-                                           LE_READ_2(&mpie->peer_linkid);
+                                           le16dec(&mpie->peer_linkid);
                                } else {
                                        mp->peer_linkid =
-                                           LE_READ_2(&mpie->peer_linkid);
+                                           le16dec(&mpie->peer_linkid);
                                        mp->peer_rcode =
-                                           LE_READ_2(&mpie->peer_rcode);
+                                           le16dec(&mpie->peer_rcode);
                                }
                                break;
                        }
@@ -2571,8 +2591,8 @@ mesh_parse_meshgate_action(struct ieee80211_node *ni,
                        ie->gann_hopcount = gannie->gann_hopcount;
                        ie->gann_ttl = gannie->gann_ttl;
                        IEEE80211_ADDR_COPY(ie->gann_addr, gannie->gann_addr);
-                       ie->gann_seq = LE_READ_4(&gannie->gann_seq);
-                       ie->gann_interval = LE_READ_2(&gannie->gann_interval);
+                       ie->gann_seq = le32dec(&gannie->gann_seq);
+                       ie->gann_interval = le16dec(&gannie->gann_interval);
                        break;
                }
                frm += frm[1] + 2;
@@ -2609,10 +2629,16 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni,
        if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie.gann_addr))
                return 0;
 
+#if defined(__DragonFly__)
        IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr,
            "received GANN, meshgate: %s (seq %u)",
            ether_sprintf(ie.gann_addr),
            ie.gann_seq);
+#else
+       IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr,
+           "received GANN, meshgate: %6D (seq %u)", ie.gann_addr, ":",
+           ie.gann_seq);
+#endif
 
        if (ms == NULL)
                return (0);
@@ -2637,8 +2663,14 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni,
                /* this GANN is from a new mesh Gate add it to known table. */
                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie.gann_addr,
                    "stored new GANN information, seq %u.", ie.gann_seq);
+#if defined(__DragonFly__)
                gr = kmalloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
                    M_80211_MESH_GT_RT, M_INTWAIT | M_ZERO);
+#else
+               gr = IEEE80211_MALLOC(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
+                   M_80211_MESH_GT_RT,
+                   IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr);
                TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
        }
@@ -2877,8 +2909,8 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
        uint8_t *frm;
 
        IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
-           "send PEER CLOSE action: localid 0x%x, peerid 0x%x reason %d",
-           args[0], args[1], args[2]);
+           "send PEER CLOSE action: localid 0x%x, peerid 0x%x reason %d (%s)",
+           args[0], args[1], args[2], ieee80211_reason_to_string(args[2]));
 
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
            "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
@@ -3396,8 +3428,13 @@ void
 ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni)
 {
        ni->ni_flags |= IEEE80211_NODE_QOS;
+#if defined(__DragonFly__)
        callout_init_mp(&ni->ni_mltimer);
        callout_init_mp(&ni->ni_mlhtimer);
+#else
+       callout_init(&ni->ni_mltimer, 1);
+       callout_init(&ni->ni_mlhtimer, 1);
+#endif
 }
 
 /*
@@ -3494,7 +3531,12 @@ mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
                        }
                        ireq->i_len = len;
                        /* XXX M_WAIT? */
+#if defined(__DragonFly__)
                        p = kmalloc(len, M_TEMP, M_INTWAIT | M_ZERO);
+#else
+                       p = IEEE80211_MALLOC(len, M_TEMP,
+                               IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                        if (p == NULL)
                                return ENOMEM;
                        off = 0;
@@ -3519,7 +3561,7 @@ mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
                        MESH_RT_UNLOCK(ms);
                        error = copyout(p, (uint8_t *)ireq->i_data,
                            ireq->i_len);
-                       kfree(p, M_TEMP);
+                       IEEE80211_FREE(p, M_TEMP);
                        break;
                case IEEE80211_MESH_RTCMD_FLUSH:
                case IEEE80211_MESH_RTCMD_ADD:
index db85c23..7b083b5 100644 (file)
@@ -131,7 +131,7 @@ monitor_input(struct ieee80211_node *ni, struct mbuf *m,
        struct ieee80211vap *vap = ni->ni_vap;
        struct ifnet *ifp = vap->iv_ifp;
 
-       IFNET_STAT_INC(ifp, ipackets, 1);
+       if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
 
        if (ieee80211_radiotap_active_vap(vap))
                ieee80211_radiotap_rx(vap, m);
index 3839099..59800de 100644 (file)
@@ -114,7 +114,11 @@ ieee80211_node_attach(struct ieee80211com *ic)
            "802.11 staging q");
        ieee80211_node_table_init(ic, &ic->ic_sta, "station",
                IEEE80211_INACT_INIT, ic->ic_max_keyix);
+#if defined(__DragonFly__)
        callout_init_mp(&ic->ic_inact);
+#else
+       callout_init(&ic->ic_inact, 1);
+#endif
        callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
                ieee80211_node_timeout, ic);
 
@@ -172,9 +176,16 @@ ieee80211_node_latevattach(struct ieee80211vap *vap)
                            "WARNING: max aid too small, changed to %d\n",
                            vap->iv_max_aid);
                }
+#if defined(__DragonFly__)
                vap->iv_aid_bitmap = (uint32_t *) kmalloc(
                        howmany(vap->iv_max_aid, 32) * sizeof(uint32_t),
                        M_80211_NODE, M_INTWAIT | M_ZERO);
+#else
+               vap->iv_aid_bitmap = (uint32_t *) IEEE80211_MALLOC(
+                       howmany(vap->iv_max_aid, 32) * sizeof(uint32_t),
+                       M_80211_NODE,
+                       IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                if (vap->iv_aid_bitmap == NULL) {
                        /* XXX no way to recover */
                        kprintf("%s: no memory for AID bitmap, max aid %d!\n",
@@ -199,7 +210,7 @@ ieee80211_node_vdetach(struct ieee80211vap *vap)
                vap->iv_bss = NULL;
        }
        if (vap->iv_aid_bitmap != NULL) {
-               kfree(vap->iv_aid_bitmap, M_80211_NODE);
+               IEEE80211_FREE(vap->iv_aid_bitmap, M_80211_NODE);
                vap->iv_aid_bitmap = NULL;
        }
 }
@@ -329,9 +340,10 @@ ieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan)
        struct ieee80211_node *ni;
 
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-               "%s: creating %s on channel %u\n", __func__,
+               "%s: creating %s on channel %u%c\n", __func__,
                ieee80211_opmode_name[vap->iv_opmode],
-               ieee80211_chan2ieee(ic, chan));
+               ieee80211_chan2ieee(ic, chan),
+               ieee80211_channel_type_char(chan));
 
        ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
        if (ni == NULL) {
@@ -555,31 +567,18 @@ check_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni)
 }
 #endif /* IEEE80211_DEBUG */
  
-/*
- * Handle 802.11 ad hoc network merge.  The
- * convention, set by the Wireless Ethernet Compatibility Alliance
- * (WECA), is that an 802.11 station will change its BSSID to match
- * the "oldest" 802.11 ad hoc network, on the same channel, that
- * has the station's desired SSID.  The "oldest" 802.11 network
- * sends beacons with the greatest TSF timestamp.
- *
- * The caller is assumed to validate TSF's before attempting a merge.
- *
- * Return !0 if the BSSID changed, 0 otherwise.
- */
+
 int
-ieee80211_ibss_merge(struct ieee80211_node *ni)
+ieee80211_ibss_merge_check(struct ieee80211_node *ni)
 {
        struct ieee80211vap *vap = ni->ni_vap;
-#ifdef IEEE80211_DEBUG
-       struct ieee80211com *ic = ni->ni_ic;
-#endif
 
        if (ni == vap->iv_bss ||
            IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
                /* unchanged, nothing to do */
                return 0;
        }
+
        if (!check_bss(vap, ni)) {
                /* capabilities mismatch */
                IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
@@ -591,6 +590,33 @@ ieee80211_ibss_merge(struct ieee80211_node *ni)
                vap->iv_stats.is_ibss_capmismatch++;
                return 0;
        }
+
+       return 1;
+}
+
+/*
+ * Handle 802.11 ad hoc network merge.  The
+ * convention, set by the Wireless Ethernet Compatibility Alliance
+ * (WECA), is that an 802.11 station will change its BSSID to match
+ * the "oldest" 802.11 ad hoc network, on the same channel, that
+ * has the station's desired SSID.  The "oldest" 802.11 network
+ * sends beacons with the greatest TSF timestamp.
+ *
+ * The caller is assumed to validate TSF's before attempting a merge.
+ *
+ * Return !0 if the BSSID changed, 0 otherwise.
+ */
+int
+ieee80211_ibss_merge(struct ieee80211_node *ni)
+{
+#ifdef IEEE80211_DEBUG
+       struct ieee80211vap *vap = ni->ni_vap;
+       struct ieee80211com *ic = ni->ni_ic;
+#endif
+
+       if (! ieee80211_ibss_merge_check(ni))
+               return 0;
+
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
                "%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,
                ether_sprintf(ni->ni_bssid),
@@ -892,8 +918,13 @@ node_alloc(struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
 {
        struct ieee80211_node *ni;
 
+#if defined(__DragonFly__)
        ni = (struct ieee80211_node *) kmalloc(sizeof(struct ieee80211_node),
                M_80211_NODE, M_INTWAIT | M_ZERO);
+#else
+       ni = (struct ieee80211_node *) IEEE80211_MALLOC(sizeof(struct ieee80211_node),
+               M_80211_NODE, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        return ni;
 }
 
@@ -910,11 +941,18 @@ ieee80211_ies_init(struct ieee80211_ies *ies, const uint8_t *data, int len)
        memset(ies, 0, offsetof(struct ieee80211_ies, data));
        if (ies->data != NULL && ies->len != len) {
                /* data size changed */
-               kfree(ies->data, M_80211_NODE_IE);
+               IEEE80211_FREE(ies->data, M_80211_NODE_IE);
                ies->data = NULL;
        }
        if (ies->data == NULL) {
-               ies->data = (uint8_t *) kmalloc(len, M_80211_NODE_IE, M_INTWAIT);
+#if defined(__DragonFly__)
+               ies->data = (uint8_t *) kmalloc(len,
+                       M_80211_NODE_IE, M_INTWAIT | M_ZERO);
+#else
+               ies->data = (uint8_t *) IEEE80211_MALLOC(len, M_80211_NODE_IE,
+                       IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+
+#endif
                if (ies->data == NULL) {
                        ies->len = 0;
                        /* NB: pointers have already been zero'd above */
@@ -933,7 +971,7 @@ void
 ieee80211_ies_cleanup(struct ieee80211_ies *ies)
 {
        if (ies->data != NULL)
-               kfree(ies->data, M_80211_NODE_IE);
+               IEEE80211_FREE(ies->data, M_80211_NODE_IE);
 }
 
 /*
@@ -1012,8 +1050,8 @@ node_cleanup(struct ieee80211_node *ni)
        if (ni->ni_flags & IEEE80211_NODE_HT)
                ieee80211_ht_node_cleanup(ni);
 #ifdef IEEE80211_SUPPORT_SUPERG
-       else if (ni->ni_ath_flags & IEEE80211_NODE_ATH)
-               ieee80211_ff_node_cleanup(ni);
+       /* Always do FF node cleanup; for A-MSDU */
+       ieee80211_ff_node_cleanup(ni);
 #endif
 #ifdef IEEE80211_SUPPORT_MESH
        /*
@@ -1045,7 +1083,7 @@ node_cleanup(struct ieee80211_node *ni)
 
        ni->ni_associd = 0;
        if (ni->ni_challenge != NULL) {
-               kfree(ni->ni_challenge, M_80211_NODE);
+               IEEE80211_FREE(ni->ni_challenge, M_80211_NODE);
                ni->ni_challenge = NULL;
        }
        /*
@@ -1080,7 +1118,7 @@ node_free(struct ieee80211_node *ni)
        ic->ic_node_cleanup(ni);
        ieee80211_ies_cleanup(&ni->ni_ies);
        ieee80211_psq_cleanup(&ni->ni_psq);
-       kfree(ni, M_80211_NODE);
+       IEEE80211_FREE(ni, M_80211_NODE);
 }
 
 static void
@@ -1918,9 +1956,16 @@ ieee80211_node_table_init(struct ieee80211com *ic,
        nt->nt_inact_init = inact;
        nt->nt_keyixmax = keyixmax;
        if (nt->nt_keyixmax > 0) {
+#if defined(__DragonFly__)
                nt->nt_keyixmap = (struct ieee80211_node **) kmalloc(
                        keyixmax * sizeof(struct ieee80211_node *),
                        M_80211_NODE, M_INTWAIT | M_ZERO);
+#else
+               nt->nt_keyixmap = (struct ieee80211_node **) IEEE80211_MALLOC(
+                       keyixmax * sizeof(struct ieee80211_node *),
+                       M_80211_NODE,
+                       IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
                if (nt->nt_keyixmap == NULL)
                        ic_printf(ic,
                            "Cannot allocate key index map with %u entries\n",
@@ -1979,7 +2024,7 @@ ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
                                kprintf("%s: %s[%u] still active\n", __func__,
                                        nt->nt_name, i);
 #endif
-               kfree(nt->nt_keyixmap, M_80211_NODE);
+               IEEE80211_FREE(nt->nt_keyixmap, M_80211_NODE);
                nt->nt_keyixmap = NULL;
        }
        IEEE80211_NODE_ITERATE_LOCK_DESTROY(nt);
@@ -2199,7 +2244,7 @@ ieee80211_node_timeout(void *arg)
         * Defer timeout processing if a channel switch is pending.
         * We typically need to be mute so not doing things that
         * might generate frames is good to handle in one place.
-        * Supressing the station timeout processing may extend the
+        * Suppressing the station timeout processing may extend the
         * lifetime of inactive stations (by not decrementing their
         * idle counters) but this should be ok unless the CSA is
         * active for an unusually long time.
@@ -2318,8 +2363,13 @@ ieee80211_iterate_nodes(struct ieee80211_node_table *nt,
                max_aid = vap->iv_max_aid;
 
        size = max_aid * sizeof(struct ieee80211_node *);
+#if defined(__DragonFly__)
        ni_arr = (struct ieee80211_node **) kmalloc(size, M_80211_NODE,
-           M_INTWAIT | M_ZERO);
+               M_INTWAIT | M_ZERO);
+#else
+       ni_arr = (struct ieee80211_node **) IEEE80211_MALLOC(size, M_80211_NODE,
+               IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+#endif
        if (ni_arr == NULL)
                return;
 
@@ -2342,7 +2392,7 @@ ieee80211_iterate_nodes(struct ieee80211_node_table *nt,
        }
 
 done:
-       kfree(ni_arr, M_80211_NODE);
+       IEEE80211_FREE(ni_arr, M_80211_NODE);
 }
 
 void
@@ -2635,7 +2685,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");
@@ -2680,7 +2730,6 @@ ieee80211_node_leave(struct ieee80211_node *ni)
 
        IEEE80211_LOCK(ic);
        IEEE80211_AID_CLR(vap, ni->ni_associd);
-       ni->ni_associd = 0;
        vap->iv_sta_assoc--;
        ic->ic_sta_assoc--;
 
index 371d79a..6440d14 100644 (file)
@@ -33,8 +33,9 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h> 
-#include <sys/mbuf.h>   
 #include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>   
 #include <sys/endian.h>
 
 #include <sys/socket.h>
@@ -75,23 +76,14 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip6.h>
 #endif
 
-/*#include <security/mac/