ieee80211_ht.c (193840) | ieee80211_ht.c (195377) |
---|---|
1/*- 2 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27#ifdef __FreeBSD__ | 1/*- 2 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27#ifdef __FreeBSD__ |
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ht.c 193840 2009-06-09 16:32:07Z sam $"); | 28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ht.c 195377 2009-07-05 17:59:19Z sam $"); |
29#endif 30 31/* 32 * IEEE 802.11n protocol support. 33 */ 34 35#include "opt_inet.h" 36#include "opt_wlan.h" --- 5 unchanged lines hidden (view full) --- 42 43#include <sys/socket.h> 44 45#include <net/if.h> 46#include <net/if_media.h> 47#include <net/ethernet.h> 48 49#include <net80211/ieee80211_var.h> | 29#endif 30 31/* 32 * IEEE 802.11n protocol support. 33 */ 34 35#include "opt_inet.h" 36#include "opt_wlan.h" --- 5 unchanged lines hidden (view full) --- 42 43#include <sys/socket.h> 44 45#include <net/if.h> 46#include <net/if_media.h> 47#include <net/ethernet.h> 48 49#include <net80211/ieee80211_var.h> |
50#include <net80211/ieee80211_action.h> |
|
50#include <net80211/ieee80211_input.h> 51 52/* define here, used throughout file */ 53#define MS(_v, _f) (((_v) & _f) >> _f##_S) 54#define SM(_v, _f) (((_v) << _f##_S) & _f) 55 56const struct ieee80211_mcs_rates ieee80211_htrates[16] = { 57 { 13, 14, 27, 30 }, /* MCS 0 */ --- 41 unchanged lines hidden (view full) --- 99 "ADDBA request backoff (ms)"); 100static int ieee80211_addba_maxtries = 3;/* max ADDBA requests before backoff */ 101SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLTYPE_INT | CTLFLAG_RW, 102 &ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff"); 103 104static int ieee80211_bar_timeout = -1; /* timeout waiting for BAR response */ 105static int ieee80211_bar_maxtries = 50;/* max BAR requests before DELBA */ 106 | 51#include <net80211/ieee80211_input.h> 52 53/* define here, used throughout file */ 54#define MS(_v, _f) (((_v) & _f) >> _f##_S) 55#define SM(_v, _f) (((_v) << _f##_S) & _f) 56 57const struct ieee80211_mcs_rates ieee80211_htrates[16] = { 58 { 13, 14, 27, 30 }, /* MCS 0 */ --- 41 unchanged lines hidden (view full) --- 100 "ADDBA request backoff (ms)"); 101static int ieee80211_addba_maxtries = 3;/* max ADDBA requests before backoff */ 102SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLTYPE_INT | CTLFLAG_RW, 103 &ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff"); 104 105static int ieee80211_bar_timeout = -1; /* timeout waiting for BAR response */ 106static int ieee80211_bar_maxtries = 50;/* max BAR requests before DELBA */ 107 |
107/* 108 * Setup HT parameters that depends on the clock frequency. 109 */ | 108static ieee80211_recv_action_func ht_recv_action_ba_addba_request; 109static ieee80211_recv_action_func ht_recv_action_ba_addba_response; 110static ieee80211_recv_action_func ht_recv_action_ba_delba; 111static ieee80211_recv_action_func ht_recv_action_ht_mimopwrsave; 112static ieee80211_recv_action_func ht_recv_action_ht_txchwidth; 113 114static ieee80211_send_action_func ht_send_action_ba_addba; 115static ieee80211_send_action_func ht_send_action_ba_delba; 116static ieee80211_send_action_func ht_send_action_ht_txchwidth; 117 |
110static void | 118static void |
111ieee80211_ht_setup(void) | 119ieee80211_ht_init(void) |
112{ | 120{ |
121 /* 122 * Setup HT parameters that depends on the clock frequency. 123 */ |
|
113#ifdef IEEE80211_AMPDU_AGE 114 ieee80211_ampdu_age = msecs_to_ticks(500); 115#endif 116 ieee80211_addba_timeout = msecs_to_ticks(250); 117 ieee80211_addba_backoff = msecs_to_ticks(10*1000); 118 ieee80211_bar_timeout = msecs_to_ticks(250); | 124#ifdef IEEE80211_AMPDU_AGE 125 ieee80211_ampdu_age = msecs_to_ticks(500); 126#endif 127 ieee80211_addba_timeout = msecs_to_ticks(250); 128 ieee80211_addba_backoff = msecs_to_ticks(10*1000); 129 ieee80211_bar_timeout = msecs_to_ticks(250); |
130 /* 131 * Register action frame handlers. 132 */ 133 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 134 IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_recv_action_ba_addba_request); 135 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 136 IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_recv_action_ba_addba_response); 137 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 138 IEEE80211_ACTION_BA_DELBA, ht_recv_action_ba_delba); 139 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT, 140 IEEE80211_ACTION_HT_MIMOPWRSAVE, ht_recv_action_ht_mimopwrsave); 141 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT, 142 IEEE80211_ACTION_HT_TXCHWIDTH, ht_recv_action_ht_txchwidth); 143 144 ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 145 IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_send_action_ba_addba); 146 ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 147 IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_send_action_ba_addba); 148 ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 149 IEEE80211_ACTION_BA_DELBA, ht_send_action_ba_delba); 150 ieee80211_send_action_register(IEEE80211_ACTION_CAT_HT, 151 IEEE80211_ACTION_HT_TXCHWIDTH, ht_send_action_ht_txchwidth); |
|
119} | 152} |
120SYSINIT(wlan_ht, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_ht_setup, NULL); | 153SYSINIT(wlan_ht, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_ht_init, NULL); |
121 122static int ieee80211_ampdu_enable(struct ieee80211_node *ni, 123 struct ieee80211_tx_ampdu *tap); 124static int ieee80211_addba_request(struct ieee80211_node *ni, 125 struct ieee80211_tx_ampdu *tap, 126 int dialogtoken, int baparamset, int batimeout); 127static int ieee80211_addba_response(struct ieee80211_node *ni, 128 struct ieee80211_tx_ampdu *tap, 129 int code, int baparamset, int batimeout); 130static void ieee80211_addba_stop(struct ieee80211_node *ni, 131 struct ieee80211_tx_ampdu *tap); | 154 155static int ieee80211_ampdu_enable(struct ieee80211_node *ni, 156 struct ieee80211_tx_ampdu *tap); 157static int ieee80211_addba_request(struct ieee80211_node *ni, 158 struct ieee80211_tx_ampdu *tap, 159 int dialogtoken, int baparamset, int batimeout); 160static int ieee80211_addba_response(struct ieee80211_node *ni, 161 struct ieee80211_tx_ampdu *tap, 162 int code, int baparamset, int batimeout); 163static void ieee80211_addba_stop(struct ieee80211_node *ni, 164 struct ieee80211_tx_ampdu *tap); |
132static void ieee80211_aggr_recv_action(struct ieee80211_node *ni, 133 const uint8_t *frm, const uint8_t *efrm); | |
134static void ieee80211_bar_response(struct ieee80211_node *ni, 135 struct ieee80211_tx_ampdu *tap, int status); 136static void ampdu_tx_stop(struct ieee80211_tx_ampdu *tap); 137static void bar_stop_timer(struct ieee80211_tx_ampdu *tap); 138static int ampdu_rx_start(struct ieee80211_node *, struct ieee80211_rx_ampdu *, 139 int baparamset, int batimeout, int baseqctl); 140static void ampdu_rx_stop(struct ieee80211_node *, struct ieee80211_rx_ampdu *); 141 142void 143ieee80211_ht_attach(struct ieee80211com *ic) 144{ 145 /* setup default aggregation policy */ | 165static void ieee80211_bar_response(struct ieee80211_node *ni, 166 struct ieee80211_tx_ampdu *tap, int status); 167static void ampdu_tx_stop(struct ieee80211_tx_ampdu *tap); 168static void bar_stop_timer(struct ieee80211_tx_ampdu *tap); 169static int ampdu_rx_start(struct ieee80211_node *, struct ieee80211_rx_ampdu *, 170 int baparamset, int batimeout, int baseqctl); 171static void ampdu_rx_stop(struct ieee80211_node *, struct ieee80211_rx_ampdu *); 172 173void 174ieee80211_ht_attach(struct ieee80211com *ic) 175{ 176 /* setup default aggregation policy */ |
146 ic->ic_recv_action = ieee80211_aggr_recv_action; | 177 ic->ic_recv_action = ieee80211_recv_action; |
147 ic->ic_send_action = ieee80211_send_action; 148 ic->ic_ampdu_enable = ieee80211_ampdu_enable; 149 ic->ic_addba_request = ieee80211_addba_request; 150 ic->ic_addba_response = ieee80211_addba_response; 151 ic->ic_addba_stop = ieee80211_addba_stop; 152 ic->ic_bar_response = ieee80211_bar_response; 153 ic->ic_ampdu_rx_start = ampdu_rx_start; 154 ic->ic_ampdu_rx_stop = ampdu_rx_stop; --- 1420 unchanged lines hidden (view full) --- 1575} 1576 1577/* 1578 * Process a received action frame using the default aggregation 1579 * policy. We intercept ADDBA-related frames and use them to 1580 * update our aggregation state. All other frames are passed up 1581 * for processing by ieee80211_recv_action. 1582 */ | 178 ic->ic_send_action = ieee80211_send_action; 179 ic->ic_ampdu_enable = ieee80211_ampdu_enable; 180 ic->ic_addba_request = ieee80211_addba_request; 181 ic->ic_addba_response = ieee80211_addba_response; 182 ic->ic_addba_stop = ieee80211_addba_stop; 183 ic->ic_bar_response = ieee80211_bar_response; 184 ic->ic_ampdu_rx_start = ampdu_rx_start; 185 ic->ic_ampdu_rx_stop = ampdu_rx_stop; --- 1420 unchanged lines hidden (view full) --- 1606} 1607 1608/* 1609 * Process a received action frame using the default aggregation 1610 * policy. We intercept ADDBA-related frames and use them to 1611 * update our aggregation state. All other frames are passed up 1612 * for processing by ieee80211_recv_action. 1613 */ |
1583static void 1584ieee80211_aggr_recv_action(struct ieee80211_node *ni, | 1614static int 1615ht_recv_action_ba_addba_request(struct ieee80211_node *ni, 1616 const struct ieee80211_frame *wh, |
1585 const uint8_t *frm, const uint8_t *efrm) 1586{ 1587 struct ieee80211com *ic = ni->ni_ic; 1588 struct ieee80211vap *vap = ni->ni_vap; | 1617 const uint8_t *frm, const uint8_t *efrm) 1618{ 1619 struct ieee80211com *ic = ni->ni_ic; 1620 struct ieee80211vap *vap = ni->ni_vap; |
1589 const struct ieee80211_action *ia; | |
1590 struct ieee80211_rx_ampdu *rap; | 1621 struct ieee80211_rx_ampdu *rap; |
1591 struct ieee80211_tx_ampdu *tap; 1592 uint8_t dialogtoken, policy; 1593 uint16_t baparamset, batimeout, baseqctl, code; | 1622 uint8_t dialogtoken; 1623 uint16_t baparamset, batimeout, baseqctl; |
1594 uint16_t args[4]; | 1624 uint16_t args[4]; |
1595 int tid, ac, bufsiz; | 1625 int tid; |
1596 | 1626 |
1597 ia = (const struct ieee80211_action *) frm; 1598 switch (ia->ia_category) { 1599 case IEEE80211_ACTION_CAT_BA: 1600 switch (ia->ia_action) { 1601 case IEEE80211_ACTION_BA_ADDBA_REQUEST: 1602 dialogtoken = frm[2]; 1603 baparamset = LE_READ_2(frm+3); 1604 batimeout = LE_READ_2(frm+5); 1605 baseqctl = LE_READ_2(frm+7); | 1627 dialogtoken = frm[2]; 1628 baparamset = LE_READ_2(frm+3); 1629 batimeout = LE_READ_2(frm+5); 1630 baseqctl = LE_READ_2(frm+7); |
1606 | 1631 |
1607 tid = MS(baparamset, IEEE80211_BAPS_TID); | 1632 tid = MS(baparamset, IEEE80211_BAPS_TID); |
1608 | 1633 |
1609 IEEE80211_NOTE(vap, 1610 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1611 "recv ADDBA request: dialogtoken %u " 1612 "baparamset 0x%x (tid %d bufsiz %d) batimeout %d " 1613 "baseqctl %d:%d", 1614 dialogtoken, baparamset, 1615 tid, MS(baparamset, IEEE80211_BAPS_BUFSIZ), 1616 batimeout, 1617 MS(baseqctl, IEEE80211_BASEQ_START), 1618 MS(baseqctl, IEEE80211_BASEQ_FRAG)); | 1634 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1635 "recv ADDBA request: dialogtoken %u baparamset 0x%x " 1636 "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d", 1637 dialogtoken, baparamset, 1638 tid, MS(baparamset, IEEE80211_BAPS_BUFSIZ), 1639 batimeout, 1640 MS(baseqctl, IEEE80211_BASEQ_START), 1641 MS(baseqctl, IEEE80211_BASEQ_FRAG)); |
1619 | 1642 |
1620 rap = &ni->ni_rx_ampdu[tid]; | 1643 rap = &ni->ni_rx_ampdu[tid]; |
1621 | 1644 |
1622 /* Send ADDBA response */ 1623 args[0] = dialogtoken; 1624 /* 1625 * NB: We ack only if the sta associated with HT and 1626 * the ap is configured to do AMPDU rx (the latter 1627 * violates the 11n spec and is mostly for testing). 1628 */ 1629 if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) && 1630 (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) { 1631 /* XXX handle ampdu_rx_start failure */ 1632 ic->ic_ampdu_rx_start(ni, rap, 1633 baparamset, batimeout, baseqctl); | 1645 /* Send ADDBA response */ 1646 args[0] = dialogtoken; 1647 /* 1648 * NB: We ack only if the sta associated with HT and 1649 * the ap is configured to do AMPDU rx (the latter 1650 * violates the 11n spec and is mostly for testing). 1651 */ 1652 if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) && 1653 (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) { 1654 /* XXX handle ampdu_rx_start failure */ 1655 ic->ic_ampdu_rx_start(ni, rap, 1656 baparamset, batimeout, baseqctl); |
1634 | 1657 |
1635 args[1] = IEEE80211_STATUS_SUCCESS; 1636 } else { 1637 IEEE80211_NOTE(vap, 1638 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1639 ni, "reject ADDBA request: %s", 1640 ni->ni_flags & IEEE80211_NODE_AMPDU_RX ? 1641 "administratively disabled" : 1642 "not negotiated for station"); 1643 vap->iv_stats.is_addba_reject++; 1644 args[1] = IEEE80211_STATUS_UNSPECIFIED; 1645 } 1646 /* XXX honor rap flags? */ 1647 args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE 1648 | SM(tid, IEEE80211_BAPS_TID) 1649 | SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) 1650 ; 1651 args[3] = 0; 1652 ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, 1653 IEEE80211_ACTION_BA_ADDBA_RESPONSE, args); 1654 return; | 1658 args[1] = IEEE80211_STATUS_SUCCESS; 1659 } else { 1660 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1661 ni, "reject ADDBA request: %s", 1662 ni->ni_flags & IEEE80211_NODE_AMPDU_RX ? 1663 "administratively disabled" : 1664 "not negotiated for station"); 1665 vap->iv_stats.is_addba_reject++; 1666 args[1] = IEEE80211_STATUS_UNSPECIFIED; 1667 } 1668 /* XXX honor rap flags? */ 1669 args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE 1670 | SM(tid, IEEE80211_BAPS_TID) 1671 | SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) 1672 ; 1673 args[3] = 0; 1674 ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, 1675 IEEE80211_ACTION_BA_ADDBA_RESPONSE, args); 1676 return 0; 1677} |
1655 | 1678 |
1656 case IEEE80211_ACTION_BA_ADDBA_RESPONSE: 1657 dialogtoken = frm[2]; 1658 code = LE_READ_2(frm+3); 1659 baparamset = LE_READ_2(frm+5); 1660 tid = MS(baparamset, IEEE80211_BAPS_TID); 1661 bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); 1662 policy = MS(baparamset, IEEE80211_BAPS_POLICY); 1663 batimeout = LE_READ_2(frm+7); | 1679static int 1680ht_recv_action_ba_addba_response(struct ieee80211_node *ni, 1681 const struct ieee80211_frame *wh, 1682 const uint8_t *frm, const uint8_t *efrm) 1683{ 1684 struct ieee80211com *ic = ni->ni_ic; 1685 struct ieee80211vap *vap = ni->ni_vap; 1686 struct ieee80211_tx_ampdu *tap; 1687 uint8_t dialogtoken, policy; 1688 uint16_t baparamset, batimeout, code; 1689 int tid, ac, bufsiz; |
1664 | 1690 |
1665 ac = TID_TO_WME_AC(tid); 1666 tap = &ni->ni_tx_ampdu[ac]; 1667 if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { 1668 IEEE80211_DISCARD_MAC(vap, 1669 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1670 ni->ni_macaddr, "ADDBA response", 1671 "no pending ADDBA, tid %d dialogtoken %u " 1672 "code %d", tid, dialogtoken, code); 1673 vap->iv_stats.is_addba_norequest++; 1674 return; 1675 } 1676 if (dialogtoken != tap->txa_token) { 1677 IEEE80211_DISCARD_MAC(vap, 1678 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1679 ni->ni_macaddr, "ADDBA response", 1680 "dialogtoken mismatch: waiting for %d, " 1681 "received %d, tid %d code %d", 1682 tap->txa_token, dialogtoken, tid, code); 1683 vap->iv_stats.is_addba_badtoken++; 1684 return; 1685 } 1686 /* NB: assumes IEEE80211_AGGR_IMMEDIATE is 1 */ 1687 if (policy != (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE)) { 1688 IEEE80211_DISCARD_MAC(vap, 1689 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1690 ni->ni_macaddr, "ADDBA response", 1691 "policy mismatch: expecting %s, " 1692 "received %s, tid %d code %d", 1693 tap->txa_flags & IEEE80211_AGGR_IMMEDIATE, 1694 policy, tid, code); 1695 vap->iv_stats.is_addba_badpolicy++; 1696 return; 1697 } | 1691 dialogtoken = frm[2]; 1692 code = LE_READ_2(frm+3); 1693 baparamset = LE_READ_2(frm+5); 1694 tid = MS(baparamset, IEEE80211_BAPS_TID); 1695 bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); 1696 policy = MS(baparamset, IEEE80211_BAPS_POLICY); 1697 batimeout = LE_READ_2(frm+7); 1698 1699 ac = TID_TO_WME_AC(tid); 1700 tap = &ni->ni_tx_ampdu[ac]; 1701 if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { 1702 IEEE80211_DISCARD_MAC(vap, 1703 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1704 ni->ni_macaddr, "ADDBA response", 1705 "no pending ADDBA, tid %d dialogtoken %u " 1706 "code %d", tid, dialogtoken, code); 1707 vap->iv_stats.is_addba_norequest++; 1708 return 0; 1709 } 1710 if (dialogtoken != tap->txa_token) { 1711 IEEE80211_DISCARD_MAC(vap, 1712 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1713 ni->ni_macaddr, "ADDBA response", 1714 "dialogtoken mismatch: waiting for %d, " 1715 "received %d, tid %d code %d", 1716 tap->txa_token, dialogtoken, tid, code); 1717 vap->iv_stats.is_addba_badtoken++; 1718 return 0; 1719 } 1720 /* NB: assumes IEEE80211_AGGR_IMMEDIATE is 1 */ 1721 if (policy != (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE)) { 1722 IEEE80211_DISCARD_MAC(vap, 1723 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1724 ni->ni_macaddr, "ADDBA response", 1725 "policy mismatch: expecting %s, " 1726 "received %s, tid %d code %d", 1727 tap->txa_flags & IEEE80211_AGGR_IMMEDIATE, 1728 policy, tid, code); 1729 vap->iv_stats.is_addba_badpolicy++; 1730 return 0; 1731 } |
1698#if 0 | 1732#if 0 |
1699 /* XXX we take MIN in ieee80211_addba_response */ 1700 if (bufsiz > IEEE80211_AGGR_BAWMAX) { 1701 IEEE80211_DISCARD_MAC(vap, 1702 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1703 ni->ni_macaddr, "ADDBA response", 1704 "BA window too large: max %d, " 1705 "received %d, tid %d code %d", 1706 bufsiz, IEEE80211_AGGR_BAWMAX, tid, code); 1707 vap->iv_stats.is_addba_badbawinsize++; 1708 return; 1709 } | 1733 /* XXX we take MIN in ieee80211_addba_response */ 1734 if (bufsiz > IEEE80211_AGGR_BAWMAX) { 1735 IEEE80211_DISCARD_MAC(vap, 1736 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1737 ni->ni_macaddr, "ADDBA response", 1738 "BA window too large: max %d, " 1739 "received %d, tid %d code %d", 1740 bufsiz, IEEE80211_AGGR_BAWMAX, tid, code); 1741 vap->iv_stats.is_addba_badbawinsize++; 1742 return 0; 1743 } |
1710#endif | 1744#endif |
1711 IEEE80211_NOTE(vap, 1712 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1713 "recv ADDBA response: dialogtoken %u code %d " 1714 "baparamset 0x%x (tid %d bufsiz %d) batimeout %d", 1715 dialogtoken, code, baparamset, tid, bufsiz, 1716 batimeout); 1717 ic->ic_addba_response(ni, tap, 1718 code, baparamset, batimeout); 1719 return; | 1745 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1746 "recv ADDBA response: dialogtoken %u code %d " 1747 "baparamset 0x%x (tid %d bufsiz %d) batimeout %d", 1748 dialogtoken, code, baparamset, tid, bufsiz, 1749 batimeout); 1750 ic->ic_addba_response(ni, tap, code, baparamset, batimeout); 1751 return 0; 1752} |
1720 | 1753 |
1721 case IEEE80211_ACTION_BA_DELBA: 1722 baparamset = LE_READ_2(frm+2); 1723 code = LE_READ_2(frm+4); | 1754static int 1755ht_recv_action_ba_delba(struct ieee80211_node *ni, 1756 const struct ieee80211_frame *wh, 1757 const uint8_t *frm, const uint8_t *efrm) 1758{ 1759 struct ieee80211com *ic = ni->ni_ic; 1760 struct ieee80211_rx_ampdu *rap; 1761 struct ieee80211_tx_ampdu *tap; 1762 uint16_t baparamset, code; 1763 int tid, ac; |
1724 | 1764 |
1725 tid = MS(baparamset, IEEE80211_DELBAPS_TID); | 1765 baparamset = LE_READ_2(frm+2); 1766 code = LE_READ_2(frm+4); |
1726 | 1767 |
1727 IEEE80211_NOTE(vap, 1728 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1729 "recv DELBA: baparamset 0x%x (tid %d initiator %d) " 1730 "code %d", baparamset, tid, 1731 MS(baparamset, IEEE80211_DELBAPS_INIT), code); | 1768 tid = MS(baparamset, IEEE80211_DELBAPS_TID); |
1732 | 1769 |
1733 if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) { 1734 ac = TID_TO_WME_AC(tid); 1735 tap = &ni->ni_tx_ampdu[ac]; 1736 ic->ic_addba_stop(ni, tap); 1737 } else { 1738 rap = &ni->ni_rx_ampdu[tid]; 1739 ic->ic_ampdu_rx_stop(ni, rap); 1740 } 1741 return; 1742 } 1743 break; | 1770 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1771 "recv DELBA: baparamset 0x%x (tid %d initiator %d) " 1772 "code %d", baparamset, tid, 1773 MS(baparamset, IEEE80211_DELBAPS_INIT), code); 1774 1775 if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) { 1776 ac = TID_TO_WME_AC(tid); 1777 tap = &ni->ni_tx_ampdu[ac]; 1778 ic->ic_addba_stop(ni, tap); 1779 } else { 1780 rap = &ni->ni_rx_ampdu[tid]; 1781 ic->ic_ampdu_rx_stop(ni, rap); |
1744 } | 1782 } |
1745 ieee80211_recv_action(ni, frm, efrm); | 1783 return 0; |
1746} 1747 | 1784} 1785 |
1748/* 1749 * Process a received 802.11n action frame. 1750 * Aggregation-related frames are assumed to be handled 1751 * already; we handle any other frames we can, otherwise 1752 * complain about being unsupported (with debugging). 1753 */ 1754void 1755ieee80211_recv_action(struct ieee80211_node *ni, | 1786static int 1787ht_recv_action_ht_txchwidth(struct ieee80211_node *ni, 1788 const struct ieee80211_frame *wh, |
1756 const uint8_t *frm, const uint8_t *efrm) 1757{ | 1789 const uint8_t *frm, const uint8_t *efrm) 1790{ |
1758 struct ieee80211vap *vap = ni->ni_vap; 1759 const struct ieee80211_action *ia; | |
1760 int chw; 1761 | 1791 int chw; 1792 |
1762 ia = (const struct ieee80211_action *) frm; 1763 switch (ia->ia_category) { 1764 case IEEE80211_ACTION_CAT_BA: 1765 IEEE80211_NOTE(vap, 1766 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1767 "%s: BA action %d not implemented", __func__, 1768 ia->ia_action); 1769 vap->iv_stats.is_rx_mgtdiscard++; 1770 break; 1771 case IEEE80211_ACTION_CAT_HT: 1772 switch (ia->ia_action) { 1773 case IEEE80211_ACTION_HT_TXCHWIDTH: 1774 chw = frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040 ? 40 : 20; 1775 IEEE80211_NOTE(vap, 1776 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1777 "%s: HT txchwidth, width %d%s", 1778 __func__, chw, ni->ni_chw != chw ? "*" : ""); 1779 if (chw != ni->ni_chw) { 1780 ni->ni_chw = chw; 1781 /* XXX notify on change */ 1782 } 1783 break; 1784 case IEEE80211_ACTION_HT_MIMOPWRSAVE: { 1785 const struct ieee80211_action_ht_mimopowersave *mps = 1786 (const struct ieee80211_action_ht_mimopowersave *) ia; 1787 /* XXX check iv_htcaps */ 1788 if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA) 1789 ni->ni_flags |= IEEE80211_NODE_MIMO_PS; 1790 else 1791 ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS; 1792 if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_MODE) 1793 ni->ni_flags |= IEEE80211_NODE_MIMO_RTS; 1794 else 1795 ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS; 1796 /* XXX notify on change */ 1797 IEEE80211_NOTE(vap, 1798 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1799 "%s: HT MIMO PS (%s%s)", __func__, 1800 (ni->ni_flags & IEEE80211_NODE_MIMO_PS) ? 1801 "on" : "off", 1802 (ni->ni_flags & IEEE80211_NODE_MIMO_RTS) ? 1803 "+rts" : "" 1804 ); 1805 break; 1806 } 1807 default: 1808 IEEE80211_NOTE(vap, 1809 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1810 "%s: HT action %d not implemented", __func__, 1811 ia->ia_action); 1812 vap->iv_stats.is_rx_mgtdiscard++; 1813 break; 1814 } 1815 break; 1816 default: 1817 IEEE80211_NOTE(vap, 1818 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1819 "%s: category %d not implemented", __func__, 1820 ia->ia_category); 1821 vap->iv_stats.is_rx_mgtdiscard++; 1822 break; | 1793 chw = (frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040) ? 40 : 20; 1794 1795 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1796 "%s: HT txchwidth, width %d%s", 1797 __func__, chw, ni->ni_chw != chw ? "*" : ""); 1798 if (chw != ni->ni_chw) { 1799 ni->ni_chw = chw; 1800 /* XXX notify on change */ |
1823 } | 1801 } |
1802 return 0; |
|
1824} 1825 | 1803} 1804 |
1805static int 1806ht_recv_action_ht_mimopwrsave(struct ieee80211_node *ni, 1807 const struct ieee80211_frame *wh, 1808 const uint8_t *frm, const uint8_t *efrm) 1809{ 1810 const struct ieee80211_action_ht_mimopowersave *mps = 1811 (const struct ieee80211_action_ht_mimopowersave *) frm; 1812 1813 /* XXX check iv_htcaps */ 1814 if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA) 1815 ni->ni_flags |= IEEE80211_NODE_MIMO_PS; 1816 else 1817 ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS; 1818 if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_MODE) 1819 ni->ni_flags |= IEEE80211_NODE_MIMO_RTS; 1820 else 1821 ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS; 1822 /* XXX notify on change */ 1823 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 1824 "%s: HT MIMO PS (%s%s)", __func__, 1825 (ni->ni_flags & IEEE80211_NODE_MIMO_PS) ? "on" : "off", 1826 (ni->ni_flags & IEEE80211_NODE_MIMO_RTS) ? "+rts" : "" 1827 ); 1828 return 0; 1829} 1830 |
|
1826/* 1827 * Transmit processing. 1828 */ 1829 1830/* 1831 * Check if A-MPDU should be requested/enabled for a stream. 1832 * We require a traffic rate above a per-AC threshold and we 1833 * also handle backoff from previous failed attempts. --- 98 unchanged lines hidden (view full) --- 1932 ni, "%s: stop BA stream for AC %d (reason %d)", 1933 __func__, tap->txa_ac, reason); 1934 vap->iv_stats.is_ampdu_stop++; 1935 1936 ic->ic_addba_stop(ni, tap); 1937 args[0] = WME_AC_TO_TID(tap->txa_ac); 1938 args[1] = IEEE80211_DELBAPS_INIT; 1939 args[2] = reason; /* XXX reason code */ | 1831/* 1832 * Transmit processing. 1833 */ 1834 1835/* 1836 * Check if A-MPDU should be requested/enabled for a stream. 1837 * We require a traffic rate above a per-AC threshold and we 1838 * also handle backoff from previous failed attempts. --- 98 unchanged lines hidden (view full) --- 1937 ni, "%s: stop BA stream for AC %d (reason %d)", 1938 __func__, tap->txa_ac, reason); 1939 vap->iv_stats.is_ampdu_stop++; 1940 1941 ic->ic_addba_stop(ni, tap); 1942 args[0] = WME_AC_TO_TID(tap->txa_ac); 1943 args[1] = IEEE80211_DELBAPS_INIT; 1944 args[2] = reason; /* XXX reason code */ |
1940 ieee80211_send_action(ni, IEEE80211_ACTION_CAT_BA, | 1945 ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, |
1941 IEEE80211_ACTION_BA_DELBA, args); 1942 } else { 1943 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1944 ni, "%s: BA stream for AC %d not running (reason %d)", 1945 __func__, tap->txa_ac, reason); 1946 vap->iv_stats.is_ampdu_stop_failed++; 1947 } 1948} --- 161 unchanged lines hidden (view full) --- 2110 bar_start_timer(tap); 2111 return 0; 2112bad: 2113 ieee80211_free_node(ni); 2114 return ret; 2115#undef senderr 2116} 2117 | 1946 IEEE80211_ACTION_BA_DELBA, args); 1947 } else { 1948 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 1949 ni, "%s: BA stream for AC %d not running (reason %d)", 1950 __func__, tap->txa_ac, reason); 1951 vap->iv_stats.is_ampdu_stop_failed++; 1952 } 1953} --- 161 unchanged lines hidden (view full) --- 2115 bar_start_timer(tap); 2116 return 0; 2117bad: 2118 ieee80211_free_node(ni); 2119 return ret; 2120#undef senderr 2121} 2122 |
2118/* 2119 * Send an action management frame. The arguments are stuff 2120 * into a frame without inspection; the caller is assumed to 2121 * prepare them carefully (e.g. based on the aggregation state). 2122 */ 2123int 2124ieee80211_send_action(struct ieee80211_node *ni, 2125 int category, int action, uint16_t args[4]) | 2123static int 2124ht_action_output(struct ieee80211_node *ni, struct mbuf *m) |
2126{ | 2125{ |
2127#define senderr(_x, _v) do { vap->iv_stats._v++; ret = _x; goto bad; } while (0) | 2126 struct ieee80211_bpf_params params; 2127 2128 memset(¶ms, 0, sizeof(params)); 2129 params.ibp_pri = WME_AC_VO; 2130 params.ibp_rate0 = ni->ni_txparms->mgmtrate; 2131 /* NB: we know all frames are unicast */ 2132 params.ibp_try0 = ni->ni_txparms->maxretry; 2133 params.ibp_power = ni->ni_txpower; 2134 return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION, 2135 ¶ms); 2136} 2137 |
2128#define ADDSHORT(frm, v) do { \ 2129 frm[0] = (v) & 0xff; \ 2130 frm[1] = (v) >> 8; \ 2131 frm += 2; \ 2132} while (0) | 2138#define ADDSHORT(frm, v) do { \ 2139 frm[0] = (v) & 0xff; \ 2140 frm[1] = (v) >> 8; \ 2141 frm += 2; \ 2142} while (0) |
2143 2144/* 2145 * Send an action management frame. The arguments are stuff 2146 * into a frame without inspection; the caller is assumed to 2147 * prepare them carefully (e.g. based on the aggregation state). 2148 */ 2149static int 2150ht_send_action_ba_addba(struct ieee80211_node *ni, 2151 int category, int action, void *arg0) 2152{ |
|
2133 struct ieee80211vap *vap = ni->ni_vap; 2134 struct ieee80211com *ic = ni->ni_ic; | 2153 struct ieee80211vap *vap = ni->ni_vap; 2154 struct ieee80211com *ic = ni->ni_ic; |
2135 struct ieee80211_bpf_params params; | 2155 uint16_t *args = arg0; |
2136 struct mbuf *m; 2137 uint8_t *frm; | 2156 struct mbuf *m; 2157 uint8_t *frm; |
2138 uint16_t baparamset; 2139 int ret; | |
2140 | 2158 |
2141 KASSERT(ni != NULL, ("null node")); | 2159 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2160 "send ADDBA %s: dialogtoken %d " 2161 "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x", 2162 (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ? 2163 "request" : "response", 2164 args[0], args[1], MS(args[1], IEEE80211_BAPS_TID), 2165 args[2], args[3]); |
2142 | 2166 |
2143 /* 2144 * Hold a reference on the node so it doesn't go away until after 2145 * the xmit is complete all the way in the driver. On error we 2146 * will remove our reference. 2147 */ | |
2148 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, | 2167 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, |
2149 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", 2150 __func__, __LINE__, 2151 ni, ether_sprintf(ni->ni_macaddr), 2152 ieee80211_node_refcnt(ni)+1); | 2168 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, 2169 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); |
2153 ieee80211_ref_node(ni); 2154 2155 m = ieee80211_getmgtframe(&frm, | 2170 ieee80211_ref_node(ni); 2171 2172 m = ieee80211_getmgtframe(&frm, |
2156 ic->ic_headroom + sizeof(struct ieee80211_frame), 2157 sizeof(uint16_t) /* action+category */ 2158 /* XXX may action payload */ 2159 + sizeof(struct ieee80211_action_ba_addbaresponse) | 2173 ic->ic_headroom + sizeof(struct ieee80211_frame), 2174 sizeof(uint16_t) /* action+category */ 2175 /* XXX may action payload */ 2176 + sizeof(struct ieee80211_action_ba_addbaresponse) |
2160 ); | 2177 ); |
2161 if (m == NULL) 2162 senderr(ENOMEM, is_tx_nobuf); | 2178 if (m != NULL) { 2179 *frm++ = category; 2180 *frm++ = action; 2181 *frm++ = args[0]; /* dialog token */ 2182 ADDSHORT(frm, args[1]); /* baparamset */ 2183 ADDSHORT(frm, args[2]); /* batimeout */ 2184 if (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) 2185 ADDSHORT(frm, args[3]); /* baseqctl */ 2186 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); 2187 return ht_action_output(ni, m); 2188 } else { 2189 vap->iv_stats.is_tx_nobuf++; 2190 ieee80211_free_node(ni); 2191 return ENOMEM; 2192 } 2193} |
2163 | 2194 |
2164 *frm++ = category; 2165 *frm++ = action; 2166 switch (category) { 2167 case IEEE80211_ACTION_CAT_BA: 2168 switch (action) { 2169 case IEEE80211_ACTION_BA_ADDBA_REQUEST: 2170 IEEE80211_NOTE(vap, 2171 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2172 "send ADDBA request: dialogtoken %d " 2173 "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x", 2174 args[0], args[1], MS(args[1], IEEE80211_BAPS_TID), 2175 args[2], args[3]); | 2195static int 2196ht_send_action_ba_delba(struct ieee80211_node *ni, 2197 int category, int action, void *arg0) 2198{ 2199 struct ieee80211vap *vap = ni->ni_vap; 2200 struct ieee80211com *ic = ni->ni_ic; 2201 uint16_t *args = arg0; 2202 struct mbuf *m; 2203 uint16_t baparamset; 2204 uint8_t *frm; |
2176 | 2205 |
2177 *frm++ = args[0]; /* dialog token */ 2178 ADDSHORT(frm, args[1]); /* baparamset */ 2179 ADDSHORT(frm, args[2]); /* batimeout */ 2180 ADDSHORT(frm, args[3]); /* baseqctl */ 2181 break; 2182 case IEEE80211_ACTION_BA_ADDBA_RESPONSE: 2183 IEEE80211_NOTE(vap, 2184 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2185 "send ADDBA response: dialogtoken %d status %d " 2186 "baparamset 0x%x (tid %d) batimeout %d", 2187 args[0], args[1], args[2], 2188 MS(args[2], IEEE80211_BAPS_TID), args[3]); | 2206 baparamset = SM(args[0], IEEE80211_DELBAPS_TID) 2207 | args[1] 2208 ; 2209 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2210 "send DELBA action: tid %d, initiator %d reason %d", 2211 args[0], args[1], args[2]); |
2189 | 2212 |
2190 *frm++ = args[0]; /* dialog token */ 2191 ADDSHORT(frm, args[1]); /* statuscode */ 2192 ADDSHORT(frm, args[2]); /* baparamset */ 2193 ADDSHORT(frm, args[3]); /* batimeout */ 2194 break; 2195 case IEEE80211_ACTION_BA_DELBA: 2196 /* XXX */ 2197 baparamset = SM(args[0], IEEE80211_DELBAPS_TID) 2198 | args[1] 2199 ; 2200 ADDSHORT(frm, baparamset); 2201 ADDSHORT(frm, args[2]); /* reason code */ | 2213 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 2214 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, 2215 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); 2216 ieee80211_ref_node(ni); |
2202 | 2217 |
2203 IEEE80211_NOTE(vap, 2204 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2205 "send DELBA action: tid %d, initiator %d reason %d", 2206 args[0], args[1], args[2]); 2207 break; 2208 default: 2209 goto badaction; 2210 } 2211 break; 2212 case IEEE80211_ACTION_CAT_HT: 2213 switch (action) { 2214 case IEEE80211_ACTION_HT_TXCHWIDTH: 2215 IEEE80211_NOTE(vap, 2216 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, 2217 ni, "send HT txchwidth: width %d", 2218 IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 40 : 20 2219 ); 2220 *frm++ = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 2221 IEEE80211_A_HT_TXCHWIDTH_2040 : 2222 IEEE80211_A_HT_TXCHWIDTH_20; 2223 break; 2224 default: 2225 goto badaction; 2226 } 2227 break; 2228 default: 2229 badaction: 2230 IEEE80211_NOTE(vap, 2231 IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2232 "%s: unsupported category %d action %d", __func__, 2233 category, action); 2234 senderr(EINVAL, is_tx_unknownmgt); 2235 /* NOTREACHED */ | 2218 m = ieee80211_getmgtframe(&frm, 2219 ic->ic_headroom + sizeof(struct ieee80211_frame), 2220 sizeof(uint16_t) /* action+category */ 2221 /* XXX may action payload */ 2222 + sizeof(struct ieee80211_action_ba_addbaresponse) 2223 ); 2224 if (m != NULL) { 2225 *frm++ = category; 2226 *frm++ = action; 2227 ADDSHORT(frm, baparamset); 2228 ADDSHORT(frm, args[2]); /* reason code */ 2229 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); 2230 return ht_action_output(ni, m); 2231 } else { 2232 vap->iv_stats.is_tx_nobuf++; 2233 ieee80211_free_node(ni); 2234 return ENOMEM; |
2236 } | 2235 } |
2237 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); | 2236} |
2238 | 2237 |
2239 memset(¶ms, 0, sizeof(params)); 2240 params.ibp_pri = WME_AC_VO; 2241 params.ibp_rate0 = ni->ni_txparms->mgmtrate; 2242 /* NB: we know all frames are unicast */ 2243 params.ibp_try0 = ni->ni_txparms->maxretry; 2244 params.ibp_power = ni->ni_txpower; 2245 return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION, 2246 ¶ms); 2247bad: 2248 ieee80211_free_node(ni); 2249 if (m != NULL) 2250 m_freem(m); 2251 return ret; 2252#undef ADDSHORT 2253#undef senderr | 2238static int 2239ht_send_action_ht_txchwidth(struct ieee80211_node *ni, 2240 int category, int action, void *arg0) 2241{ 2242 struct ieee80211vap *vap = ni->ni_vap; 2243 struct ieee80211com *ic = ni->ni_ic; 2244 struct mbuf *m; 2245 uint8_t *frm; 2246 2247 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, 2248 "send HT txchwidth: width %d", 2249 IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 40 : 20); 2250 2251 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 2252 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, 2253 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); 2254 ieee80211_ref_node(ni); 2255 2256 m = ieee80211_getmgtframe(&frm, 2257 ic->ic_headroom + sizeof(struct ieee80211_frame), 2258 sizeof(uint16_t) /* action+category */ 2259 /* XXX may action payload */ 2260 + sizeof(struct ieee80211_action_ba_addbaresponse) 2261 ); 2262 if (m != NULL) { 2263 *frm++ = category; 2264 *frm++ = action; 2265 *frm++ = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 2266 IEEE80211_A_HT_TXCHWIDTH_2040 : 2267 IEEE80211_A_HT_TXCHWIDTH_20; 2268 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); 2269 return ht_action_output(ni, m); 2270 } else { 2271 vap->iv_stats.is_tx_nobuf++; 2272 ieee80211_free_node(ni); 2273 return ENOMEM; 2274 } |
2254} | 2275} |
2276#undef ADDSHORT |
|
2255 2256/* 2257 * Construct the MCS bit mask for inclusion 2258 * in an HT information element. 2259 */ 2260static void 2261ieee80211_set_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs) 2262{ --- 237 unchanged lines hidden --- | 2277 2278/* 2279 * Construct the MCS bit mask for inclusion 2280 * in an HT information element. 2281 */ 2282static void 2283ieee80211_set_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs) 2284{ --- 237 unchanged lines hidden --- |