Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl819x_BAProc.c
Go to the documentation of this file.
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 *******************************************************************************************************************************/
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 
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 ********************************************************************************************************************/
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 
242  if (net_ratelimit())
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 
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 ********************************************************************************************************************/
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 
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  {
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  {
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  {
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);
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 ********************************************************************************************************************/
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 ********************************************************************************************************************/
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 
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
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
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))
677  ieee,
678  pTsCommonInfo->Addr,
679  (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
680  TxRxSelect,
682  }
683  else if(TxRxSelect == RX_DIR)
684  {
685  PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
686  if(RxTsDeleteBA(ieee, pRxTs))
688  ieee,
689  pTsCommonInfo->Addr,
690  &pRxTs->RxAdmittedBARecord,
691  TxRxSelect,
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 ********************************************************************************************************************/
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 
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);
716  ieee,
717  pTxTs->TsCommonInfo.Addr,
718  &pTxTs->TxAdmittedBARecord,
719  TX_DIR,
721 }
722 
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);
730  ieee,
731  pRxTs->TsCommonInfo.Addr,
732  &pRxTs->RxAdmittedBARecord,
733  RX_DIR,
735  return ;
736 }
737