/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
C | 676 lines | 489 code | 82 blank | 105 comment | 61 complexity | 7b2713b4ae1e031c177843bf0d4259ef MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * This file is created to process BA Action Frame. According to 802.11 spec,
- * there are 3 BA action types at all. And as BA is related to TS, this part
- * need some struture defined in QOS side code. Also TX RX is going to be
- * resturctured, so how to send ADDBAREQ ADDBARSP and DELBA packet is still
- * on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
- */
- #include "ieee80211.h"
- #include "rtl819x_BA.h"
- /*
- * Activate BA entry. And if Time is nozero, start timer.
- */
- void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
- {
- pBA->bValid = true;
- if(Time != 0)
- mod_timer(&pBA->Timer, jiffies + MSECS(Time));
- }
- /*
- * deactivate BA entry, including its timer.
- */
- void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
- {
- pBA->bValid = false;
- del_timer_sync(&pBA->Timer);
- }
- /*
- * deactivete BA entry in Tx Ts, and send DELBA.
- */
- u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
- {
- PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
- PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
- u8 bSendDELBA = false;
- // Delete pending BA
- if(pPendingBa->bValid)
- {
- DeActivateBAEntry(ieee, pPendingBa);
- bSendDELBA = true;
- }
- // Delete admitted BA
- if(pAdmittedBa->bValid)
- {
- DeActivateBAEntry(ieee, pAdmittedBa);
- bSendDELBA = true;
- }
- return bSendDELBA;
- }
- /*
- * deactivete BA entry in Tx Ts, and send DELBA.
- */
- u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
- {
- PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
- u8 bSendDELBA = false;
- if(pBa->bValid)
- {
- DeActivateBAEntry(ieee, pBa);
- bSendDELBA = true;
- }
- return bSendDELBA;
- }
- /*
- * reset BA entry
- */
- void ResetBaEntry( PBA_RECORD pBA)
- {
- pBA->bValid = false;
- pBA->BaParamSet.shortData = 0;
- pBA->BaTimeoutValue = 0;
- pBA->DialogToken = 0;
- pBA->BaStartSeqCtrl.ShortData = 0;
- }
- /*
- * construct ADDBAREQ and ADDBARSP frame here together.
- * return constructed skb to xmit
- */
- static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
- {
- struct sk_buff *skb = NULL;
- struct ieee80211_hdr_3addr* BAReq = NULL;
- u8* tag = NULL;
- u16 tmp = 0;
- u16 len = ieee->tx_headroom + 9;
- //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
- if (pBA == NULL||ieee == NULL)
- {
- IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
- return NULL;
- }
- skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
- if (skb == NULL)
- {
- IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
- return NULL;
- }
- memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
- skb_reserve(skb, ieee->tx_headroom);
- BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
- memcpy(BAReq->addr1, Dst, ETH_ALEN);
- memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
- BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
- //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
- tag = (u8*)skb_put(skb, 9);
- *tag ++= ACT_CAT_BA;
- *tag ++= type;
- // Dialog Token
- *tag ++= pBA->DialogToken;
- if (ACT_ADDBARSP == type)
- {
- // Status Code
- printk("=====>to send ADDBARSP\n");
- tmp = cpu_to_le16(StatusCode);
- memcpy(tag, (u8*)&tmp, 2);
- tag += 2;
- }
- // BA Parameter Set
- tmp = cpu_to_le16(pBA->BaParamSet.shortData);
- memcpy(tag, (u8*)&tmp, 2);
- tag += 2;
- // BA Timeout Value
- tmp = cpu_to_le16(pBA->BaTimeoutValue);
- memcpy(tag, (u8*)&tmp, 2);
- tag += 2;
- if (ACT_ADDBAREQ == type)
- {
- // BA Start SeqCtrl
- memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
- tag += 2;
- }
- IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
- return skb;
- //return NULL;
- }
- /*
- * construct DELBA frame
- */
- static struct sk_buff* ieee80211_DELBA(
- struct ieee80211_device* ieee,
- u8* dst,
- PBA_RECORD pBA,
- TR_SELECT TxRxSelect,
- u16 ReasonCode
- )
- {
- DELBA_PARAM_SET DelbaParamSet;
- struct sk_buff *skb = NULL;
- struct ieee80211_hdr_3addr* Delba = NULL;
- u8* tag = NULL;
- u16 tmp = 0;
- //len = head len + DELBA Parameter Set(2) + Reason Code(2)
- u16 len = 6 + ieee->tx_headroom;
- if (net_ratelimit())
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
- memset(&DelbaParamSet, 0, 2);
- DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
- DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
- skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
- if (skb == NULL)
- {
- IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
- return NULL;
- }
- // memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
- skb_reserve(skb, ieee->tx_headroom);
- Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
- memcpy(Delba->addr1, dst, ETH_ALEN);
- memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
- Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
- tag = (u8*)skb_put(skb, 6);
- *tag ++= ACT_CAT_BA;
- *tag ++= ACT_DELBA;
- // DELBA Parameter Set
- tmp = cpu_to_le16(DelbaParamSet.shortData);
- memcpy(tag, (u8*)&tmp, 2);
- tag += 2;
- // Reason Code
- tmp = cpu_to_le16(ReasonCode);
- memcpy(tag, (u8*)&tmp, 2);
- tag += 2;
- IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
- if (net_ratelimit())
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
- return skb;
- }
- /*
- * send ADDBAReq frame out
- * If any possible, please hide pBA in ieee.
- * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
- */
- void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
- {
- struct sk_buff *skb = NULL;
- skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
- if (skb)
- {
- softmac_mgmt_xmit(skb, ieee);
- //add statistic needed here.
- //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
- //WB
- }
- else
- {
- IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
- }
- }
- /*
- * send ADDBARSP frame out
- * If any possible, please hide pBA in ieee.
- * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does