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