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.
6 * *****************************************************************************************************************************/
7 #include <asm/byteorder.h>
8 #include <asm/unaligned.h>
10 #include "rtl819x_BA.h"
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.
17 ********************************************************************************************************************/
18 static void ActivateBAEntry(struct ieee80211_device
*ieee
, PBA_RECORD pBA
, u16 Time
)
22 mod_timer(&pBA
->Timer
, jiffies
+ MSECS(Time
));
25 /********************************************************************************************************************
26 *function: deactivate BA entry, including its timer.
27 * input: PBA_RECORD pBA //BA entry to be disabled
29 ********************************************************************************************************************/
30 static void DeActivateBAEntry(struct ieee80211_device
*ieee
, PBA_RECORD pBA
)
33 del_timer_sync(&pBA
->Timer
);
35 /********************************************************************************************************************
36 *function: deactivete BA entry in Tx Ts, and send DELBA.
38 * PTX_TS_RECORD pTxTs //Tx Ts which is to deactivate BA entry.
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
)
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;
49 if(pPendingBa
->bValid
)
51 DeActivateBAEntry(ieee
, pPendingBa
);
56 if(pAdmittedBa
->bValid
)
58 DeActivateBAEntry(ieee
, pAdmittedBa
);
65 /********************************************************************************************************************
66 *function: deactivete BA entry in Tx Ts, and send DELBA.
68 * PRX_TS_RECORD pRxTs //Rx Ts which is to deactivate BA entry.
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
)
74 PBA_RECORD pBa
= &pRxTs
->RxAdmittedBARecord
;
75 u8 bSendDELBA
= false;
79 DeActivateBAEntry(ieee
, pBa
);
86 /********************************************************************************************************************
87 *function: reset BA entry
89 * PBA_RECORD pBA //entry to be reset
91 ********************************************************************************************************************/
92 void ResetBaEntry(PBA_RECORD pBA
)
95 pBA
->BaParamSet
.shortData
= 0;
96 pBA
->BaTimeoutValue
= 0;
98 pBA
->BaStartSeqCtrl
.ShortData
= 0;
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)
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
)
112 struct sk_buff
*skb
= NULL
;
113 struct ieee80211_hdr_3addr
*BAReq
= 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
);
120 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "pBA is NULL\n");
123 skb
= dev_alloc_skb(len
+ sizeof( struct ieee80211_hdr_3addr
)); //need to add something others? FIXME
126 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
130 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.
131 skb_reserve(skb
, ieee
->tx_headroom
);
133 BAReq
= ( struct ieee80211_hdr_3addr
*) skb_put(skb
,sizeof( struct ieee80211_hdr_3addr
));
135 memcpy(BAReq
->addr1
, Dst
, ETH_ALEN
);
136 memcpy(BAReq
->addr2
, ieee
->dev
->dev_addr
, ETH_ALEN
);
138 memcpy(BAReq
->addr3
, ieee
->current_network
.bssid
, ETH_ALEN
);
140 BAReq
->frame_ctl
= cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT
); //action frame
142 //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
143 tag
= (u8
*)skb_put(skb
, 9);
147 *tag
++= pBA
->DialogToken
;
149 if (ACT_ADDBARSP
== type
)
152 printk("=====>to send ADDBARSP\n");
154 put_unaligned_le16(StatusCode
, tag
);
159 put_unaligned_le16(pBA
->BaParamSet
.shortData
, tag
);
163 put_unaligned_le16(pBA
->BaTimeoutValue
, tag
);
166 if (ACT_ADDBAREQ
== type
)
169 memcpy(tag
, (u8
*)&(pBA
->BaStartSeqCtrl
), 2);
173 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
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.
186 * return: sk_buff* skb //return constructed skb to xmit
187 ********************************************************************************************************************/
188 static struct sk_buff
*ieee80211_DELBA(
189 struct ieee80211_device
*ieee
,
192 TR_SELECT TxRxSelect
,
196 DELBA_PARAM_SET DelbaParamSet
;
197 struct sk_buff
*skb
= NULL
;
198 struct ieee80211_hdr_3addr
*Delba
= NULL
;
200 //len = head len + DELBA Parameter Set(2) + Reason Code(2)
201 u16 len
= 6 + ieee
->tx_headroom
;
204 IEEE80211_DEBUG(IEEE80211_DL_TRACE
| IEEE80211_DL_BA
, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __func__
, ReasonCode
, dst
);
206 memset(&DelbaParamSet
, 0, 2);
208 DelbaParamSet
.field
.Initiator
= (TxRxSelect
==TX_DIR
)?1:0;
209 DelbaParamSet
.field
.TID
= pBA
->BaParamSet
.field
.TID
;
211 skb
= dev_alloc_skb(len
+ sizeof( struct ieee80211_hdr_3addr
)); //need to add something others? FIXME
214 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
217 // memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
218 skb_reserve(skb
, ieee
->tx_headroom
);
220 Delba
= ( struct ieee80211_hdr_3addr
*) skb_put(skb
,sizeof( struct ieee80211_hdr_3addr
));
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
227 tag
= (u8
*)skb_put(skb
, 6);
232 // DELBA Parameter Set
234 put_unaligned_le16(DelbaParamSet
.shortData
, tag
);
238 put_unaligned_le16(ReasonCode
, tag
);
241 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
243 IEEE80211_DEBUG(IEEE80211_DL_TRACE
| IEEE80211_DL_BA
, "<=====%s()\n", __func__
);
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
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
)
257 struct sk_buff
*skb
= NULL
;
258 skb
= ieee80211_ADDBA(ieee
, dst
, pBA
, 0, ACT_ADDBAREQ
); //construct ACT_ADDBAREQ frames so set statuscode zero.
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()
269 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __func__
);
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
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
)
285 struct sk_buff
*skb
= NULL
;
286 skb
= ieee80211_ADDBA(ieee
, dst
, pBA
, StatusCode
, ACT_ADDBARSP
); //construct ACT_ADDBARSP frames
289 softmac_mgmt_xmit(skb
, ieee
);
294 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __func__
);
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
307 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
308 ********************************************************************************************************************/
310 static void ieee80211_send_DELBA(struct ieee80211_device
*ieee
, u8
*dst
,
311 PBA_RECORD pBA
, TR_SELECT TxRxSelect
,
314 struct sk_buff
*skb
= NULL
;
315 skb
= ieee80211_DELBA(ieee
, dst
, pBA
, TxRxSelect
, ReasonCode
); //construct ACT_ADDBARSP frames
318 softmac_mgmt_xmit(skb
, ieee
);
323 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __func__
);
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
)
336 struct ieee80211_hdr_3addr
*req
= NULL
;
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
;
345 if (skb
->len
< sizeof(struct ieee80211_hdr_3addr
) + 9) {
346 IEEE80211_DEBUG(IEEE80211_DL_ERR
,
347 " Invalid skb len in BAREQ(%d / %zu)\n",
349 (sizeof(struct ieee80211_hdr_3addr
) + 9));
353 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
355 req
= (struct ieee80211_hdr_3addr
*) skb
->data
;
357 dst
= (u8
*)(&req
->addr2
[0]);
358 tag
+= sizeof(struct ieee80211_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);
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
== false)) //||
368 // (ieee->pStaQos->bEnableRxImmBA == false) )
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
;
374 // Search for related traffic stream.
375 // If there is no matched TS, reject the ADDBA request.
378 (PTS_COMMON_INFO
*)(&pTS
),
380 (u8
)(pBaParamSet
->field
.TID
),
384 rc
= ADDBA_STATUS_REFUSED
;
385 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS in %s()\n", __func__
);
386 goto OnADDBAReq_Fail
;
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!!!
393 if(pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
)
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
;
399 // Admit the ADDBA Request
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;
410 pBA
->BaParamSet
.field
.BufferSize
= 32;
411 ActivateBAEntry(ieee
, pBA
, pBA
->BaTimeoutValue
);
412 ieee80211_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
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.
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
)
438 struct ieee80211_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
;
446 if (skb
->len
< sizeof(struct ieee80211_hdr_3addr
) + 9) {
447 IEEE80211_DEBUG(IEEE80211_DL_ERR
,
448 " Invalid skb len in BARSP(%d / %zu)\n",
450 (sizeof(struct ieee80211_hdr_3addr
) + 9));
453 rsp
= (struct ieee80211_hdr_3addr
*)skb
->data
;
455 dst
= (u8
*)(&rsp
->addr2
[0]);
456 tag
+= sizeof(struct ieee80211_hdr_3addr
);
457 pDialogToken
= tag
+ 2;
458 pStatusCode
= (u16
*)(tag
+ 3);
459 pBaParamSet
= (PBA_PARAM_SET
)(tag
+ 5);
460 pBaTimeoutVal
= (u16
*)(tag
+ 7);
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
== false ||
466 ieee
->pHTInfo
->bCurrentAMPDUEnable
== false) {
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
;
474 // Search for related TS.
475 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
479 (PTS_COMMON_INFO
*)(&pTS
),
481 (u8
)(pBaParamSet
->field
.TID
),
485 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS in %s()\n", __func__
);
486 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
487 goto OnADDBARsp_Reject
;
490 pTS
->bAddBaReqInProgress
= false;
491 pPendingBA
= &pTS
->TxPendingBARecord
;
492 pAdmittedBA
= &pTS
->TxAdmittedBARecord
;
496 // Check if related BA is waiting for setup.
497 // If not, reject by sending DELBA frame.
499 if((pAdmittedBA
->bValid
==true))
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");
505 else if((pPendingBA
->bValid
== false) ||(*pDialogToken
!= pPendingBA
->DialogToken
))
507 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
508 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
509 goto OnADDBARsp_Reject
;
513 IEEE80211_DEBUG(IEEE80211_DL_BA
, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode
);
514 DeActivateBAEntry(ieee
, pPendingBA
);
518 if(*pStatusCode
== ADDBA_STATUS_SUCCESS
)
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.
525 if(pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
)
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
;
536 // Admitted condition
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
);
547 // Delay next ADDBA process.
548 pTS
->bAddBaReqDelayed
= true;
557 BA
.BaParamSet
= *pBaParamSet
;
558 ieee80211_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
564 /********************************************************************************************************************
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
)
572 struct ieee80211_hdr_3addr
*delba
= NULL
;
573 PDELBA_PARAM_SET pDelBaParamSet
= NULL
;
574 u16
*pReasonCode
= NULL
;
577 if (skb
->len
< sizeof(struct ieee80211_hdr_3addr
) + 6) {
578 IEEE80211_DEBUG(IEEE80211_DL_ERR
,
579 " Invalid skb len in DELBA(%d / %zu)\n",
581 (sizeof(struct ieee80211_hdr_3addr
) + 6));
585 if(ieee
->current_network
.qos_data
.active
== 0 ||
586 ieee
->pHTInfo
->bCurrentHTSupport
== false )
588 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
);
592 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
593 delba
= (struct ieee80211_hdr_3addr
*)skb
->data
;
594 dst
= (u8
*)(&delba
->addr2
[0]);
595 delba
+= sizeof(struct ieee80211_hdr_3addr
);
596 pDelBaParamSet
= (PDELBA_PARAM_SET
)(delba
+2);
597 pReasonCode
= (u16
*)(delba
+4);
599 if(pDelBaParamSet
->field
.Initiator
== 1)
605 (PTS_COMMON_INFO
*)&pRxTs
,
607 (u8
)pDelBaParamSet
->field
.TID
,
611 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS for RXTS in %s()\n", __func__
);
615 RxTsDeleteBA(ieee
, pRxTs
);
623 (PTS_COMMON_INFO
*)&pTxTs
,
625 (u8
)pDelBaParamSet
->field
.TID
,
629 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS for TXTS in %s()\n", __func__
);
633 pTxTs
->bUsingBa
= false;
634 pTxTs
->bAddBaReqInProgress
= false;
635 pTxTs
->bAddBaReqDelayed
= false;
636 del_timer_sync(&pTxTs
->TsAddBaTimer
);
637 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
638 TxTsDeleteBA(ieee
, pTxTs
);
644 // ADDBA initiate. This can only be called by TX side.
648 struct ieee80211_device
*ieee
,
654 PBA_RECORD pBA
= &pTS
->TxPendingBARecord
;
656 if(pBA
->bValid
==true && bOverwritePending
==false)
659 // Set parameters to "Pending" variable set
660 DeActivateBAEntry(ieee
, pBA
);
662 pBA
->DialogToken
++; // DialogToken: Only keep the latest dialog token
663 pBA
->BaParamSet
.field
.AMSDU_Support
= 0; // Do not support A-MSDU with A-MPDU now!!
664 pBA
->BaParamSet
.field
.BAPolicy
= Policy
; // Policy: Delayed or Immediate
665 pBA
->BaParamSet
.field
.TID
= pTS
->TsCommonInfo
.TSpec
.f
.TSInfo
.field
.ucTSID
; // TID
666 // BufferSize: This need to be set according to A-MPDU vector
667 pBA
->BaParamSet
.field
.BufferSize
= 32; // BufferSize: This need to be set according to A-MPDU vector
668 pBA
->BaTimeoutValue
= 0; // Timeout value: Set 0 to disable Timer
669 pBA
->BaStartSeqCtrl
.field
.SeqNum
= (pTS
->TxCurSeq
+ 3) % 4096; // Block Ack will start after 3 packets later.
671 ActivateBAEntry(ieee
, pBA
, BA_SETUP_TIMEOUT
);
673 ieee80211_send_ADDBAReq(ieee
, pTS
->TsCommonInfo
.Addr
, pBA
);
677 TsInitDelBA( struct ieee80211_device
*ieee
, PTS_COMMON_INFO pTsCommonInfo
, TR_SELECT TxRxSelect
)
680 if(TxRxSelect
== TX_DIR
)
682 PTX_TS_RECORD pTxTs
= (PTX_TS_RECORD
)pTsCommonInfo
;
684 if(TxTsDeleteBA(ieee
, pTxTs
))
685 ieee80211_send_DELBA(
688 (pTxTs
->TxAdmittedBARecord
.bValid
)?(&pTxTs
->TxAdmittedBARecord
):(&pTxTs
->TxPendingBARecord
),
690 DELBA_REASON_END_BA
);
692 else if(TxRxSelect
== RX_DIR
)
694 PRX_TS_RECORD pRxTs
= (PRX_TS_RECORD
)pTsCommonInfo
;
695 if(RxTsDeleteBA(ieee
, pRxTs
))
696 ieee80211_send_DELBA(
699 &pRxTs
->RxAdmittedBARecord
,
701 DELBA_REASON_END_BA
);
704 /********************************************************************************************************************
705 *function: BA setup timer
706 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
709 ********************************************************************************************************************/
710 void BaSetupTimeOut(unsigned long data
)
712 PTX_TS_RECORD pTxTs
= (PTX_TS_RECORD
)data
;
714 pTxTs
->bAddBaReqInProgress
= false;
715 pTxTs
->bAddBaReqDelayed
= true;
716 pTxTs
->TxPendingBARecord
.bValid
= false;
719 void TxBaInactTimeout(unsigned long data
)
721 PTX_TS_RECORD pTxTs
= (PTX_TS_RECORD
)data
;
722 struct ieee80211_device
*ieee
= container_of(pTxTs
, struct ieee80211_device
, TxTsRecord
[pTxTs
->num
]);
723 TxTsDeleteBA(ieee
, pTxTs
);
724 ieee80211_send_DELBA(
726 pTxTs
->TsCommonInfo
.Addr
,
727 &pTxTs
->TxAdmittedBARecord
,
729 DELBA_REASON_TIMEOUT
);
732 void RxBaInactTimeout(unsigned long data
)
734 PRX_TS_RECORD pRxTs
= (PRX_TS_RECORD
)data
;
735 struct ieee80211_device
*ieee
= container_of(pRxTs
, struct ieee80211_device
, RxTsRecord
[pRxTs
->num
]);
737 RxTsDeleteBA(ieee
, pRxTs
);
738 ieee80211_send_DELBA(
740 pRxTs
->TsCommonInfo
.Addr
,
741 &pRxTs
->RxAdmittedBARecord
,
743 DELBA_REASON_TIMEOUT
);