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