1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <asm/byteorder.h>
16#include <asm/unaligned.h>
17#include <linux/etherdevice.h>
18#include "rtllib.h"
19#include "rtl819x_BA.h"
20
21static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
22 u16 Time)
23{
24 pBA->bValid = true;
25 if (Time != 0)
26 mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
27}
28
29static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA)
30{
31 pBA->bValid = false;
32 del_timer_sync(&pBA->Timer);
33}
34
35static u8 TxTsDeleteBA(struct rtllib_device *ieee, struct tx_ts_record *pTxTs)
36{
37 struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord;
38 struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord;
39 u8 bSendDELBA = false;
40
41 if (pPendingBa->bValid) {
42 DeActivateBAEntry(ieee, pPendingBa);
43 bSendDELBA = true;
44 }
45
46 if (pAdmittedBa->bValid) {
47 DeActivateBAEntry(ieee, pAdmittedBa);
48 bSendDELBA = true;
49 }
50 return bSendDELBA;
51}
52
53static u8 RxTsDeleteBA(struct rtllib_device *ieee, struct rx_ts_record *pRxTs)
54{
55 struct ba_record *pBa = &pRxTs->RxAdmittedBARecord;
56 u8 bSendDELBA = false;
57
58 if (pBa->bValid) {
59 DeActivateBAEntry(ieee, pBa);
60 bSendDELBA = true;
61 }
62
63 return bSendDELBA;
64}
65
66void ResetBaEntry(struct ba_record *pBA)
67{
68 pBA->bValid = false;
69 pBA->BaParamSet.shortData = 0;
70 pBA->BaTimeoutValue = 0;
71 pBA->DialogToken = 0;
72 pBA->BaStartSeqCtrl.ShortData = 0;
73}
74static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
75 struct ba_record *pBA,
76 u16 StatusCode, u8 type)
77{
78 struct sk_buff *skb = NULL;
79 struct rtllib_hdr_3addr *BAReq = NULL;
80 u8 *tag = NULL;
81 u16 len = ieee->tx_headroom + 9;
82
83 netdev_dbg(ieee->dev, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n",
84 __func__, type, Dst, ieee->dev);
85
86 if (pBA == NULL) {
87 netdev_warn(ieee->dev, "pBA is NULL\n");
88 return NULL;
89 }
90 skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
91 if (!skb)
92 return NULL;
93
94 memset(skb->data, 0, sizeof(struct rtllib_hdr_3addr));
95
96 skb_reserve(skb, ieee->tx_headroom);
97
98 BAReq = skb_put(skb, sizeof(struct rtllib_hdr_3addr));
99
100 ether_addr_copy(BAReq->addr1, Dst);
101 ether_addr_copy(BAReq->addr2, ieee->dev->dev_addr);
102
103 ether_addr_copy(BAReq->addr3, ieee->current_network.bssid);
104 BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
105
106 tag = skb_put(skb, 9);
107 *tag++ = ACT_CAT_BA;
108 *tag++ = type;
109 *tag++ = pBA->DialogToken;
110
111 if (type == ACT_ADDBARSP) {
112 RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n");
113
114 put_unaligned_le16(StatusCode, tag);
115 tag += 2;
116 }
117
118 put_unaligned_le16(pBA->BaParamSet.shortData, tag);
119 tag += 2;
120
121 put_unaligned_le16(pBA->BaTimeoutValue, tag);
122 tag += 2;
123
124 if (type == ACT_ADDBAREQ) {
125 memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
126 tag += 2;
127 }
128
129#ifdef VERBOSE_DEBUG
130 print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE, skb->data,
131 skb->len);
132#endif
133 return skb;
134}
135
136static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
137 struct ba_record *pBA,
138 enum tr_select TxRxSelect, u16 ReasonCode)
139{
140 union delba_param_set DelbaParamSet;
141 struct sk_buff *skb = NULL;
142 struct rtllib_hdr_3addr *Delba = NULL;
143 u8 *tag = NULL;
144 u16 len = 6 + ieee->tx_headroom;
145
146 if (net_ratelimit())
147 netdev_dbg(ieee->dev, "%s(): ReasonCode(%d) sentd to: %pM\n",
148 __func__, ReasonCode, dst);
149
150 memset(&DelbaParamSet, 0, 2);
151
152 DelbaParamSet.field.Initiator = (TxRxSelect == TX_DIR) ? 1 : 0;
153 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
154
155 skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
156 if (!skb)
157 return NULL;
158
159 skb_reserve(skb, ieee->tx_headroom);
160
161 Delba = skb_put(skb, sizeof(struct rtllib_hdr_3addr));
162
163 ether_addr_copy(Delba->addr1, dst);
164 ether_addr_copy(Delba->addr2, ieee->dev->dev_addr);
165 ether_addr_copy(Delba->addr3, ieee->current_network.bssid);
166 Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
167
168 tag = skb_put(skb, 6);
169
170 *tag++ = ACT_CAT_BA;
171 *tag++ = ACT_DELBA;
172
173
174 put_unaligned_le16(DelbaParamSet.shortData, tag);
175 tag += 2;
176
177 put_unaligned_le16(ReasonCode, tag);
178 tag += 2;
179
180#ifdef VERBOSE_DEBUG
181 print_hex_dump_bytes("rtllib_DELBA(): ", DUMP_PREFIX_NONE, skb->data,
182 skb->len);
183#endif
184 return skb;
185}
186
187static void rtllib_send_ADDBAReq(struct rtllib_device *ieee, u8 *dst,
188 struct ba_record *pBA)
189{
190 struct sk_buff *skb;
191
192 skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ);
193
194 if (skb) {
195 RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n");
196 softmac_mgmt_xmit(skb, ieee);
197 } else {
198 netdev_dbg(ieee->dev, "Failed to generate ADDBAReq packet.\n");
199 }
200}
201
202static void rtllib_send_ADDBARsp(struct rtllib_device *ieee, u8 *dst,
203 struct ba_record *pBA, u16 StatusCode)
204{
205 struct sk_buff *skb;
206
207 skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP);
208 if (skb)
209 softmac_mgmt_xmit(skb, ieee);
210 else
211 netdev_dbg(ieee->dev, "Failed to generate ADDBARsp packet.\n");
212}
213
214static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst,
215 struct ba_record *pBA, enum tr_select TxRxSelect,
216 u16 ReasonCode)
217{
218 struct sk_buff *skb;
219
220 skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode);
221 if (skb)
222 softmac_mgmt_xmit(skb, ieee);
223 else
224 netdev_dbg(ieee->dev, "Failed to generate DELBA packet.\n");
225}
226
227int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
228{
229 struct rtllib_hdr_3addr *req = NULL;
230 u16 rc = 0;
231 u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
232 struct ba_record *pBA = NULL;
233 union ba_param_set *pBaParamSet = NULL;
234 u16 *pBaTimeoutVal = NULL;
235 union sequence_control *pBaStartSeqCtrl = NULL;
236 struct rx_ts_record *pTS = NULL;
237
238 if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
239 netdev_warn(ieee->dev, "Invalid skb len in BAREQ(%d / %d)\n",
240 (int)skb->len,
241 (int)(sizeof(struct rtllib_hdr_3addr) + 9));
242 return -1;
243 }
244
245#ifdef VERBOSE_DEBUG
246 print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE,
247 skb->data, skb->len);
248#endif
249
250 req = (struct rtllib_hdr_3addr *) skb->data;
251 tag = (u8 *)req;
252 dst = (u8 *)(&req->addr2[0]);
253 tag += sizeof(struct rtllib_hdr_3addr);
254 pDialogToken = tag + 2;
255 pBaParamSet = (union ba_param_set *)(tag + 3);
256 pBaTimeoutVal = (u16 *)(tag + 5);
257 pBaStartSeqCtrl = (union sequence_control *)(req + 7);
258
259 RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from : %pM\n", dst);
260 if (ieee->current_network.qos_data.active == 0 ||
261 (ieee->pHTInfo->bCurrentHTSupport == false) ||
262 (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
263 rc = ADDBA_STATUS_REFUSED;
264 netdev_warn(ieee->dev,
265 "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
266 ieee->current_network.qos_data.active,
267 ieee->pHTInfo->bCurrentHTSupport);
268 goto OnADDBAReq_Fail;
269 }
270 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
271 (u8)(pBaParamSet->field.TID), RX_DIR, true)) {
272 rc = ADDBA_STATUS_REFUSED;
273 netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
274 goto OnADDBAReq_Fail;
275 }
276 pBA = &pTS->RxAdmittedBARecord;
277
278 if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
279 rc = ADDBA_STATUS_INVALID_PARAM;
280 netdev_warn(ieee->dev, "%s(): BA Policy is not correct\n",
281 __func__);
282 goto OnADDBAReq_Fail;
283 }
284
285 rtllib_FlushRxTsPendingPkts(ieee, pTS);
286
287 DeActivateBAEntry(ieee, pBA);
288 pBA->DialogToken = *pDialogToken;
289 pBA->BaParamSet = *pBaParamSet;
290 pBA->BaTimeoutValue = *pBaTimeoutVal;
291 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
292
293 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev) ||
294 (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
295 pBA->BaParamSet.field.BufferSize = 1;
296 else
297 pBA->BaParamSet.field.BufferSize = 32;
298
299 ActivateBAEntry(ieee, pBA, 0);
300 rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
301
302 return 0;
303
304OnADDBAReq_Fail:
305 {
306 struct ba_record BA;
307
308 BA.BaParamSet = *pBaParamSet;
309 BA.BaTimeoutValue = *pBaTimeoutVal;
310 BA.DialogToken = *pDialogToken;
311 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
312 rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
313 return 0;
314 }
315}
316
317int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
318{
319 struct rtllib_hdr_3addr *rsp = NULL;
320 struct ba_record *pPendingBA, *pAdmittedBA;
321 struct tx_ts_record *pTS = NULL;
322 u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
323 u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
324 union ba_param_set *pBaParamSet = NULL;
325 u16 ReasonCode;
326
327 if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
328 netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n",
329 (int)skb->len,
330 (int)(sizeof(struct rtllib_hdr_3addr) + 9));
331 return -1;
332 }
333 rsp = (struct rtllib_hdr_3addr *)skb->data;
334 tag = (u8 *)rsp;
335 dst = (u8 *)(&rsp->addr2[0]);
336 tag += sizeof(struct rtllib_hdr_3addr);
337 pDialogToken = tag + 2;
338 pStatusCode = (u16 *)(tag + 3);
339 pBaParamSet = (union ba_param_set *)(tag + 5);
340 pBaTimeoutVal = (u16 *)(tag + 7);
341
342 RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst);
343 if (ieee->current_network.qos_data.active == 0 ||
344 ieee->pHTInfo->bCurrentHTSupport == false ||
345 ieee->pHTInfo->bCurrentAMPDUEnable == false) {
346 netdev_warn(ieee->dev,
347 "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
348 ieee->current_network.qos_data.active,
349 ieee->pHTInfo->bCurrentHTSupport,
350 ieee->pHTInfo->bCurrentAMPDUEnable);
351 ReasonCode = DELBA_REASON_UNKNOWN_BA;
352 goto OnADDBARsp_Reject;
353 }
354
355
356 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
357 (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
358 netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
359 ReasonCode = DELBA_REASON_UNKNOWN_BA;
360 goto OnADDBARsp_Reject;
361 }
362
363 pTS->bAddBaReqInProgress = false;
364 pPendingBA = &pTS->TxPendingBARecord;
365 pAdmittedBA = &pTS->TxAdmittedBARecord;
366
367
368 if (pAdmittedBA->bValid == true) {
369 netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n",
370 __func__);
371 return -1;
372 } else if ((pPendingBA->bValid == false) ||
373 (*pDialogToken != pPendingBA->DialogToken)) {
374 netdev_warn(ieee->dev,
375 "%s(): ADDBA Rsp. BA invalid, DELBA!\n",
376 __func__);
377 ReasonCode = DELBA_REASON_UNKNOWN_BA;
378 goto OnADDBARsp_Reject;
379 } else {
380 netdev_dbg(ieee->dev,
381 "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
382 __func__, *pStatusCode);
383 DeActivateBAEntry(ieee, pPendingBA);
384 }
385
386
387 if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
388 if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
389 pTS->bAddBaReqDelayed = true;
390 DeActivateBAEntry(ieee, pAdmittedBA);
391 ReasonCode = DELBA_REASON_END_BA;
392 goto OnADDBARsp_Reject;
393 }
394
395
396 pAdmittedBA->DialogToken = *pDialogToken;
397 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
398 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
399 pAdmittedBA->BaParamSet = *pBaParamSet;
400 DeActivateBAEntry(ieee, pAdmittedBA);
401 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
402 } else {
403 pTS->bAddBaReqDelayed = true;
404 pTS->bDisable_AddBa = true;
405 ReasonCode = DELBA_REASON_END_BA;
406 goto OnADDBARsp_Reject;
407 }
408
409 return 0;
410
411OnADDBARsp_Reject:
412 {
413 struct ba_record BA;
414
415 BA.BaParamSet = *pBaParamSet;
416 rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
417 return 0;
418 }
419}
420
421int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
422{
423 struct rtllib_hdr_3addr *delba = NULL;
424 union delba_param_set *pDelBaParamSet = NULL;
425 u8 *dst = NULL;
426
427 if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
428 netdev_warn(ieee->dev, "Invalid skb len in DELBA(%d / %d)\n",
429 (int)skb->len,
430 (int)(sizeof(struct rtllib_hdr_3addr) + 6));
431 return -1;
432 }
433
434 if (ieee->current_network.qos_data.active == 0 ||
435 ieee->pHTInfo->bCurrentHTSupport == false) {
436 netdev_warn(ieee->dev,
437 "received DELBA while QOS or HT is not supported(%d, %d)\n",
438 ieee->current_network. qos_data.active,
439 ieee->pHTInfo->bCurrentHTSupport);
440 return -1;
441 }
442
443#ifdef VERBOSE_DEBUG
444 print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE, skb->data,
445 skb->len);
446#endif
447 delba = (struct rtllib_hdr_3addr *)skb->data;
448 dst = (u8 *)(&delba->addr2[0]);
449 pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
450
451 if (pDelBaParamSet->field.Initiator == 1) {
452 struct rx_ts_record *pRxTs;
453
454 if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
455 (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
456 netdev_warn(ieee->dev,
457 "%s(): can't get TS for RXTS. dst:%pM TID:%d\n",
458 __func__, dst,
459 (u8)pDelBaParamSet->field.TID);
460 return -1;
461 }
462
463 RxTsDeleteBA(ieee, pRxTs);
464 } else {
465 struct tx_ts_record *pTxTs;
466
467 if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
468 (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
469 netdev_warn(ieee->dev, "%s(): can't get TS for TXTS\n",
470 __func__);
471 return -1;
472 }
473
474 pTxTs->bUsingBa = false;
475 pTxTs->bAddBaReqInProgress = false;
476 pTxTs->bAddBaReqDelayed = false;
477 del_timer_sync(&pTxTs->TsAddBaTimer);
478 TxTsDeleteBA(ieee, pTxTs);
479 }
480 return 0;
481}
482
483void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
484 u8 Policy, u8 bOverwritePending)
485{
486 struct ba_record *pBA = &pTS->TxPendingBARecord;
487
488 if (pBA->bValid == true && bOverwritePending == false)
489 return;
490
491 DeActivateBAEntry(ieee, pBA);
492
493 pBA->DialogToken++;
494 pBA->BaParamSet.field.AMSDU_Support = 0;
495 pBA->BaParamSet.field.BAPolicy = Policy;
496 pBA->BaParamSet.field.TID =
497 pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;
498 pBA->BaParamSet.field.BufferSize = 32;
499 pBA->BaTimeoutValue = 0;
500 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;
501
502 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
503
504 rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
505}
506
507void TsInitDelBA(struct rtllib_device *ieee,
508 struct ts_common_info *pTsCommonInfo,
509 enum tr_select TxRxSelect)
510{
511 if (TxRxSelect == TX_DIR) {
512 struct tx_ts_record *pTxTs =
513 (struct tx_ts_record *)pTsCommonInfo;
514
515 if (TxTsDeleteBA(ieee, pTxTs))
516 rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
517 (pTxTs->TxAdmittedBARecord.bValid) ?
518 (&pTxTs->TxAdmittedBARecord) :
519 (&pTxTs->TxPendingBARecord),
520 TxRxSelect, DELBA_REASON_END_BA);
521 } else if (TxRxSelect == RX_DIR) {
522 struct rx_ts_record *pRxTs =
523 (struct rx_ts_record *)pTsCommonInfo;
524 if (RxTsDeleteBA(ieee, pRxTs))
525 rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
526 &pRxTs->RxAdmittedBARecord,
527 TxRxSelect, DELBA_REASON_END_BA);
528 }
529}
530
531void BaSetupTimeOut(struct timer_list *t)
532{
533 struct tx_ts_record *pTxTs = from_timer(pTxTs, t,
534 TxPendingBARecord.Timer);
535
536 pTxTs->bAddBaReqInProgress = false;
537 pTxTs->bAddBaReqDelayed = true;
538 pTxTs->TxPendingBARecord.bValid = false;
539}
540
541void TxBaInactTimeout(struct timer_list *t)
542{
543 struct tx_ts_record *pTxTs = from_timer(pTxTs, t,
544 TxAdmittedBARecord.Timer);
545 struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
546 TxTsRecord[pTxTs->num]);
547 TxTsDeleteBA(ieee, pTxTs);
548 rtllib_send_DELBA(ieee, pTxTs->TsCommonInfo.Addr,
549 &pTxTs->TxAdmittedBARecord, TX_DIR,
550 DELBA_REASON_TIMEOUT);
551}
552
553void RxBaInactTimeout(struct timer_list *t)
554{
555 struct rx_ts_record *pRxTs = from_timer(pRxTs, t,
556 RxAdmittedBARecord.Timer);
557 struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
558 RxTsRecord[pRxTs->num]);
559
560 RxTsDeleteBA(ieee, pRxTs);
561 rtllib_send_DELBA(ieee, pRxTs->TsCommonInfo.Addr,
562 &pRxTs->RxAdmittedBARecord, RX_DIR,
563 DELBA_REASON_TIMEOUT);
564}
565