• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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 ********************************************************************************************************************/
ActivateBAEntry(struct ieee80211_device * ieee,PBA_RECORD pBA,u16 Time)16 void 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 ********************************************************************************************************************/
DeActivateBAEntry(struct ieee80211_device * ieee,PBA_RECORD pBA)28 void 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 ********************************************************************************************************************/
TxTsDeleteBA(struct ieee80211_device * ieee,PTX_TS_RECORD pTxTs)40 u8 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 ********************************************************************************************************************/
RxTsDeleteBA(struct ieee80211_device * ieee,PRX_TS_RECORD pRxTs)70 u8 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 ********************************************************************************************************************/
ResetBaEntry(PBA_RECORD pBA)90 void 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 *******************************************************************************************************************************/
ieee80211_ADDBA(struct ieee80211_device * ieee,u8 * Dst,PBA_RECORD pBA,u16 StatusCode,u8 type)108 static 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:%pM, ieee->dev:%p\n", __FUNCTION__, type, 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 
178 /********************************************************************************************************************
179  *function:  construct DELBA frame
180  *   input:  u8*		dst	//DELBA frame's destination
181  *	     PBA_RECORD		pBA	//BA_RECORD entry which stores the necessary information for BA
182  *	     TR_SELECT	        TxRxSelect  //TX RX direction
183  *	     u16		ReasonCode  //status code.
184  *  output:  none
185  *  return:  sk_buff*		skb     //return constructed skb to xmit
186 ********************************************************************************************************************/
ieee80211_DELBA(struct ieee80211_device * ieee,u8 * dst,PBA_RECORD pBA,TR_SELECT TxRxSelect,u16 ReasonCode)187 static struct sk_buff* ieee80211_DELBA(
188 	struct ieee80211_device* ieee,
189 	u8*		         dst,
190 	PBA_RECORD		 pBA,
191 	TR_SELECT		 TxRxSelect,
192 	u16			 ReasonCode
193 	)
194 {
195 	DELBA_PARAM_SET	DelbaParamSet;
196 	struct sk_buff *skb = NULL;
197 	 struct ieee80211_hdr_3addr* Delba = NULL;
198 	u8* tag = NULL;
199 	u16 tmp = 0;
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", __FUNCTION__, 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 ieee80211_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 ieee80211_hdr_3addr));
218 	skb_reserve(skb, ieee->tx_headroom);
219 
220 	Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_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 	tmp = cpu_to_le16(DelbaParamSet.shortData);
234 	memcpy(tag, (u8*)&tmp, 2);
235 	tag += 2;
236 	// Reason Code
237 	tmp = cpu_to_le16(ReasonCode);
238 	memcpy(tag, (u8*)&tmp, 2);
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", __FUNCTION__);
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 ********************************************************************************************************************/
ieee80211_send_ADDBAReq(struct ieee80211_device * ieee,u8 * dst,PBA_RECORD pBA)254 void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8*	dst, PBA_RECORD	pBA)
255 {
256 	struct sk_buff *skb = NULL;
257 	skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
258 
259 	if (skb)
260 	{
261 		softmac_mgmt_xmit(skb, ieee);
262 		//add statistic needed here.
263 		//and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
264 		//WB
265 	}
266 	else
267 	{
268 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
269 	}
270 	return;
271 }
272 
273 /********************************************************************************************************************
274  *function: send ADDBARSP frame out
275  *   input:  u8*		dst	//DELBA frame's destination
276  *	     PBA_RECORD		pBA	//BA_RECORD entry which stores the necessary information for BA
277  *	     u16		StatusCode //RSP StatusCode
278  *  output:  none
279  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
280 ********************************************************************************************************************/
ieee80211_send_ADDBARsp(struct ieee80211_device * ieee,u8 * dst,PBA_RECORD pBA,u16 StatusCode)281 void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
282 {
283 	struct sk_buff *skb = NULL;
284 	skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
285 	if (skb)
286 	{
287 		softmac_mgmt_xmit(skb, ieee);
288 		//same above
289 	}
290 	else
291 	{
292 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
293 	}
294 
295 	return;
296 
297 }
298 /********************************************************************************************************************
299  *function: send ADDBARSP frame out
300  *   input:  u8*		dst	//DELBA frame's destination
301  *	     PBA_RECORD		pBA	//BA_RECORD entry which stores the necessary information for BA
302  *	     TR_SELECT          TxRxSelect //TX or RX
303  *	     u16		ReasonCode //DEL ReasonCode
304  *  output:  none
305  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
306 ********************************************************************************************************************/
307 
ieee80211_send_DELBA(struct ieee80211_device * ieee,u8 * dst,PBA_RECORD pBA,TR_SELECT TxRxSelect,u16 ReasonCode)308 void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
309 {
310 	struct sk_buff *skb = NULL;
311 	skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
312 	if (skb)
313 	{
314 		softmac_mgmt_xmit(skb, ieee);
315 		//same above
316 	}
317 	else
318 	{
319 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
320 	}
321 	return ;
322 }
323 
324 /********************************************************************************************************************
325  *function: RX ADDBAReq
326  *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
327  *  return:  0(pass), other(fail)
328  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
329 ********************************************************************************************************************/
ieee80211_rx_ADDBAReq(struct ieee80211_device * ieee,struct sk_buff * skb)330 int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
331 {
332 	 struct ieee80211_hdr_3addr* req = NULL;
333 	u16 rc = 0;
334 	u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
335 	PBA_RECORD pBA = NULL;
336 	PBA_PARAM_SET	pBaParamSet = NULL;
337 	u16* pBaTimeoutVal = NULL;
338 	PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
339 	PRX_TS_RECORD	pTS = NULL;
340 
341 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
342 	{
343 		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,	(sizeof( struct ieee80211_hdr_3addr) + 9));
344 		return -1;
345 	}
346 
347 	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
348 
349 	req = ( struct ieee80211_hdr_3addr*) skb->data;
350 	tag = (u8*)req;
351 	dst = (u8*)(&req->addr2[0]);
352 	tag += sizeof( struct ieee80211_hdr_3addr);
353 	pDialogToken = tag + 2;  //category+action
354 	pBaParamSet = (PBA_PARAM_SET)(tag + 3);   //+DialogToken
355 	pBaTimeoutVal = (u16*)(tag + 5);
356 	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
357 
358 	printk("====================>rx ADDBAREQ from :%pM\n", dst);
359 //some other capability is not ready now.
360 	if(	(ieee->current_network.qos_data.active == 0) ||
361 		(ieee->pHTInfo->bCurrentHTSupport == false)) //||
362 	//	(ieee->pStaQos->bEnableRxImmBA == false)	)
363 	{
364 		rc = ADDBA_STATUS_REFUSED;
365 		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);
366 		goto OnADDBAReq_Fail;
367 	}
368 	// Search for related traffic stream.
369 	// If there is no matched TS, reject the ADDBA request.
370 	if(	!GetTs(
371 			ieee,
372 			(PTS_COMMON_INFO*)(&pTS),
373 			dst,
374 			(u8)(pBaParamSet->field.TID),
375 			RX_DIR,
376 			true)	)
377 	{
378 		rc = ADDBA_STATUS_REFUSED;
379 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
380 		goto OnADDBAReq_Fail;
381 	}
382 	pBA = &pTS->RxAdmittedBARecord;
383 	// To Determine the ADDBA Req content
384 	// We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
385 	// I want to check StartSeqCtrl to make sure when we start aggregation!!!
386 	//
387 	if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
388 	{
389 		rc = ADDBA_STATUS_INVALID_PARAM;
390 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
391 		goto OnADDBAReq_Fail;
392 	}
393 		// Admit the ADDBA Request
394 	//
395 	DeActivateBAEntry(ieee, pBA);
396 	pBA->DialogToken = *pDialogToken;
397 	pBA->BaParamSet = *pBaParamSet;
398 	pBA->BaTimeoutValue = *pBaTimeoutVal;
399 	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
400 	//for half N mode we only aggregate 1 frame
401 	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
402 	pBA->BaParamSet.field.BufferSize = 1;
403 	else
404 	pBA->BaParamSet.field.BufferSize = 32;
405 	ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
406 	ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
407 
408 	// End of procedure.
409 	return 0;
410 
411 OnADDBAReq_Fail:
412 	{
413 		BA_RECORD	BA;
414 		BA.BaParamSet = *pBaParamSet;
415 		BA.BaTimeoutValue = *pBaTimeoutVal;
416 		BA.DialogToken = *pDialogToken;
417 		BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
418 		ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
419 		return 0; //we send RSP out.
420 	}
421 
422 }
423 
424 /********************************************************************************************************************
425  *function: RX ADDBARSP
426  *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
427  *  return:  0(pass), other(fail)
428  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
429 ********************************************************************************************************************/
ieee80211_rx_ADDBARsp(struct ieee80211_device * ieee,struct sk_buff * skb)430 int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
431 {
432 	 struct ieee80211_hdr_3addr* rsp = NULL;
433 	PBA_RECORD		pPendingBA, pAdmittedBA;
434 	PTX_TS_RECORD		pTS = NULL;
435 	u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
436 	u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
437 	PBA_PARAM_SET		pBaParamSet = NULL;
438 	u16			ReasonCode;
439 
440 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
441 	{
442 		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,	(sizeof( struct ieee80211_hdr_3addr) + 9));
443 		return -1;
444 	}
445 	rsp = ( struct ieee80211_hdr_3addr*)skb->data;
446 	tag = (u8*)rsp;
447 	dst = (u8*)(&rsp->addr2[0]);
448 	tag += sizeof( struct ieee80211_hdr_3addr);
449 	pDialogToken = tag + 2;
450 	pStatusCode = (u16*)(tag + 3);
451 	pBaParamSet = (PBA_PARAM_SET)(tag + 5);
452 	pBaTimeoutVal = (u16*)(tag + 7);
453 
454 	// Check the capability
455 	// Since we can always receive A-MPDU, we just check if it is under HT mode.
456 	if(     ieee->current_network.qos_data.active == 0  ||
457 		ieee->pHTInfo->bCurrentHTSupport == false ||
458 		ieee->pHTInfo->bCurrentAMPDUEnable == false )
459 	{
460 		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);
461 		ReasonCode = DELBA_REASON_UNKNOWN_BA;
462 		goto OnADDBARsp_Reject;
463 	}
464 
465 
466 	//
467 	// Search for related TS.
468 	// If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
469 	//
470 	if (!GetTs(
471 			ieee,
472 			(PTS_COMMON_INFO*)(&pTS),
473 			dst,
474 			(u8)(pBaParamSet->field.TID),
475 			TX_DIR,
476 			false)	)
477 	{
478 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
479 		ReasonCode = DELBA_REASON_UNKNOWN_BA;
480 		goto OnADDBARsp_Reject;
481 	}
482 
483 	pTS->bAddBaReqInProgress = false;
484 	pPendingBA = &pTS->TxPendingBARecord;
485 	pAdmittedBA = &pTS->TxAdmittedBARecord;
486 
487 
488 	//
489 	// Check if related BA is waiting for setup.
490 	// If not, reject by sending DELBA frame.
491 	//
492 	if((pAdmittedBA->bValid==true))
493 	{
494 		// Since BA is already setup, we ignore all other ADDBA Response.
495 		IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
496 		return -1;
497 	}
498 	else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
499 	{
500 		IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
501 		ReasonCode = DELBA_REASON_UNKNOWN_BA;
502 		goto OnADDBARsp_Reject;
503 	}
504 	else
505 	{
506 		IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
507 		DeActivateBAEntry(ieee, pPendingBA);
508 	}
509 
510 
511 	if(*pStatusCode == ADDBA_STATUS_SUCCESS)
512 	{
513 		//
514 		// Determine ADDBA Rsp content here.
515 		// We can compare the value of BA parameter set that Peer returned and Self sent.
516 		// If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
517 		//
518 		if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
519 		{
520 			// Since this is a kind of ADDBA failed, we delay next ADDBA process.
521 			pTS->bAddBaReqDelayed = true;
522 			DeActivateBAEntry(ieee, pAdmittedBA);
523 			ReasonCode = DELBA_REASON_END_BA;
524 			goto OnADDBARsp_Reject;
525 		}
526 
527 
528 		//
529 		// Admitted condition
530 		//
531 		pAdmittedBA->DialogToken = *pDialogToken;
532 		pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
533 		pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
534 		pAdmittedBA->BaParamSet = *pBaParamSet;
535 		DeActivateBAEntry(ieee, pAdmittedBA);
536 		ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
537 	}
538 	else
539 	{
540 		// Delay next ADDBA process.
541 		pTS->bAddBaReqDelayed = true;
542 	}
543 
544 	// End of procedure
545 	return 0;
546 
547 OnADDBARsp_Reject:
548 	{
549 		BA_RECORD	BA;
550 		BA.BaParamSet = *pBaParamSet;
551 		ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
552 		return 0;
553 	}
554 
555 }
556 
557 /********************************************************************************************************************
558  *function: RX DELBA
559  *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
560  *  return:  0(pass), other(fail)
561  *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
562 ********************************************************************************************************************/
ieee80211_rx_DELBA(struct ieee80211_device * ieee,struct sk_buff * skb)563 int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
564 {
565 	 struct ieee80211_hdr_3addr* delba = NULL;
566 	PDELBA_PARAM_SET	pDelBaParamSet = NULL;
567 	u16*			pReasonCode = NULL;
568 	u8*			dst = NULL;
569 
570 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
571 	{
572 		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,	(sizeof( struct ieee80211_hdr_3addr) + 6));
573 		return -1;
574 	}
575 
576 	if(ieee->current_network.qos_data.active == 0 ||
577 		ieee->pHTInfo->bCurrentHTSupport == false )
578 	{
579 		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);
580 		return -1;
581 	}
582 
583 	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
584 	delba = ( struct ieee80211_hdr_3addr*)skb->data;
585 	dst = (u8*)(&delba->addr2[0]);
586 	delba += sizeof( struct ieee80211_hdr_3addr);
587 	pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
588 	pReasonCode = (u16*)(delba+4);
589 
590 	if(pDelBaParamSet->field.Initiator == 1)
591 	{
592 		PRX_TS_RECORD	pRxTs;
593 
594 		if( !GetTs(
595 				ieee,
596 				(PTS_COMMON_INFO*)&pRxTs,
597 				dst,
598 				(u8)pDelBaParamSet->field.TID,
599 				RX_DIR,
600 				false)	)
601 		{
602 			IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for RXTS in %s()\n", __FUNCTION__);
603 			return -1;
604 		}
605 
606 		RxTsDeleteBA(ieee, pRxTs);
607 	}
608 	else
609 	{
610 		PTX_TS_RECORD	pTxTs;
611 
612 		if(!GetTs(
613 			ieee,
614 			(PTS_COMMON_INFO*)&pTxTs,
615 			dst,
616 			(u8)pDelBaParamSet->field.TID,
617 			TX_DIR,
618 			false)	)
619 		{
620 			IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for TXTS in %s()\n", __FUNCTION__);
621 			return -1;
622 		}
623 
624 		pTxTs->bUsingBa = false;
625 		pTxTs->bAddBaReqInProgress = false;
626 		pTxTs->bAddBaReqDelayed = false;
627 		del_timer_sync(&pTxTs->TsAddBaTimer);
628 		//PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
629 		TxTsDeleteBA(ieee, pTxTs);
630 	}
631 	return 0;
632 }
633 
634 //
635 // ADDBA initiate. This can only be called by TX side.
636 //
637 void
TsInitAddBA(struct ieee80211_device * ieee,PTX_TS_RECORD pTS,u8 Policy,u8 bOverwritePending)638 TsInitAddBA(
639 	struct ieee80211_device* ieee,
640 	PTX_TS_RECORD	pTS,
641 	u8		Policy,
642 	u8		bOverwritePending
643 	)
644 {
645 	PBA_RECORD			pBA = &pTS->TxPendingBARecord;
646 
647 	if(pBA->bValid==true && bOverwritePending==false)
648 		return;
649 
650 	// Set parameters to "Pending" variable set
651 	DeActivateBAEntry(ieee, pBA);
652 
653 	pBA->DialogToken++;						// DialogToken: Only keep the latest dialog token
654 	pBA->BaParamSet.field.AMSDU_Support = 0;	// Do not support A-MSDU with A-MPDU now!!
655 	pBA->BaParamSet.field.BAPolicy = Policy;	// Policy: Delayed or Immediate
656 	pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;	// TID
657 	// BufferSize: This need to be set according to A-MPDU vector
658 	pBA->BaParamSet.field.BufferSize = 32;		// BufferSize: This need to be set according to A-MPDU vector
659 	pBA->BaTimeoutValue = 0;					// Timeout value: Set 0 to disable Timer
660 	pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;	// Block Ack will start after 3 packets later.
661 
662 	ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
663 
664 	ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
665 }
666 
667 void
TsInitDelBA(struct ieee80211_device * ieee,PTS_COMMON_INFO pTsCommonInfo,TR_SELECT TxRxSelect)668 TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
669 {
670 
671 	if(TxRxSelect == TX_DIR)
672 	{
673 		PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
674 
675 		if(TxTsDeleteBA(ieee, pTxTs))
676 			ieee80211_send_DELBA(
677 				ieee,
678 				pTsCommonInfo->Addr,
679 				(pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
680 				TxRxSelect,
681 				DELBA_REASON_END_BA);
682 	}
683 	else if(TxRxSelect == RX_DIR)
684 	{
685 		PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
686 		if(RxTsDeleteBA(ieee, pRxTs))
687 			ieee80211_send_DELBA(
688 				ieee,
689 				pTsCommonInfo->Addr,
690 				&pRxTs->RxAdmittedBARecord,
691 				TxRxSelect,
692 				DELBA_REASON_END_BA	);
693 	}
694 }
695 /********************************************************************************************************************
696  *function:  BA setup timer
697  *   input:  unsigned long	 data		//acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
698  *  return:  NULL
699  *  notice:
700 ********************************************************************************************************************/
BaSetupTimeOut(unsigned long data)701 void BaSetupTimeOut(unsigned long data)
702 {
703 	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
704 
705 	pTxTs->bAddBaReqInProgress = false;
706 	pTxTs->bAddBaReqDelayed = true;
707 	pTxTs->TxPendingBARecord.bValid = false;
708 }
709 
TxBaInactTimeout(unsigned long data)710 void TxBaInactTimeout(unsigned long data)
711 {
712 	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
713 	struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
714 	TxTsDeleteBA(ieee, pTxTs);
715 	ieee80211_send_DELBA(
716 		ieee,
717 		pTxTs->TsCommonInfo.Addr,
718 		&pTxTs->TxAdmittedBARecord,
719 		TX_DIR,
720 		DELBA_REASON_TIMEOUT);
721 }
722 
RxBaInactTimeout(unsigned long data)723 void RxBaInactTimeout(unsigned long data)
724 {
725 	PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)data;
726 	struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
727 
728 	RxTsDeleteBA(ieee, pRxTs);
729 	ieee80211_send_DELBA(
730 		ieee,
731 		pRxTs->TsCommonInfo.Addr,
732 		&pRxTs->RxAdmittedBARecord,
733 		RX_DIR,
734 		DELBA_REASON_TIMEOUT);
735 	return ;
736 }
737