root/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ActivateBAEntry
  2. DeActivateBAEntry
  3. TxTsDeleteBA
  4. RxTsDeleteBA
  5. ResetBaEntry
  6. ieee80211_ADDBA
  7. ieee80211_DELBA
  8. ieee80211_send_ADDBAReq
  9. ieee80211_send_ADDBARsp
  10. ieee80211_send_DELBA
  11. ieee80211_rx_ADDBAReq
  12. ieee80211_rx_ADDBARsp
  13. ieee80211_rx_DELBA
  14. TsInitAddBA
  15. TsInitDelBA
  16. BaSetupTimeOut
  17. TxBaInactTimeout
  18. RxBaInactTimeout

   1 // SPDX-License-Identifier: GPL-2.0
   2 /********************************************************************************************************************************
   3  * 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
   4  * related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send
   5  * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
   6  * WB 2008-05-27
   7  * *****************************************************************************************************************************/
   8 #include <asm/byteorder.h>
   9 #include <asm/unaligned.h>
  10 #include "ieee80211.h"
  11 #include "rtl819x_BA.h"
  12 
  13 /********************************************************************************************************************
  14  *function:  Activate BA entry. And if Time is nozero, start timer.
  15  *   input:  struct ba_record          *pBA  //BA entry to be enabled
  16  *           u16                        Time //indicate time delay.
  17  *  output:  none
  18  ********************************************************************************************************************/
  19 static void ActivateBAEntry(struct ieee80211_device *ieee, struct ba_record *pBA, u16 Time)
  20 {
  21         pBA->valid = true;
  22         if (Time != 0)
  23                 mod_timer(&pBA->timer, jiffies + msecs_to_jiffies(Time));
  24 }
  25 
  26 /********************************************************************************************************************
  27  *function:  deactivate BA entry, including its timer.
  28  *   input:  struct ba_record       *pBA  //BA entry to be disabled
  29  *  output:  none
  30  ********************************************************************************************************************/
  31 static void DeActivateBAEntry(struct ieee80211_device *ieee, struct ba_record *pBA)
  32 {
  33         pBA->valid = false;
  34         del_timer_sync(&pBA->timer);
  35 }
  36 /********************************************************************************************************************
  37  *function: deactivete BA entry in Tx Ts, and send DELBA.
  38  *   input:
  39  *           struct tx_ts_record *pTxTs //Tx Ts which is to deactivate BA entry.
  40  *  output:  none
  41  *  notice:  As struct tx_ts_record * structure will be defined in QOS, so wait to be merged. //FIXME
  42  ********************************************************************************************************************/
  43 static u8 TxTsDeleteBA(struct ieee80211_device *ieee, struct tx_ts_record *pTxTs)
  44 {
  45         struct ba_record *pAdmittedBa = &pTxTs->tx_admitted_ba_record;  //These two BA entries must exist in TS structure
  46         struct ba_record *pPendingBa = &pTxTs->tx_pending_ba_record;
  47         u8                      bSendDELBA = false;
  48 
  49         // Delete pending BA
  50         if (pPendingBa->valid) {
  51                 DeActivateBAEntry(ieee, pPendingBa);
  52                 bSendDELBA = true;
  53         }
  54 
  55         // Delete admitted BA
  56         if (pAdmittedBa->valid) {
  57                 DeActivateBAEntry(ieee, pAdmittedBa);
  58                 bSendDELBA = true;
  59         }
  60 
  61         return bSendDELBA;
  62 }
  63 
  64 /********************************************************************************************************************
  65  *function: deactivete BA entry in Tx Ts, and send DELBA.
  66  *   input:
  67  *           struct rx_ts_record  *pRxTs //Rx Ts which is to deactivate BA entry.
  68  *  output:  none
  69  *  notice:  As struct rx_ts_record * structure will be defined in QOS, so wait to be merged. //FIXME, same with above
  70  ********************************************************************************************************************/
  71 static u8 RxTsDeleteBA(struct ieee80211_device *ieee, struct rx_ts_record *pRxTs)
  72 {
  73         struct ba_record       *pBa = &pRxTs->rx_admitted_ba_record;
  74         u8                      bSendDELBA = false;
  75 
  76         if (pBa->valid) {
  77                 DeActivateBAEntry(ieee, pBa);
  78                 bSendDELBA = true;
  79         }
  80 
  81         return bSendDELBA;
  82 }
  83 
  84 /********************************************************************************************************************
  85  *function: reset BA entry
  86  *   input:
  87  *           struct ba_record *pBA //entry to be reset
  88  *  output:  none
  89  ********************************************************************************************************************/
  90 void ResetBaEntry(struct ba_record *pBA)
  91 {
  92         pBA->valid                      = false;
  93         pBA->param_set.short_data       = 0;
  94         pBA->timeout_value              = 0;
  95         pBA->dialog_token               = 0;
  96         pBA->start_seq_ctrl.short_data  = 0;
  97 }
  98 //These functions need porting here or not?
  99 /*******************************************************************************************************************************
 100  *function:  construct ADDBAREQ and ADDBARSP frame here together.
 101  *   input:  u8*                Dst     //ADDBA frame's destination
 102  *           struct ba_record  *pBA     //BA_RECORD entry which stores the necessary information for BA.
 103  *           u16                StatusCode  //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
 104  *           u8                 type    //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
 105  *  output:  none
 106  *  return:  sk_buff*           skb     //return constructed skb to xmit
 107  *******************************************************************************************************************************/
 108 static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, struct ba_record *pBA, u16 StatusCode, u8 type)
 109 {
 110         struct sk_buff *skb = NULL;
 111         struct rtl_80211_hdr_3addr *BAReq = NULL;
 112         u8 *tag = NULL;
 113         u16 len = ieee->tx_headroom + 9;
 114         //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
 115         IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev);
 116         if (pBA == NULL) {
 117                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n");
 118                 return NULL;
 119         }
 120         skb = dev_alloc_skb(len + sizeof(struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
 121         if (!skb)
 122                 return NULL;
 123 
 124         memset(skb->data, 0, sizeof(struct rtl_80211_hdr_3addr));       //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
 125         skb_reserve(skb, ieee->tx_headroom);
 126 
 127         BAReq = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 128 
 129         memcpy(BAReq->addr1, Dst, ETH_ALEN);
 130         memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
 131 
 132         memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
 133 
 134         BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
 135 
 136         //tag += sizeof( struct rtl_80211_hdr_3addr); //move to action field
 137         tag = skb_put(skb, 9);
 138         *tag++ = ACT_CAT_BA;
 139         *tag++ = type;
 140         // Dialog Token
 141         *tag++ = pBA->dialog_token;
 142 
 143         if (ACT_ADDBARSP == type) {
 144                 // Status Code
 145                 netdev_info(ieee->dev, "=====>to send ADDBARSP\n");
 146 
 147                 put_unaligned_le16(StatusCode, tag);
 148                 tag += 2;
 149         }
 150         // BA Parameter Set
 151 
 152         put_unaligned_le16(pBA->param_set.short_data, tag);
 153         tag += 2;
 154         // BA Timeout Value
 155 
 156         put_unaligned_le16(pBA->timeout_value, tag);
 157         tag += 2;
 158 
 159         if (ACT_ADDBAREQ == type) {
 160         // BA Start SeqCtrl
 161                 memcpy(tag, (u8 *)&(pBA->start_seq_ctrl), 2);
 162                 tag += 2;
 163         }
 164 
 165         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
 166         return skb;
 167         //return NULL;
 168 }
 169 
 170 
 171 /********************************************************************************************************************
 172  *function:  construct DELBA frame
 173  *   input:  u8*                dst     //DELBA frame's destination
 174  *           struct ba_record  *pBA     //BA_RECORD entry which stores the necessary information for BA
 175  *           enum tr_select     TxRxSelect  //TX RX direction
 176  *           u16                ReasonCode  //status code.
 177  *  output:  none
 178  *  return:  sk_buff*           skb     //return constructed skb to xmit
 179  ********************************************************************************************************************/
 180 static struct sk_buff *ieee80211_DELBA(
 181         struct ieee80211_device  *ieee,
 182         u8                       *dst,
 183         struct ba_record         *pBA,
 184         enum tr_select           TxRxSelect,
 185         u16                      ReasonCode
 186         )
 187 {
 188         union delba_param_set   DelbaParamSet;
 189         struct sk_buff *skb = NULL;
 190         struct rtl_80211_hdr_3addr *Delba = NULL;
 191         u8 *tag = NULL;
 192         //len = head len + DELBA Parameter Set(2) + Reason Code(2)
 193         u16 len = 6 + ieee->tx_headroom;
 194 
 195         if (net_ratelimit())
 196                 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
 197                                 "========>%s(), ReasonCode(%d) sentd to:%pM\n",
 198                                 __func__, ReasonCode, dst);
 199 
 200         memset(&DelbaParamSet, 0, 2);
 201 
 202         DelbaParamSet.field.initiator   = (TxRxSelect == TX_DIR) ? 1 : 0;
 203         DelbaParamSet.field.tid = pBA->param_set.field.tid;
 204 
 205         skb = dev_alloc_skb(len + sizeof(struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
 206         if (!skb)
 207                 return NULL;
 208 //      memset(skb->data, 0, len+sizeof( struct rtl_80211_hdr_3addr));
 209         skb_reserve(skb, ieee->tx_headroom);
 210 
 211         Delba = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 212 
 213         memcpy(Delba->addr1, dst, ETH_ALEN);
 214         memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
 215         memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
 216         Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
 217 
 218         tag = skb_put(skb, 6);
 219 
 220         *tag++ = ACT_CAT_BA;
 221         *tag++ = ACT_DELBA;
 222 
 223         // DELBA Parameter Set
 224 
 225         put_unaligned_le16(DelbaParamSet.short_data, tag);
 226         tag += 2;
 227         // Reason Code
 228 
 229         put_unaligned_le16(ReasonCode, tag);
 230         tag += 2;
 231 
 232         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
 233         if (net_ratelimit())
 234                 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
 235                                 "<=====%s()\n", __func__);
 236         return skb;
 237 }
 238 
 239 /********************************************************************************************************************
 240  *function: send ADDBAReq frame out
 241  *   input:  u8*                dst     //ADDBAReq frame's destination
 242  *           struct ba_record  *pBA     //BA_RECORD entry which stores the necessary information for BA
 243  *  output:  none
 244  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 245  ********************************************************************************************************************/
 246 static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee,
 247                                     u8 *dst, struct ba_record *pBA)
 248 {
 249         struct sk_buff *skb;
 250         skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
 251 
 252         if (skb) {
 253                 softmac_mgmt_xmit(skb, ieee);
 254                 //add statistic needed here.
 255                 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
 256                 //WB
 257         } else {
 258                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 259         }
 260 }
 261 
 262 /********************************************************************************************************************
 263  *function: send ADDBARSP frame out
 264  *   input:  u8*                dst     //DELBA frame's destination
 265  *           struct ba_record  *pBA     //BA_RECORD entry which stores the necessary information for BA
 266  *           u16                StatusCode //RSP StatusCode
 267  *  output:  none
 268  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 269  ********************************************************************************************************************/
 270 static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst,
 271                                     struct ba_record *pBA, u16 StatusCode)
 272 {
 273         struct sk_buff *skb;
 274         skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
 275         if (skb) {
 276                 softmac_mgmt_xmit(skb, ieee);
 277                 //same above
 278         } else {
 279                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 280         }
 281 
 282         return;
 283 
 284 }
 285 /********************************************************************************************************************
 286  *function: send ADDBARSP frame out
 287  *   input:  u8*                dst     //DELBA frame's destination
 288  *           struct ba_record  *pBA     //BA_RECORD entry which stores the necessary information for BA
 289  *           enum tr_select     TxRxSelect //TX or RX
 290  *           u16                ReasonCode //DEL ReasonCode
 291  *  output:  none
 292  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 293  ********************************************************************************************************************/
 294 
 295 static void ieee80211_send_DELBA(struct ieee80211_device *ieee, u8 *dst,
 296                                  struct ba_record *pBA, enum tr_select TxRxSelect,
 297                                  u16 ReasonCode)
 298 {
 299         struct sk_buff *skb;
 300         skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
 301         if (skb) {
 302                 softmac_mgmt_xmit(skb, ieee);
 303                 //same above
 304         } else {
 305                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 306         }
 307 }
 308 
 309 /********************************************************************************************************************
 310  *function: RX ADDBAReq
 311  *   input:  struct sk_buff *   skb     //incoming ADDBAReq skb.
 312  *  return:  0(pass), other(fail)
 313  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
 314  ********************************************************************************************************************/
 315 int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
 316 {
 317         struct rtl_80211_hdr_3addr *req = NULL;
 318         u16 rc = 0;
 319         u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
 320         struct ba_record *pBA = NULL;
 321         union ba_param_set     *pBaParamSet = NULL;
 322         u16 *pBaTimeoutVal = NULL;
 323         union sequence_control *pBaStartSeqCtrl = NULL;
 324         struct rx_ts_record  *pTS = NULL;
 325 
 326         if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
 327                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
 328                                 " Invalid skb len in BAREQ(%d / %zu)\n",
 329                                 skb->len,
 330                                 (sizeof(struct rtl_80211_hdr_3addr) + 9));
 331                 return -1;
 332         }
 333 
 334         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
 335 
 336         req = (struct rtl_80211_hdr_3addr *)skb->data;
 337         tag = (u8 *)req;
 338         dst = &req->addr2[0];
 339         tag += sizeof(struct rtl_80211_hdr_3addr);
 340         pDialogToken = tag + 2;  //category+action
 341         pBaParamSet = (union ba_param_set *)(tag + 3);   //+DialogToken
 342         pBaTimeoutVal = (u16 *)(tag + 5);
 343         pBaStartSeqCtrl = (union sequence_control *)(req + 7);
 344 
 345         netdev_info(ieee->dev, "====================>rx ADDBAREQ from :%pM\n", dst);
 346 //some other capability is not ready now.
 347         if ((ieee->current_network.qos_data.active == 0) ||
 348                 (!ieee->pHTInfo->bCurrentHTSupport)) //||
 349         //      (!ieee->pStaQos->bEnableRxImmBA)        )
 350         {
 351                 rc = ADDBA_STATUS_REFUSED;
 352                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
 353                 goto OnADDBAReq_Fail;
 354         }
 355         // Search for related traffic stream.
 356         // If there is no matched TS, reject the ADDBA request.
 357         if (!GetTs(
 358                         ieee,
 359                         (struct ts_common_info **)(&pTS),
 360                         dst,
 361                         (u8)(pBaParamSet->field.tid),
 362                         RX_DIR,
 363                         true)) {
 364                 rc = ADDBA_STATUS_REFUSED;
 365                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
 366                 goto OnADDBAReq_Fail;
 367         }
 368         pBA = &pTS->rx_admitted_ba_record;
 369         // To Determine the ADDBA Req content
 370         // We can do much more check here, including buffer_size, AMSDU_Support, Policy, StartSeqCtrl...
 371         // I want to check StartSeqCtrl to make sure when we start aggregation!!!
 372         //
 373         if (pBaParamSet->field.ba_policy == BA_POLICY_DELAYED) {
 374                 rc = ADDBA_STATUS_INVALID_PARAM;
 375                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
 376                 goto OnADDBAReq_Fail;
 377         }
 378                 // Admit the ADDBA Request
 379         //
 380         DeActivateBAEntry(ieee, pBA);
 381         pBA->dialog_token = *pDialogToken;
 382         pBA->param_set = *pBaParamSet;
 383         pBA->timeout_value = *pBaTimeoutVal;
 384         pBA->start_seq_ctrl = *pBaStartSeqCtrl;
 385         //for half N mode we only aggregate 1 frame
 386         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
 387                 pBA->param_set.field.buffer_size = 1;
 388         else
 389                 pBA->param_set.field.buffer_size = 32;
 390         ActivateBAEntry(ieee, pBA, pBA->timeout_value);
 391         ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
 392 
 393         // End of procedure.
 394         return 0;
 395 
 396 OnADDBAReq_Fail:
 397         {
 398                 struct ba_record        BA;
 399                 BA.param_set = *pBaParamSet;
 400                 BA.timeout_value = *pBaTimeoutVal;
 401                 BA.dialog_token = *pDialogToken;
 402                 BA.param_set.field.ba_policy = BA_POLICY_IMMEDIATE;
 403                 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
 404                 return 0; //we send RSP out.
 405         }
 406 
 407 }
 408 
 409 /********************************************************************************************************************
 410  *function: RX ADDBARSP
 411  *   input:  struct sk_buff *   skb     //incoming ADDBAReq skb.
 412  *  return:  0(pass), other(fail)
 413  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
 414  ********************************************************************************************************************/
 415 int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
 416 {
 417         struct rtl_80211_hdr_3addr *rsp = NULL;
 418         struct ba_record        *pPendingBA, *pAdmittedBA;
 419         struct tx_ts_record     *pTS = NULL;
 420         u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
 421         u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
 422         union ba_param_set       *pBaParamSet = NULL;
 423         u16                     ReasonCode;
 424 
 425         if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
 426                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
 427                                 " Invalid skb len in BARSP(%d / %zu)\n",
 428                                 skb->len,
 429                                 (sizeof(struct rtl_80211_hdr_3addr) + 9));
 430                 return -1;
 431         }
 432         rsp = (struct rtl_80211_hdr_3addr *)skb->data;
 433         tag = (u8 *)rsp;
 434         dst = &rsp->addr2[0];
 435         tag += sizeof(struct rtl_80211_hdr_3addr);
 436         pDialogToken = tag + 2;
 437         pStatusCode = (u16 *)(tag + 3);
 438         pBaParamSet = (union ba_param_set *)(tag + 5);
 439         pBaTimeoutVal = (u16 *)(tag + 7);
 440 
 441         // Check the capability
 442         // Since we can always receive A-MPDU, we just check if it is under HT mode.
 443         if (ieee->current_network.qos_data.active == 0  ||
 444             !ieee->pHTInfo->bCurrentHTSupport ||
 445             !ieee->pHTInfo->bCurrentAMPDUEnable) {
 446                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
 447                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
 448                 goto OnADDBARsp_Reject;
 449         }
 450 
 451 
 452         //
 453         // Search for related TS.
 454         // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
 455         //
 456         if (!GetTs(
 457                         ieee,
 458                         (struct ts_common_info **)(&pTS),
 459                         dst,
 460                         (u8)(pBaParamSet->field.tid),
 461                         TX_DIR,
 462                         false)) {
 463                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
 464                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
 465                 goto OnADDBARsp_Reject;
 466         }
 467 
 468         pTS->add_ba_req_in_progress = false;
 469         pPendingBA = &pTS->tx_pending_ba_record;
 470         pAdmittedBA = &pTS->tx_admitted_ba_record;
 471 
 472 
 473         //
 474         // Check if related BA is waiting for setup.
 475         // If not, reject by sending DELBA frame.
 476         //
 477         if (pAdmittedBA->valid) {
 478                 // Since BA is already setup, we ignore all other ADDBA Response.
 479                 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
 480                 return -1;
 481         } else if ((!pPendingBA->valid) || (*pDialogToken != pPendingBA->dialog_token)) {
 482                 IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
 483                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
 484                 goto OnADDBARsp_Reject;
 485         } else {
 486                 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
 487                 DeActivateBAEntry(ieee, pPendingBA);
 488         }
 489 
 490 
 491         if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
 492                 //
 493                 // Determine ADDBA Rsp content here.
 494                 // We can compare the value of BA parameter set that Peer returned and Self sent.
 495                 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
 496                 //
 497                 if (pBaParamSet->field.ba_policy == BA_POLICY_DELAYED) {
 498                         // Since this is a kind of ADDBA failed, we delay next ADDBA process.
 499                         pTS->add_ba_req_delayed = true;
 500                         DeActivateBAEntry(ieee, pAdmittedBA);
 501                         ReasonCode = DELBA_REASON_END_BA;
 502                         goto OnADDBARsp_Reject;
 503                 }
 504 
 505 
 506                 //
 507                 // Admitted condition
 508                 //
 509                 pAdmittedBA->dialog_token = *pDialogToken;
 510                 pAdmittedBA->timeout_value = *pBaTimeoutVal;
 511                 pAdmittedBA->start_seq_ctrl = pPendingBA->start_seq_ctrl;
 512                 pAdmittedBA->param_set = *pBaParamSet;
 513                 DeActivateBAEntry(ieee, pAdmittedBA);
 514                 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
 515         } else {
 516                 // Delay next ADDBA process.
 517                 pTS->add_ba_req_delayed = true;
 518         }
 519 
 520         // End of procedure
 521         return 0;
 522 
 523 OnADDBARsp_Reject:
 524         {
 525                 struct ba_record        BA;
 526                 BA.param_set = *pBaParamSet;
 527                 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
 528                 return 0;
 529         }
 530 
 531 }
 532 
 533 /********************************************************************************************************************
 534  *function: RX DELBA
 535  *   input:  struct sk_buff *   skb     //incoming ADDBAReq skb.
 536  *  return:  0(pass), other(fail)
 537  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
 538  ********************************************************************************************************************/
 539 int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
 540 {
 541         struct rtl_80211_hdr_3addr *delba = NULL;
 542         union delba_param_set   *pDelBaParamSet = NULL;
 543         u8                      *dst = NULL;
 544 
 545         if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
 546                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
 547                                 " Invalid skb len in DELBA(%d / %zu)\n",
 548                                 skb->len,
 549                                 (sizeof(struct rtl_80211_hdr_3addr) + 6));
 550                 return -1;
 551         }
 552 
 553         if (ieee->current_network.qos_data.active == 0 ||
 554             !ieee->pHTInfo->bCurrentHTSupport) {
 555                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
 556                 return -1;
 557         }
 558 
 559         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len);
 560         delba = (struct rtl_80211_hdr_3addr *)skb->data;
 561         dst = &delba->addr2[0];
 562         pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
 563 
 564         if (pDelBaParamSet->field.initiator == 1) {
 565                 struct rx_ts_record *pRxTs;
 566 
 567                 if (!GetTs(
 568                                 ieee,
 569                                 (struct ts_common_info **)&pRxTs,
 570                                 dst,
 571                                 (u8)pDelBaParamSet->field.tid,
 572                                 RX_DIR,
 573                                 false)) {
 574                         IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for RXTS in %s()\n", __func__);
 575                         return -1;
 576                 }
 577 
 578                 RxTsDeleteBA(ieee, pRxTs);
 579         } else {
 580                 struct tx_ts_record *pTxTs;
 581 
 582                 if (!GetTs(
 583                         ieee,
 584                         (struct ts_common_info **)&pTxTs,
 585                         dst,
 586                         (u8)pDelBaParamSet->field.tid,
 587                         TX_DIR,
 588                         false)) {
 589                         IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for TXTS in %s()\n", __func__);
 590                         return -1;
 591                 }
 592 
 593                 pTxTs->using_ba = false;
 594                 pTxTs->add_ba_req_in_progress = false;
 595                 pTxTs->add_ba_req_delayed = false;
 596                 del_timer_sync(&pTxTs->ts_add_ba_timer);
 597                 //PlatformCancelTimer(Adapter, &pTxTs->ts_add_ba_timer);
 598                 TxTsDeleteBA(ieee, pTxTs);
 599         }
 600         return 0;
 601 }
 602 
 603 //
 604 // ADDBA initiate. This can only be called by TX side.
 605 //
 606 void
 607 TsInitAddBA(
 608         struct ieee80211_device *ieee,
 609         struct tx_ts_record     *pTS,
 610         u8              Policy,
 611         u8              bOverwritePending
 612         )
 613 {
 614         struct ba_record *pBA = &pTS->tx_pending_ba_record;
 615 
 616         if (pBA->valid && !bOverwritePending)
 617                 return;
 618 
 619         // Set parameters to "Pending" variable set
 620         DeActivateBAEntry(ieee, pBA);
 621 
 622         pBA->dialog_token++;                                            // DialogToken: Only keep the latest dialog token
 623         pBA->param_set.field.amsdu_support = 0; // Do not support A-MSDU with A-MPDU now!!
 624         pBA->param_set.field.ba_policy = Policy;        // Policy: Delayed or Immediate
 625         pBA->param_set.field.tid = pTS->ts_common_info.t_spec.ts_info.uc_tsid;  // TID
 626         // buffer_size: This need to be set according to A-MPDU vector
 627         pBA->param_set.field.buffer_size = 32;          // buffer_size: This need to be set according to A-MPDU vector
 628         pBA->timeout_value = 0;                                 // Timeout value: Set 0 to disable Timer
 629         pBA->start_seq_ctrl.field.seq_num = (pTS->tx_cur_seq + 3) % 4096;       // Block Ack will start after 3 packets later.
 630 
 631         ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
 632 
 633         ieee80211_send_ADDBAReq(ieee, pTS->ts_common_info.addr, pBA);
 634 }
 635 
 636 void
 637 TsInitDelBA(struct ieee80211_device *ieee, struct ts_common_info *pTsCommonInfo, enum tr_select TxRxSelect)
 638 {
 639         if (TxRxSelect == TX_DIR) {
 640                 struct tx_ts_record *pTxTs = (struct tx_ts_record *)pTsCommonInfo;
 641 
 642                 if (TxTsDeleteBA(ieee, pTxTs))
 643                         ieee80211_send_DELBA(
 644                                 ieee,
 645                                 pTsCommonInfo->addr,
 646                                 (pTxTs->tx_admitted_ba_record.valid) ? (&pTxTs->tx_admitted_ba_record) : (&pTxTs->tx_pending_ba_record),
 647                                 TxRxSelect,
 648                                 DELBA_REASON_END_BA);
 649         } else if (TxRxSelect == RX_DIR) {
 650                 struct rx_ts_record *pRxTs = (struct rx_ts_record *)pTsCommonInfo;
 651                 if (RxTsDeleteBA(ieee, pRxTs))
 652                         ieee80211_send_DELBA(
 653                                 ieee,
 654                                 pTsCommonInfo->addr,
 655                                 &pRxTs->rx_admitted_ba_record,
 656                                 TxRxSelect,
 657                                 DELBA_REASON_END_BA);
 658         }
 659 }
 660 /********************************************************************************************************************
 661  *function:  BA setup timer
 662  *   input:  unsigned long       data           //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
 663  *  return:  NULL
 664  *  notice:
 665  ********************************************************************************************************************/
 666 void BaSetupTimeOut(struct timer_list *t)
 667 {
 668         struct tx_ts_record *pTxTs = from_timer(pTxTs, t, tx_pending_ba_record.timer);
 669 
 670         pTxTs->add_ba_req_in_progress = false;
 671         pTxTs->add_ba_req_delayed = true;
 672         pTxTs->tx_pending_ba_record.valid = false;
 673 }
 674 
 675 void TxBaInactTimeout(struct timer_list *t)
 676 {
 677         struct tx_ts_record *pTxTs = from_timer(pTxTs, t, tx_admitted_ba_record.timer);
 678         struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
 679         TxTsDeleteBA(ieee, pTxTs);
 680         ieee80211_send_DELBA(
 681                 ieee,
 682                 pTxTs->ts_common_info.addr,
 683                 &pTxTs->tx_admitted_ba_record,
 684                 TX_DIR,
 685                 DELBA_REASON_TIMEOUT);
 686 }
 687 
 688 void RxBaInactTimeout(struct timer_list *t)
 689 {
 690         struct rx_ts_record *pRxTs = from_timer(pRxTs, t, rx_admitted_ba_record.timer);
 691         struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
 692 
 693         RxTsDeleteBA(ieee, pRxTs);
 694         ieee80211_send_DELBA(
 695                 ieee,
 696                 pRxTs->ts_common_info.addr,
 697                 &pRxTs->rx_admitted_ba_record,
 698                 RX_DIR,
 699                 DELBA_REASON_TIMEOUT);
 700 }

/* [<][>][^][v][top][bottom][index][help] */