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