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