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