On Mon, 2007-11-26 at 16:14 +0200, Ron Rindjunsky wrote: > This patch adds the capability to identify and answer an add block ACK > request. > As this series of patches only adds HT handling with no aggregations, > (A-MPDU aggregations acceptance is not obligatory according to 802.11n > draft) we are currently sending back a refusal upon this request. > > Signed-off-by: Ron Rindjunsky <ron.rindjunsky@xxxxxxxxx> Acked-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> Do you have a plan already on how to fill in that TODO? Just curious. > --- > net/mac80211/ieee80211_sta.c | 124 ++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 124 insertions(+), 0 deletions(-) > > diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c > index 2e23137..0f133e3 100644 > --- a/net/mac80211/ieee80211_sta.c > +++ b/net/mac80211/ieee80211_sta.c > @@ -57,6 +57,13 @@ > > #define ERP_INFO_USE_PROTECTION BIT(1) > > +/* mgmt header + 1 byte action code */ > +#define IEEE80211_MIN_ACTION_SIZE (24 + 1) > + > +#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 > +#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C > +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 > + > static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, > u8 *ssid, size_t ssid_len); > static struct ieee80211_sta_bss * > @@ -991,6 +998,91 @@ static void ieee80211_auth_challenge(struct net_device *dev, > elems.challenge_len + 2, 1); > } > > +static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, > + u8 dialog_token, u16 status, u16 policy, > + u16 buf_size, u16 timeout) > +{ > + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); > + struct ieee80211_if_sta *ifsta = &sdata->u.sta; > + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); > + struct sk_buff *skb; > + struct ieee80211_mgmt *mgmt; > + u16 capab; > + > + skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); > + if (!skb) { > + printk(KERN_DEBUG "%s: failed to allocate buffer " > + "for addba resp frame\n", dev->name); > + return; > + } > + > + skb_reserve(skb, local->hw.extra_tx_headroom); > + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); > + memset(mgmt, 0, 24); > + memcpy(mgmt->da, da, ETH_ALEN); > + memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); > + if (sdata->type == IEEE80211_IF_TYPE_AP) > + memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); > + else > + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); > + mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, > + IEEE80211_STYPE_ACTION); > + > + skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); > + mgmt->u.action.category = WLAN_CATEGORY_BACK; > + mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; > + mgmt->u.action.u.addba_resp.dialog_token = dialog_token; > + > + capab = (u16)(policy << 1); /* bit 1 aggregation policy */ > + capab |= (u16)(tid << 2); /* bit 5:2 TID number */ > + capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ > + > + mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); > + mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); > + mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); > + > + ieee80211_sta_tx(dev, skb, 0); > + > + return; > +} > + > +static void ieee80211_sta_process_addba_request(struct net_device *dev, > + struct ieee80211_mgmt *mgmt, > + size_t len) > +{ > + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); > + struct sta_info *sta; > + u16 capab, tid, timeout, ba_policy, buf_size, status; > + u8 dialog_token; > + > + sta = sta_info_get(local, mgmt->sa); > + if (!sta) > + return; > + > + /* extract session parameters from addba request frame */ > + dialog_token = mgmt->u.action.u.addba_req.dialog_token; > + timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); > + > + capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); > + ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; > + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; > + buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; > + > + /* TODO - currently aggregation is declined (A-MPDU add BA request > + * acceptance is not obligatory by 802.11n draft), but here is > + * the entry point for dealing with it */ > +#ifdef MAC80211_HT_DEBUG > + if (net_ratelimit()) > + printk(KERN_DEBUG "Add Block Ack request arrived," > + " currently denying it\n"); > +#endif /* MAC80211_HT_DEBUG */ > + > + status = WLAN_STATUS_REQUEST_DECLINED; > + > + ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token, > + status, 1, buf_size, timeout); > + sta_info_put(sta); > +} > > static void ieee80211_rx_mgmt_auth(struct net_device *dev, > struct ieee80211_if_sta *ifsta, > @@ -1864,6 +1956,34 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, > ieee80211_sta_tx(dev, skb, 0); > } > > +void ieee80211_rx_mgmt_action(struct net_device *dev, > + struct ieee80211_if_sta *ifsta, > + struct ieee80211_mgmt *mgmt, > + size_t len) > +{ > + if (len < IEEE80211_MIN_ACTION_SIZE) > + return; > + > + switch (mgmt->u.action.category) { > + case WLAN_CATEGORY_BACK: > + switch (mgmt->u.action.u.addba_req.action_code) { > + case WLAN_ACTION_ADDBA_REQ: > + if (len < (IEEE80211_MIN_ACTION_SIZE + > + sizeof(mgmt->u.action.u.addba_req))) > + break; > + ieee80211_sta_process_addba_request(dev, mgmt, len); > + break; > + default: > + if (net_ratelimit()) > + printk(KERN_DEBUG "%s: received unsupported BACK\n", > + dev->name); > + break; > + } > + break; > + default: > + break; > + } > +} > > void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, > struct ieee80211_rx_status *rx_status) > @@ -1893,6 +2013,7 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, > case IEEE80211_STYPE_REASSOC_RESP: > case IEEE80211_STYPE_DEAUTH: > case IEEE80211_STYPE_DISASSOC: > + case IEEE80211_STYPE_ACTION: > skb_queue_tail(&ifsta->skb_queue, skb); > queue_work(local->hw.workqueue, &ifsta->work); > return; > @@ -1950,6 +2071,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, > case IEEE80211_STYPE_DISASSOC: > ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); > break; > + case IEEE80211_STYPE_ACTION: > + ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len); > + break; > } > > kfree_skb(skb);
Attachment:
signature.asc
Description: This is a digitally signed message part