rtl819x_BAProc.c revision 50a09b3b099ebc8326b85b4f508fb47655e1fed3
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 178/******************************************************************************************************************** 179 *function: construct DELBA frame 180 * input: u8* dst //DELBA frame's destination 181 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA 182 * TR_SELECT TxRxSelect //TX RX direction 183 * u16 ReasonCode //status code. 184 * output: none 185 * return: sk_buff* skb //return constructed skb to xmit 186********************************************************************************************************************/ 187static struct sk_buff* ieee80211_DELBA( 188 struct ieee80211_device* ieee, 189 u8* dst, 190 PBA_RECORD pBA, 191 TR_SELECT TxRxSelect, 192 u16 ReasonCode 193 ) 194{ 195 DELBA_PARAM_SET DelbaParamSet; 196 struct sk_buff *skb = NULL; 197 struct ieee80211_hdr_3addr* Delba = NULL; 198 u8* tag = NULL; 199 u16 tmp = 0; 200 //len = head len + DELBA Parameter Set(2) + Reason Code(2) 201 u16 len = 6 + ieee->tx_headroom; 202 203 if (net_ratelimit()) 204 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst)); 205 206 memset(&DelbaParamSet, 0, 2); 207 208 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0; 209 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID; 210 211 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME 212 if (skb == NULL) 213 { 214 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); 215 return NULL; 216 } 217// memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr)); 218 skb_reserve(skb, ieee->tx_headroom); 219 220 Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr)); 221 222 memcpy(Delba->addr1, dst, ETH_ALEN); 223 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); 224 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); 225 Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame 226 227 tag = (u8*)skb_put(skb, 6); 228 229 *tag ++= ACT_CAT_BA; 230 *tag ++= ACT_DELBA; 231 232 // DELBA Parameter Set 233 tmp = cpu_to_le16(DelbaParamSet.shortData); 234 memcpy(tag, (u8*)&tmp, 2); 235 tag += 2; 236 // Reason Code 237 tmp = cpu_to_le16(ReasonCode); 238 memcpy(tag, (u8*)&tmp, 2); 239 tag += 2; 240 241 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); 242 if (net_ratelimit()) 243 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__); 244 return skb; 245} 246 247/******************************************************************************************************************** 248 *function: send ADDBAReq frame out 249 * input: u8* dst //ADDBAReq frame's destination 250 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA 251 * output: none 252 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does 253********************************************************************************************************************/ 254void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA) 255{ 256 struct sk_buff *skb = NULL; 257 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero. 258 259 if (skb) 260 { 261 softmac_mgmt_xmit(skb, ieee); 262 //add statistic needed here. 263 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit() 264 //WB 265 } 266 else 267 { 268 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); 269 } 270 return; 271} 272 273/******************************************************************************************************************** 274 *function: send ADDBARSP frame out 275 * input: u8* dst //DELBA frame's destination 276 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA 277 * u16 StatusCode //RSP StatusCode 278 * output: none 279 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does 280********************************************************************************************************************/ 281void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode) 282{ 283 struct sk_buff *skb = NULL; 284 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames 285 if (skb) 286 { 287 softmac_mgmt_xmit(skb, ieee); 288 //same above 289 } 290 else 291 { 292 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); 293 } 294 295 return; 296 297} 298/******************************************************************************************************************** 299 *function: send ADDBARSP frame out 300 * input: u8* dst //DELBA frame's destination 301 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA 302 * TR_SELECT TxRxSelect //TX or RX 303 * u16 ReasonCode //DEL ReasonCode 304 * output: none 305 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does 306********************************************************************************************************************/ 307 308void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode) 309{ 310 struct sk_buff *skb = NULL; 311 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames 312 if (skb) 313 { 314 softmac_mgmt_xmit(skb, ieee); 315 //same above 316 } 317 else 318 { 319 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); 320 } 321 return ; 322} 323 324/******************************************************************************************************************** 325 *function: RX ADDBAReq 326 * input: struct sk_buff * skb //incoming ADDBAReq skb. 327 * return: 0(pass), other(fail) 328 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. 329********************************************************************************************************************/ 330int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb) 331{ 332 struct ieee80211_hdr_3addr* req = NULL; 333 u16 rc = 0; 334 u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL; 335 PBA_RECORD pBA = NULL; 336 PBA_PARAM_SET pBaParamSet = NULL; 337 u16* pBaTimeoutVal = NULL; 338 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; 339 PRX_TS_RECORD pTS = NULL; 340 341 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 342 { 343 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 344 return -1; 345 } 346 347 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); 348 349 req = ( struct ieee80211_hdr_3addr*) skb->data; 350 tag = (u8*)req; 351 dst = (u8*)(&req->addr2[0]); 352 tag += sizeof( struct ieee80211_hdr_3addr); 353 pDialogToken = tag + 2; //category+action 354 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken 355 pBaTimeoutVal = (u16*)(tag + 5); 356 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); 357 358 printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst)); 359//some other capability is not ready now. 360 if( (ieee->current_network.qos_data.active == 0) || 361 (ieee->pHTInfo->bCurrentHTSupport == false)) //|| 362 // (ieee->pStaQos->bEnableRxImmBA == false) ) 363 { 364 rc = ADDBA_STATUS_REFUSED; 365 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); 366 goto OnADDBAReq_Fail; 367 } 368 // Search for related traffic stream. 369 // If there is no matched TS, reject the ADDBA request. 370 if( !GetTs( 371 ieee, 372 (PTS_COMMON_INFO*)(&pTS), 373 dst, 374 (u8)(pBaParamSet->field.TID), 375 RX_DIR, 376 true) ) 377 { 378 rc = ADDBA_STATUS_REFUSED; 379 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); 380 goto OnADDBAReq_Fail; 381 } 382 pBA = &pTS->RxAdmittedBARecord; 383 // To Determine the ADDBA Req content 384 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl... 385 // I want to check StartSeqCtrl to make sure when we start aggregation!!! 386 // 387 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) 388 { 389 rc = ADDBA_STATUS_INVALID_PARAM; 390 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__); 391 goto OnADDBAReq_Fail; 392 } 393 // Admit the ADDBA Request 394 // 395 DeActivateBAEntry(ieee, pBA); 396 pBA->DialogToken = *pDialogToken; 397 pBA->BaParamSet = *pBaParamSet; 398 pBA->BaTimeoutValue = *pBaTimeoutVal; 399 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; 400 //for half N mode we only aggregate 1 frame 401 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 402 pBA->BaParamSet.field.BufferSize = 1; 403 else 404 pBA->BaParamSet.field.BufferSize = 32; 405 ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue); 406 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); 407 408 // End of procedure. 409 return 0; 410 411OnADDBAReq_Fail: 412 { 413 BA_RECORD BA; 414 BA.BaParamSet = *pBaParamSet; 415 BA.BaTimeoutValue = *pBaTimeoutVal; 416 BA.DialogToken = *pDialogToken; 417 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; 418 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc); 419 return 0; //we send RSP out. 420 } 421 422} 423 424/******************************************************************************************************************** 425 *function: RX ADDBARSP 426 * input: struct sk_buff * skb //incoming ADDBAReq skb. 427 * return: 0(pass), other(fail) 428 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. 429********************************************************************************************************************/ 430int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb) 431{ 432 struct ieee80211_hdr_3addr* rsp = NULL; 433 PBA_RECORD pPendingBA, pAdmittedBA; 434 PTX_TS_RECORD pTS = NULL; 435 u8* dst = NULL, *pDialogToken = NULL, *tag = NULL; 436 u16* pStatusCode = NULL, *pBaTimeoutVal = NULL; 437 PBA_PARAM_SET pBaParamSet = NULL; 438 u16 ReasonCode; 439 440 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 441 { 442 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 443 return -1; 444 } 445 rsp = ( struct ieee80211_hdr_3addr*)skb->data; 446 tag = (u8*)rsp; 447 dst = (u8*)(&rsp->addr2[0]); 448 tag += sizeof( struct ieee80211_hdr_3addr); 449 pDialogToken = tag + 2; 450 pStatusCode = (u16*)(tag + 3); 451 pBaParamSet = (PBA_PARAM_SET)(tag + 5); 452 pBaTimeoutVal = (u16*)(tag + 7); 453 454 // Check the capability 455 // Since we can always receive A-MPDU, we just check if it is under HT mode. 456 if( ieee->current_network.qos_data.active == 0 || 457 ieee->pHTInfo->bCurrentHTSupport == false || 458 ieee->pHTInfo->bCurrentAMPDUEnable == false ) 459 { 460 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); 461 ReasonCode = DELBA_REASON_UNKNOWN_BA; 462 goto OnADDBARsp_Reject; 463 } 464 465 466 // 467 // Search for related TS. 468 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame. 469 // 470 if (!GetTs( 471 ieee, 472 (PTS_COMMON_INFO*)(&pTS), 473 dst, 474 (u8)(pBaParamSet->field.TID), 475 TX_DIR, 476 false) ) 477 { 478 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); 479 ReasonCode = DELBA_REASON_UNKNOWN_BA; 480 goto OnADDBARsp_Reject; 481 } 482 483 pTS->bAddBaReqInProgress = false; 484 pPendingBA = &pTS->TxPendingBARecord; 485 pAdmittedBA = &pTS->TxAdmittedBARecord; 486 487 488 // 489 // Check if related BA is waiting for setup. 490 // If not, reject by sending DELBA frame. 491 // 492 if((pAdmittedBA->bValid==true)) 493 { 494 // Since BA is already setup, we ignore all other ADDBA Response. 495 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); 496 return -1; 497 } 498 else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) 499 { 500 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); 501 ReasonCode = DELBA_REASON_UNKNOWN_BA; 502 goto OnADDBARsp_Reject; 503 } 504 else 505 { 506 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); 507 DeActivateBAEntry(ieee, pPendingBA); 508 } 509 510 511 if(*pStatusCode == ADDBA_STATUS_SUCCESS) 512 { 513 // 514 // Determine ADDBA Rsp content here. 515 // We can compare the value of BA parameter set that Peer returned and Self sent. 516 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism. 517 // 518 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) 519 { 520 // Since this is a kind of ADDBA failed, we delay next ADDBA process. 521 pTS->bAddBaReqDelayed = true; 522 DeActivateBAEntry(ieee, pAdmittedBA); 523 ReasonCode = DELBA_REASON_END_BA; 524 goto OnADDBARsp_Reject; 525 } 526 527 528 // 529 // Admitted condition 530 // 531 pAdmittedBA->DialogToken = *pDialogToken; 532 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; 533 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; 534 pAdmittedBA->BaParamSet = *pBaParamSet; 535 DeActivateBAEntry(ieee, pAdmittedBA); 536 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); 537 } 538 else 539 { 540 // Delay next ADDBA process. 541 pTS->bAddBaReqDelayed = true; 542 } 543 544 // End of procedure 545 return 0; 546 547OnADDBARsp_Reject: 548 { 549 BA_RECORD BA; 550 BA.BaParamSet = *pBaParamSet; 551 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); 552 return 0; 553 } 554 555} 556 557/******************************************************************************************************************** 558 *function: RX DELBA 559 * input: struct sk_buff * skb //incoming ADDBAReq skb. 560 * return: 0(pass), other(fail) 561 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. 562********************************************************************************************************************/ 563int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb) 564{ 565 struct ieee80211_hdr_3addr* delba = NULL; 566 PDELBA_PARAM_SET pDelBaParamSet = NULL; 567 u16* pReasonCode = NULL; 568 u8* dst = NULL; 569 570 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) 571 { 572 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); 573 return -1; 574 } 575 576 if(ieee->current_network.qos_data.active == 0 || 577 ieee->pHTInfo->bCurrentHTSupport == false ) 578 { 579 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); 580 return -1; 581 } 582 583 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); 584 delba = ( struct ieee80211_hdr_3addr*)skb->data; 585 dst = (u8*)(&delba->addr2[0]); 586 delba += sizeof( struct ieee80211_hdr_3addr); 587 pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2); 588 pReasonCode = (u16*)(delba+4); 589 590 if(pDelBaParamSet->field.Initiator == 1) 591 { 592 PRX_TS_RECORD pRxTs; 593 594 if( !GetTs( 595 ieee, 596 (PTS_COMMON_INFO*)&pRxTs, 597 dst, 598 (u8)pDelBaParamSet->field.TID, 599 RX_DIR, 600 false) ) 601 { 602 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__); 603 return -1; 604 } 605 606 RxTsDeleteBA(ieee, pRxTs); 607 } 608 else 609 { 610 PTX_TS_RECORD pTxTs; 611 612 if(!GetTs( 613 ieee, 614 (PTS_COMMON_INFO*)&pTxTs, 615 dst, 616 (u8)pDelBaParamSet->field.TID, 617 TX_DIR, 618 false) ) 619 { 620 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__); 621 return -1; 622 } 623 624 pTxTs->bUsingBa = false; 625 pTxTs->bAddBaReqInProgress = false; 626 pTxTs->bAddBaReqDelayed = false; 627 del_timer_sync(&pTxTs->TsAddBaTimer); 628 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer); 629 TxTsDeleteBA(ieee, pTxTs); 630 } 631 return 0; 632} 633 634// 635// ADDBA initiate. This can only be called by TX side. 636// 637void 638TsInitAddBA( 639 struct ieee80211_device* ieee, 640 PTX_TS_RECORD pTS, 641 u8 Policy, 642 u8 bOverwritePending 643 ) 644{ 645 PBA_RECORD pBA = &pTS->TxPendingBARecord; 646 647 if(pBA->bValid==true && bOverwritePending==false) 648 return; 649 650 // Set parameters to "Pending" variable set 651 DeActivateBAEntry(ieee, pBA); 652 653 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token 654 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!! 655 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate 656 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID 657 // BufferSize: This need to be set according to A-MPDU vector 658 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector 659 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer 660 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later. 661 662 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT); 663 664 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA); 665} 666 667void 668TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect) 669{ 670 671 if(TxRxSelect == TX_DIR) 672 { 673 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo; 674 675 if(TxTsDeleteBA(ieee, pTxTs)) 676 ieee80211_send_DELBA( 677 ieee, 678 pTsCommonInfo->Addr, 679 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), 680 TxRxSelect, 681 DELBA_REASON_END_BA); 682 } 683 else if(TxRxSelect == RX_DIR) 684 { 685 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo; 686 if(RxTsDeleteBA(ieee, pRxTs)) 687 ieee80211_send_DELBA( 688 ieee, 689 pTsCommonInfo->Addr, 690 &pRxTs->RxAdmittedBARecord, 691 TxRxSelect, 692 DELBA_REASON_END_BA ); 693 } 694} 695/******************************************************************************************************************** 696 *function: BA setup timer 697 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer 698 * return: NULL 699 * notice: 700********************************************************************************************************************/ 701void BaSetupTimeOut(unsigned long data) 702{ 703 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; 704 705 pTxTs->bAddBaReqInProgress = false; 706 pTxTs->bAddBaReqDelayed = true; 707 pTxTs->TxPendingBARecord.bValid = false; 708} 709 710void TxBaInactTimeout(unsigned long data) 711{ 712 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; 713 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]); 714 TxTsDeleteBA(ieee, pTxTs); 715 ieee80211_send_DELBA( 716 ieee, 717 pTxTs->TsCommonInfo.Addr, 718 &pTxTs->TxAdmittedBARecord, 719 TX_DIR, 720 DELBA_REASON_TIMEOUT); 721} 722 723void RxBaInactTimeout(unsigned long data) 724{ 725 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; 726 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]); 727 728 RxTsDeleteBA(ieee, pRxTs); 729 ieee80211_send_DELBA( 730 ieee, 731 pRxTs->TsCommonInfo.Addr, 732 &pRxTs->RxAdmittedBARecord, 733 RX_DIR, 734 DELBA_REASON_TIMEOUT); 735 return ; 736} 737 738