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