PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/net/wireless/tiwlan1251/common/src/core/data_ctrl/Ctrl/4X/ackEmulUtil.c

http://github.com/CyanogenMod/cm-kernel
C | 1205 lines | 647 code | 235 blank | 323 comment | 89 complexity | 48267bdb2fd9c105ca6fc8d06e588a53 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.0
  1. /****************************************************************************
  2. **+-----------------------------------------------------------------------+**
  3. **| |**
  4. **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
  5. **| All rights reserved. |**
  6. **| |**
  7. **| Redistribution and use in source and binary forms, with or without |**
  8. **| modification, are permitted provided that the following conditions |**
  9. **| are met: |**
  10. **| |**
  11. **| * Redistributions of source code must retain the above copyright |**
  12. **| notice, this list of conditions and the following disclaimer. |**
  13. **| * Redistributions in binary form must reproduce the above copyright |**
  14. **| notice, this list of conditions and the following disclaimer in |**
  15. **| the documentation and/or other materials provided with the |**
  16. **| distribution. |**
  17. **| * Neither the name Texas Instruments nor the names of its |**
  18. **| contributors may be used to endorse or promote products derived |**
  19. **| from this software without specific prior written permission. |**
  20. **| |**
  21. **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |**
  22. **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |**
  23. **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
  24. **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |**
  25. **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
  26. **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |**
  27. **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
  28. **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
  29. **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |**
  30. **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
  31. **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |**
  32. **| |**
  33. **+-----------------------------------------------------------------------+**
  34. ****************************************************************************/
  35. /***************************************************************************/
  36. /* */
  37. /* MODULE: ackEmulUtil.c */
  38. /* PURPOSE: Ack emulation utility */
  39. /* */
  40. /***************************************************************************/
  41. #include "osApi.h"
  42. #include "802_11Defs.h"
  43. #include "ackEmulDb.h"
  44. #include "report.h"
  45. #include "utils.h"
  46. #include "memMngrEx.h"
  47. #include "ackEmulDb.h"
  48. #include "ackEmulUtil.h"
  49. #include "whalCtrl_api.h"
  50. /* The minimum of segment size in byte to lock the segment size */
  51. #define MIN_LOCK_SEGMENT_SIZE 500
  52. typedef enum {
  53. OTHER =0,
  54. TCP_ACK_ONLY ,
  55. TCP_DATA ,
  56. } packetInclude_T;
  57. #define TI_SNAP_HEADER_LEN 8
  58. #define TI_SNAP_AE_TYPE 0x02
  59. #define TI_SNAP_AE_LEN 3
  60. #define OFFSET_802_3_HDR 14
  61. #define K_FACTOR 14
  62. /* TI Snap Header */
  63. /* -------------------------------------------
  64. | dsap | SSAP | Control | OUI | Type |
  65. | 0xAA | 0xAA | 0x00 | 0x080028 | 0x60D0 |
  66. ------------------------------------------- */
  67. static UINT8 tiSnapHeader[]={0xAA,0xAA,0x00,0x08,0x00,0x28,0x60,0xD0};
  68. static void wdrv_ackEmulationPktType(ackEmul_t* ackEmul, UINT8 *pWlanSnapHeader ,UINT8 *pIpHeader , packetInclude_T *packetInclude, UINT16 *tcpDataSize);
  69. static void wdrv_ackEmulationDataStandbyState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader);
  70. static void wdrv_ackEmulationAckStandbyState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader);
  71. static void wdrv_ackEmulationAckCandidateActivState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader,
  72. UINT8 *addYTag, UINT8 *activeIndex,
  73. UINT32 *segmentSize);
  74. static void wdrv_ackEmulationAckActivState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader,UINT8 *dropAck);
  75. static void wdrv_ackEmulationAckTerminateState(ackEmul_t* ackEmul, UINT8 sessionIndex);
  76. static void wdrv_ackEmulationAddYTag(ackEmul_t* ackEmul, UINT8 *pDot11Header, UINT16 firstBdLength,
  77. UINT8 activeIndex, UINT32 segmentSize);
  78. static int wdrv_aeChackSnapWithYtag(ackEmul_t* ackEmul, UINT8 *pSnapHeader, UINT8 *tiSnapLen,
  79. UINT8 *activeIndex, UINT16 *segmentSize);
  80. static void wdrv_aeGenerateAck(ackEmul_t* ackEmul, UINT16 stationIndex, UINT8 activeIndex ,UINT32 ackNumber);
  81. static UINT16 wdrv_IpChecksumCalc(ackEmul_t* ackEmul, UINT16 len_ip_header, UINT8 *buff);
  82. static UINT16 wdrv_TcpChecksumCalc(ackEmul_t* ackEmul, UINT16 len_tcp_header,UINT8 *IpSource, UINT8 *IpDest ,UINT8 *buff);
  83. ackEmul_t* ackEmul_create(TI_HANDLE hOs)
  84. {
  85. ackEmul_t* ackEmul;
  86. ackEmulDB_t* ackEmulDB;
  87. if( hOs == NULL )
  88. {
  89. WLAN_OS_REPORT(("FATAL ERROR: ackEmul_create(): OS handle Error - Aborting\n"));
  90. return NULL;
  91. }
  92. ackEmul = os_memoryAlloc(hOs, (sizeof(ackEmul_t)));
  93. ackEmulDB = ackEmulDb_create(hOs);
  94. if ( (!ackEmul) || (!ackEmulDB) )
  95. {
  96. utils_nullMemoryFree(hOs, ackEmul, sizeof(ackEmul_t));
  97. utils_nullMemoryFree(hOs, ackEmulDB, sizeof(ackEmulDB_t));
  98. WLAN_OS_REPORT(("FATAL ERROR: ackEmul_create(): Error Creating ackEmulDB module- Aborting\n"));
  99. return(NULL);
  100. }
  101. /* reset control module control block */
  102. os_memoryZero(hOs, ackEmul, (sizeof(ackEmul_t)));
  103. ackEmul->pAckEmulDB = ackEmulDB;
  104. ackEmul->hOs = hOs;
  105. return(ackEmul);
  106. }
  107. TI_STATUS ackEmul_config(ackEmul_t* ackEmul,
  108. TI_HANDLE hWhalCtrl,
  109. TI_HANDLE hOs,
  110. TI_HANDLE hReport,
  111. TI_HANDLE hMemMngr)
  112. {
  113. /* check parameters validity */
  114. if( (ackEmul == NULL) || (hOs == NULL) || (hReport == NULL)||
  115. (hWhalCtrl == NULL) || (hMemMngr == NULL) )
  116. {
  117. WLAN_OS_REPORT(("FATAL ERROR: ackEmul_config(): Parameters Error - Aborting\n"));
  118. return NOK;
  119. }
  120. /* set objects handles */
  121. ackEmul->hOs = hOs;
  122. ackEmul->hReport = hReport;
  123. ackEmul->hMemMngr = hMemMngr;
  124. ackEmul->hWhalCtrl = hWhalCtrl;
  125. ackEmul->ackEmulationActive = TRUE;
  126. ackEmulDb_config(ackEmul->pAckEmulDB,hOs,hReport);
  127. /*whalCtrl_setSend4xWackInfo(ackEmul->hWhalCtrl, 0); */
  128. WLAN_REPORT_INIT(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  129. (".....ackEmul configured successfully\n"));
  130. return OK;
  131. }
  132. TI_STATUS ackEmul_destroy(ackEmul_t* ackEmul)
  133. {
  134. ackEmulDb_destroy(ackEmul->pAckEmulDB);
  135. /* free control module controll block */
  136. os_memoryFree(ackEmul->hOs, ackEmul, sizeof(ackEmul_t));
  137. return OK;
  138. }
  139. /**********************************************************************************
  140. * wdrv_ackEmulationRxPacket()
  141. **********************************************************************************
  142. * DESCRIPTION: This is the Ack emulation packet receiver main function.
  143. *
  144. * INPUTS: *pMsdu - Pointer to the packet MSDU.
  145. *
  146. * OUTPUT: None
  147. *
  148. * RETURNS: None
  149. **********************************************************************************/
  150. TI_STATUS wdrv_ackEmulationRxPacket(ackEmul_t* ackEmul, mem_MSDU_T *pMsdu)
  151. {
  152. UINT8 rc;
  153. UINT8 *dataBuf;
  154. dot11_header_t *pDot11Header;
  155. UINT8 *pWlanSnapHeader;
  156. UINT8 *pSnapHeader;
  157. UINT8 *pIpHeader;
  158. UINT16 tcpDataSize;
  159. packetInclude_T packetInclude;
  160. UINT8 sessionIndex, monitorState;
  161. UINT8 activeIndex = 0xff;
  162. UINT16 segmentSize = 0;
  163. UINT8 tiSnapLen = 0;
  164. UINT16 dataLen;
  165. UINT8 WTsessionIndex =0xff;
  166. UINT8 XTag =0;
  167. if (ackEmul->ackEmulationActive == FALSE)
  168. return OK;
  169. dataBuf = (UINT8 *)memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr);
  170. dataLen = memMgr_BufLength(pMsdu->firstBDPtr);
  171. pDot11Header = (dot11_header_t*) dataBuf;
  172. /* Find the station Index */
  173. XTag = ((pDot11Header->fc)&0x8000)>>15;
  174. pSnapHeader = dataBuf + WLAN_HDR_LEN;
  175. pWlanSnapHeader = dataBuf + WLAN_HDR_LEN;
  176. pIpHeader = pWlanSnapHeader + WLAN_SNAP_HDR_LEN;
  177. /* Chack if SNAP with Y TAG */
  178. rc = wdrv_aeChackSnapWithYtag(ackEmul, pSnapHeader, &tiSnapLen, &activeIndex, &segmentSize);
  179. if(rc == OK)
  180. {
  181. WLAN_REPORT_WARNING(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  182. ("Packet with Ytag........\n"));
  183. /* remove the TI SMAP */
  184. os_memoryMove(NULL, pSnapHeader,pSnapHeader + tiSnapLen, dataLen - WLAN_HDR_LEN - tiSnapLen);
  185. pMsdu->firstBDPtr->length -= tiSnapLen ;
  186. pMsdu->dataLen -= tiSnapLen;
  187. /* Update table and save template */
  188. wdrv_aeWSourceSaveAckTemplate(ackEmul->pAckEmulDB, 0,activeIndex,dataBuf,pWlanSnapHeader,pIpHeader,(UINT16)pMsdu->dataLen,segmentSize);
  189. return OK;
  190. }
  191. /* Packet without ack emulation TI Snap */
  192. /* Find the packet type and length */
  193. wdrv_ackEmulationPktType(ackEmul, pWlanSnapHeader,pIpHeader,&packetInclude,&tcpDataSize);
  194. switch (packetInclude)
  195. {
  196. case TCP_DATA:
  197. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  198. ("RX packet = TCP_DATA....\n"));
  199. rc = wdrv_aeWTargetDbFindDataSession(ackEmul->pAckEmulDB, pIpHeader ,&sessionIndex, &monitorState);
  200. if(rc == OK)
  201. {
  202. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  203. ("RX packet XTAG = %d......\n",XTag));
  204. wdrv_aeDbSetXTagStatus(ackEmul->pAckEmulDB, sessionIndex, XTag);
  205. }
  206. switch (monitorState)
  207. {
  208. case AE_INACTIVE:
  209. rc = wdrv_aeWTargetDbAddSession(ackEmul->pAckEmulDB, pIpHeader);
  210. break;
  211. case AE_STANDBY:
  212. wdrv_ackEmulationDataStandbyState(ackEmul, sessionIndex, pIpHeader);
  213. break;
  214. case AE_CANDIDATE_ACTIVE:
  215. break;
  216. case AE_ACTIVE:
  217. default:
  218. break;
  219. }
  220. /* printf("\n rc= %d sessionIndex = %d monitorState = %d\n",rc, sessionIndex , monitorState);*/
  221. break;
  222. case TCP_ACK_ONLY:
  223. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  224. ("RX packet = TCP_ACK_ONLY....\n"));
  225. wdrv_aeWSourceDbUpdateTemplate(ackEmul->pAckEmulDB, pIpHeader,0,&WTsessionIndex);
  226. break;
  227. case OTHER:
  228. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  229. ("RX packet = OTHER....\n"));
  230. default:
  231. break;
  232. }
  233. /*wdrv_aeWTargetDbPrint(ackEmul->pAckEmulDB);*/
  234. return OK;
  235. }
  236. /**********************************************************************************
  237. * wdrv_ackEmulationTxPacket()
  238. **********************************************************************************
  239. * DESCRIPTION: This is the Ack emulation packet transmission main function.
  240. *
  241. * INPUTS: *pMsdu - Pointer to the packet MSDU.
  242. *
  243. * OUTPUT: *discardPacket - If TRUE discard the msdu.
  244. *
  245. * RETURNS: None
  246. **********************************************************************************/
  247. TI_STATUS wdrv_ackEmulationTxPacket(ackEmul_t* ackEmul, mem_MSDU_T *pMsdu,int *discardPacket)
  248. {
  249. UINT8 *pDot11Header;
  250. UINT8 *pWlanSnapHeader;
  251. UINT8 *pIpHeader;
  252. UINT16 tcpDataSize;
  253. packetInclude_T packetInclude;
  254. UINT8 sessionIndex = 0xff;
  255. UINT8 monitorState = 0xff;
  256. UINT8 addYTag =FALSE;
  257. UINT8 dropAck =FALSE;
  258. UINT16 firstBdLength = 0;
  259. UINT32 firstBddataOffset = 0;
  260. UINT32 secondBddataOffset = 0;
  261. UINT8 activeIndex = 0xff;
  262. UINT32 segmentSize = 0;
  263. *discardPacket = FALSE;
  264. pIpHeader = NULL;
  265. if (ackEmul->ackEmulationActive == FALSE)
  266. return OK;
  267. firstBdLength = memMgr_BufLength(pMsdu->firstBDPtr);
  268. firstBddataOffset = memMgr_BufOffset(pMsdu->firstBDPtr) ;
  269. pDot11Header = (UINT8 *)memMgr_BufData(pMsdu->firstBDPtr)+firstBddataOffset;
  270. if (firstBdLength == WLAN_HDR_LEN + WLAN_SNAP_HDR_LEN)
  271. {
  272. /* Packet from Ethernet, the IP heder is in the second data buffer */
  273. if(pMsdu->firstBDPtr->nextBDPtr != NULL)
  274. {
  275. secondBddataOffset = memMgr_BufOffset(pMsdu->firstBDPtr->nextBDPtr);
  276. pIpHeader = (UINT8 *)memMgr_BufData(pMsdu->firstBDPtr->nextBDPtr)+ secondBddataOffset;
  277. }
  278. }
  279. else
  280. {
  281. /* Packet from Wlan */
  282. pIpHeader = pDot11Header + WLAN_HDR_LEN + WLAN_SNAP_HDR_LEN;
  283. }
  284. pWlanSnapHeader = pDot11Header + WLAN_HDR_LEN;
  285. /* Find the packet type and length */
  286. wdrv_ackEmulationPktType(ackEmul, pWlanSnapHeader,pIpHeader ,&packetInclude,&tcpDataSize);
  287. switch (packetInclude)
  288. {
  289. case TCP_ACK_ONLY:
  290. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  291. ("TX packet = TCP_ACK_ONLY....\n"));
  292. wdrv_aeWTargetDbFindAckSession(ackEmul->pAckEmulDB, pIpHeader ,&sessionIndex, &monitorState);
  293. switch (monitorState)
  294. {
  295. case AE_INACTIVE:
  296. break;
  297. case AE_STANDBY:
  298. wdrv_ackEmulationAckStandbyState(ackEmul, sessionIndex, pIpHeader);
  299. break;
  300. case AE_CANDIDATE_ACTIVE:
  301. wdrv_ackEmulationAckCandidateActivState(ackEmul, sessionIndex,
  302. pIpHeader,
  303. &addYTag,
  304. &activeIndex,
  305. &segmentSize);
  306. if(addYTag == TRUE)
  307. {
  308. wdrv_ackEmulationAddYTag(ackEmul, pDot11Header, firstBdLength, activeIndex, segmentSize);
  309. /* update the MSDU fields */
  310. pMsdu->firstBDPtr->length += TI_SNAP_HEADER_LEN+2+TI_SNAP_AE_LEN;
  311. pMsdu->dataLen += TI_SNAP_HEADER_LEN+2+TI_SNAP_AE_LEN;
  312. }
  313. break;
  314. case AE_ACTIVE:
  315. /* Comper Template and drop packet */
  316. wdrv_ackEmulationAckActivState(ackEmul, sessionIndex, pIpHeader,&dropAck);
  317. *discardPacket = dropAck;
  318. break;
  319. case AE_TERMINATE:
  320. wdrv_ackEmulationAckTerminateState(ackEmul, sessionIndex);
  321. break;
  322. default:
  323. break;
  324. }
  325. break;
  326. case TCP_DATA:
  327. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  328. ("TX packet = TCP_DATA....\n"));
  329. break;
  330. case OTHER:
  331. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  332. ("TX packet = OTHER....\n"));
  333. default:
  334. break;
  335. }
  336. return OK;
  337. }
  338. /**********************************************************************************
  339. * wdrv_ackEmulationPktType()
  340. **********************************************************************************
  341. * DESCRIPTION: Find the packet type and length.
  342. *
  343. * INPUTS: pWlanSnapHeader - Pointer to the 802.11 SNAP header buffer.
  344. * pIpHeader - Pointer to the ip header header buffer.
  345. *
  346. * OUTPUT: packetInclude - The packet type, TCP_DATA, TCP_ACK_ONLY or OTHER
  347. * tcpDataSize - The packet size (only for tcp packet)
  348. *
  349. * RETURNS: None
  350. **********************************************************************************/
  351. static void wdrv_ackEmulationPktType(ackEmul_t* ackEmul, UINT8 *pWlanSnapHeader ,UINT8 *pIpHeader ,
  352. packetInclude_T *packetInclude, UINT16 *tcpDataSize)
  353. {
  354. UINT16 pktTotalLen;
  355. UINT8 ipHeaderLen, tcpHeaderLen;
  356. *tcpDataSize =0;
  357. /* Check if the packet is TCP/IP */
  358. if ((wlan_ntohs(((Wlan_LlcHeader_T*)pWlanSnapHeader)->Type) == IP_PROTOCOL_NUMBER) &&
  359. (*(unsigned char*) ((ULONG)pIpHeader+(ULONG)IP_PROTOCOL_FIELD)== TCP_PROTOCOL))
  360. {
  361. /* Check if the packet include data or Ack only */
  362. pktTotalLen = wlan_ntohs((*(UINT16*)(pIpHeader + IP_TOTAL_LEN_FIELD)));
  363. ipHeaderLen = ((*(unsigned char*)pIpHeader & 0x0f) * 4);
  364. tcpHeaderLen = ((((*(unsigned char*)(pIpHeader + ipHeaderLen+TCP_OFFSET_FIELD))& 0xf0)>>4) * 4);
  365. *tcpDataSize = pktTotalLen - (ipHeaderLen + tcpHeaderLen);
  366. if(*tcpDataSize > 0)
  367. *packetInclude = TCP_DATA;
  368. else
  369. *packetInclude = TCP_ACK_ONLY;
  370. }
  371. else
  372. {
  373. *packetInclude = OTHER;
  374. }
  375. }
  376. /**********************************************************************************
  377. * wdrv_ackEmulationDataStandbyState()
  378. **********************************************************************************
  379. * DESCRIPTION: This function handle the tcp date packet for session in
  380. * standby state.
  381. *
  382. * INPUTS: sessionIndex - the session index
  383. * *pIpHeader - Pointer to the ip header header buffer.
  384. *
  385. * OUTPUT: None.
  386. *
  387. * RETURNS: None
  388. **********************************************************************************/
  389. static void wdrv_ackEmulationDataStandbyState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader)
  390. {
  391. UINT8 ipHeaderLen = 0;
  392. UINT32 prevSequenceNumber =0;
  393. UINT32 currentSequenceNumber =0;
  394. UINT32 prevSegmentSize = 0;
  395. UINT32 currentSegmentSize =0;
  396. UINT8 equalSegmentSizeCounter =0;
  397. /* Calculate Current Sequence Number */
  398. ipHeaderLen = ((*(unsigned char*)pIpHeader & 0x0f) * 4);
  399. currentSequenceNumber = wlan_ntohl(*(unsigned long*)(pIpHeader+ipHeaderLen+TCP_SEQUENCE_NUMBER_FIELD));
  400. wdrv_aeWTargetDbGetSessionSequenceNumber(ackEmul->pAckEmulDB, sessionIndex,&prevSequenceNumber);
  401. /* Calclate Segment Size */
  402. wdrv_aeWTargetDbGetSessionSegmentSize(ackEmul->pAckEmulDB, sessionIndex,&prevSegmentSize);
  403. currentSegmentSize = currentSequenceNumber - prevSequenceNumber;
  404. if (prevSegmentSize == currentSegmentSize)
  405. {
  406. /* Increase Equal Segment Size Counter */
  407. wdrv_aeWTargetDbGetIncrSessionEqualSegmentSizeCounter(ackEmul->pAckEmulDB, sessionIndex,&equalSegmentSizeCounter);
  408. if(equalSegmentSizeCounter == 2 && currentSegmentSize > MIN_LOCK_SEGMENT_SIZE)
  409. {
  410. /* Monitor state -> AE_CANDIDATE_ACTIVE */
  411. /* printf("\n Session %d chabge state to AE_CANDIDATE_ACTIVE with segment size %d\n",
  412. sessionIndex,
  413. currentSegmentSize);*/
  414. wdrv_aeWTargetDbSetSessionMonitorState(ackEmul->pAckEmulDB, sessionIndex,AE_CANDIDATE_ACTIVE);
  415. }
  416. }
  417. else
  418. {
  419. wdrv_aeWTargetDbSetSessionSegmentSize(ackEmul->pAckEmulDB, sessionIndex,currentSegmentSize);
  420. wdrv_aeWTargetDbSetSessionEqualSegmentSizeCounter(ackEmul->pAckEmulDB, sessionIndex,0);
  421. }
  422. wdrv_aeWTargetDbSetSessionSequenceNumber(ackEmul->pAckEmulDB, sessionIndex,currentSequenceNumber);
  423. }
  424. /**********************************************************************************
  425. * wdrv_ackEmulationAckStandbyState()
  426. **********************************************************************************
  427. * DESCRIPTION: This function handle the tcp ack packet for session in
  428. * standby state.
  429. *
  430. * INPUTS: sessionIndex - the session index
  431. * *pIpHeader - Pointer to the ip header header buffer.
  432. *
  433. * OUTPUT: None.
  434. *
  435. * RETURNS: None
  436. **********************************************************************************/
  437. static void wdrv_ackEmulationAckStandbyState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader)
  438. {
  439. UINT8 ipHeaderLen = 0;
  440. UINT32 currentAckNumber =0;
  441. /* Calculate Current Ack Number */
  442. ipHeaderLen = ((*(unsigned char*)pIpHeader & 0x0f) * 4);
  443. currentAckNumber = wlan_ntohl(*(unsigned long*)(pIpHeader+ipHeaderLen+TCP_ACK_NUMBER_FIELD));
  444. /* Set Current Ack Number */
  445. wdrv_aeWTargetDbSetSessionAckNumber(ackEmul->pAckEmulDB, sessionIndex,currentAckNumber);
  446. }
  447. /**********************************************************************************
  448. * wdrv_ackEmulationAckCandidateActivState()
  449. **********************************************************************************
  450. * DESCRIPTION: This function handle the tcp ack packet for session in
  451. * candidate activ state.
  452. *
  453. * INPUTS: sessionIndex - the session index
  454. * *pIpHeader - Pointer to the ip header header buffer.
  455. *
  456. * OUTPUT: *addYTag - If true, add Ytag to the tcp acp packet
  457. * *activeIndex - The activeIndex that assign for this session
  458. * *segmentSize - The segment size of this tcp session.
  459. *
  460. * RETURNS: None
  461. **********************************************************************************/
  462. static void wdrv_ackEmulationAckCandidateActivState(ackEmul_t* ackEmul, UINT8 sessionIndex,
  463. UINT8 *pIpHeader,
  464. UINT8 *addYTag,
  465. UINT8 *activeIndex,
  466. UINT32 *segmentSize)
  467. {
  468. UINT8 ipHeaderLen = 0;
  469. UINT32 prevAckNumber =0;
  470. UINT32 currentAckNumber =0;
  471. UINT32 ackCounter =0;
  472. /* Calculate Current Ack Number */
  473. ipHeaderLen = ((*(unsigned char*)pIpHeader & 0x0f) * 4);
  474. currentAckNumber = wlan_ntohl(*(unsigned long*)(pIpHeader+ipHeaderLen+TCP_ACK_NUMBER_FIELD));
  475. wdrv_aeWTargetDbGetSessionSegmentSize(ackEmul->pAckEmulDB, sessionIndex,segmentSize);
  476. wdrv_aeWTargetDbGetSessionAckNumber(ackEmul->pAckEmulDB, sessionIndex,&prevAckNumber);
  477. if((currentAckNumber - prevAckNumber) == *segmentSize *2)
  478. {
  479. WLAN_REPORT_FATAL_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  480. ("Change State to active............\n"));
  481. /* Change state to Active and update Active index */
  482. if(wdrv_aeWTargetDbSetActiveState(ackEmul->pAckEmulDB, sessionIndex, activeIndex) == OK)
  483. {
  484. /* Calculate Ack Counter */
  485. ackCounter = currentAckNumber / (*segmentSize *2);
  486. wdrv_aeWTargetDbSetSessionAckCounter(ackEmul->pAckEmulDB, sessionIndex,ackCounter) ;
  487. /* Save template update Active index */
  488. wdrv_aeWTargetDbSaveAckTemplate(ackEmul->pAckEmulDB, sessionIndex,pIpHeader);
  489. /* add addYTag */
  490. WLAN_REPORT_FATAL_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  491. ("ADD Y TAG.........!!!!!!!!!!!!\n"));
  492. *addYTag = TRUE;
  493. }
  494. }
  495. wdrv_aeWTargetDbSetSessionAckNumber(ackEmul->pAckEmulDB, sessionIndex,currentAckNumber);
  496. }
  497. /**********************************************************************************
  498. * wdrv_ackEmulationAckActivState()
  499. **********************************************************************************
  500. * DESCRIPTION: This function handle the tcp ack packet for session in
  501. * active state.
  502. *
  503. * INPUTS: sessionIndex - the session index
  504. * *pIpHeader - Pointer to the ip header header buffer.
  505. *
  506. * OUTPUT: *dropAck - If TRUE discard the packet.
  507. *
  508. * RETURNS: None
  509. **********************************************************************************/
  510. static void wdrv_ackEmulationAckActivState(ackEmul_t* ackEmul, UINT8 sessionIndex, UINT8 *pIpHeader,UINT8 *dropAck)
  511. {
  512. int rc =NOK;
  513. UINT8 ipHeaderLen = 0;
  514. UINT32 currentAckNumber =0;
  515. UINT32 prevAckNumber =0;
  516. UINT32 segmentSize =0;
  517. UINT32 currentAckCounter =0;
  518. UINT32 prevAckCounter =0;
  519. UINT8 activeIndex = 0xff;
  520. UINT32 segmentNumber = 0;
  521. UINT32 prevTimeStamp;
  522. UINT32 currentTimeStamp;
  523. UINT8 newWackInfo = 0;
  524. UINT8 prevWackInfo;
  525. UINT8 prevOwnershipBit;
  526. UINT8 prevActvIndxBits;
  527. UINT8 prevAckCounterBits;
  528. currentTimeStamp =os_timeStampUs(ackEmul->hOs);
  529. wdrv_aeWTargetDbGetSessionTimeStamp(ackEmul->pAckEmulDB, sessionIndex, &prevTimeStamp);
  530. if(prevTimeStamp != 0)
  531. {
  532. if((WTARGET_ACTIVE_TIME_OUT) < (currentTimeStamp - prevTimeStamp))
  533. { /* If the delay between two ack packet for the same session grater */
  534. /* than WTARGET_ACTIVE_TIME_OUT change session state to terminate */
  535. wdrv_aeWTargetDbSetSessionMonitorState(ackEmul->pAckEmulDB, sessionIndex,AE_TERMINATE);
  536. /*WLAN_OS_REPORT(("1\n"));*/
  537. return;
  538. }
  539. }
  540. /* extract the information from prevWackInfo */
  541. whalCtrl_getSend4xWackInfo(ackEmul->hWhalCtrl, &prevWackInfo);
  542. prevAckCounterBits = (prevWackInfo&0x0f);
  543. prevActvIndxBits = (prevWackInfo&0x10)>>4;
  544. prevOwnershipBit = (prevWackInfo&0x80)>>7;
  545. /* Calculate Current Ack Number */
  546. ipHeaderLen = ((*(unsigned char*)pIpHeader & 0x0f) * 4);
  547. currentAckNumber = wlan_ntohl(*(unsigned long*)(pIpHeader+ipHeaderLen+TCP_ACK_NUMBER_FIELD));
  548. wdrv_aeWTargetDbGetSessionSegmentSize(ackEmul->pAckEmulDB, sessionIndex,&segmentSize);
  549. wdrv_aeWTargetDbGetSessionAckNumber(ackEmul->pAckEmulDB, sessionIndex,&prevAckNumber);
  550. wdrv_aeWTargetDbGetSessionAckCounter(ackEmul->pAckEmulDB, sessionIndex, &prevAckCounter) ;
  551. wdrv_aeWTargetDbGetSessionActiveIndex(ackEmul->pAckEmulDB, sessionIndex, &activeIndex);
  552. /* Calculate Ack Counter */
  553. currentAckCounter = currentAckNumber / (segmentSize*2);
  554. if((currentAckNumber - prevAckNumber) == segmentSize *2)
  555. {
  556. /*WLAN_OS_REPORT(("--2\n"));*/
  557. if ((currentAckCounter > prevAckCounter) && (currentAckCounter < prevAckCounter + 5))
  558. {
  559. /*WLAN_OS_REPORT(("----3\n"));*/
  560. rc = wdrv_aeWTargetDbCmpAckTemplate(ackEmul->pAckEmulDB, sessionIndex, pIpHeader);
  561. if (rc == OK)
  562. {
  563. /* drop this Ack */
  564. UINT8 Xtag;
  565. wdrv_aeDbGetXTagStatus(ackEmul->pAckEmulDB, sessionIndex,&Xtag);
  566. /*WLAN_OS_REPORT(("------4 Xtag=%d prevOwnershipBit=%d activeIndex=%d prevActvIndxBits=%d\n",Xtag,prevOwnershipBit,activeIndex,prevActvIndxBits));*/
  567. if (((prevOwnershipBit == 1)|| (activeIndex == prevActvIndxBits)) && Xtag)
  568. {
  569. *dropAck = TRUE;
  570. }
  571. }
  572. }
  573. }
  574. else
  575. {
  576. /*WLAN_OS_REPORT(("------99 prevAckNumber=%d,currentAckCounter=%d currentAckNumber=%d segmentSize=%d \n",*/
  577. /* prevAckNumber, currentAckCounter, currentAckNumber, segmentSize));*/
  578. }
  579. WLAN_REPORT_FATAL_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  580. ("dropAck = %d\n",*dropAck));
  581. if(*dropAck == TRUE)
  582. {
  583. newWackInfo = (((currentAckCounter % K_FACTOR)+1)&0xf); /* Add currentAckCounter MOD K_FACTOR to bit 0-3 */
  584. newWackInfo = newWackInfo | (activeIndex << 4); /* Add activeIndex to bit 4 */
  585. whalCtrl_setSend4xWackInfo(ackEmul->hWhalCtrl, newWackInfo);
  586. wdrv_aeWTargetDbSetSessionTimeStamp(ackEmul->pAckEmulDB, sessionIndex, currentTimeStamp);
  587. }
  588. else
  589. {
  590. if((prevAckNumber % (segmentSize*2))>(currentAckNumber % (segmentSize*2)))
  591. {
  592. /* Ack Reorder Problem */
  593. newWackInfo = 0xF;
  594. }
  595. else
  596. {
  597. if(prevAckCounterBits == 0xF)
  598. {
  599. /* chack if this wack info send */
  600. if(prevOwnershipBit == 1)
  601. newWackInfo = 0;
  602. }
  603. else
  604. {
  605. newWackInfo = 0;
  606. }
  607. }
  608. newWackInfo = newWackInfo | (activeIndex << 4); /* Add activeIndex to bit 4 */
  609. whalCtrl_setSend4xWackInfo(ackEmul->hWhalCtrl, newWackInfo);
  610. wdrv_aeWTargetDbSetSessionAckCounter(ackEmul->pAckEmulDB, sessionIndex,currentAckCounter) ;
  611. }
  612. wdrv_aeWTargetDbSetSessionAckNumber(ackEmul->pAckEmulDB, sessionIndex,currentAckNumber);
  613. segmentNumber = wlan_ntohl(*(unsigned long*)(pIpHeader+ipHeaderLen+TCP_SEQUENCE_NUMBER_FIELD));
  614. wdrv_aeWTargetDbUpdateAckTemplate(ackEmul->pAckEmulDB, sessionIndex,segmentNumber);
  615. }
  616. /**********************************************************************************
  617. * wdrv_ackEmulationAckTerminateState()
  618. **********************************************************************************
  619. * DESCRIPTION: This function handle the tcp ack packet for session in
  620. * terminate state.
  621. *
  622. * INPUTS: sessionIndex -
  623. *
  624. * OUTPUT: None
  625. *
  626. * RETURNS: None
  627. **********************************************************************************/
  628. static void wdrv_ackEmulationAckTerminateState(ackEmul_t* ackEmul, UINT8 sessionIndex)
  629. {
  630. UINT32 prevTimeStamp;
  631. UINT32 currentTimeStamp = os_timeStampUs(ackEmul->hOs);
  632. wdrv_aeWTargetDbGetSessionTimeStamp(ackEmul->pAckEmulDB, sessionIndex, &prevTimeStamp);
  633. if(prevTimeStamp != 0)
  634. {
  635. if((WTARGET_TERMINATE_TIME_OUT) < (currentTimeStamp - prevTimeStamp))
  636. {
  637. /* Reset Session */
  638. wdrv_aeWTargetDbResetTuple(ackEmul->pAckEmulDB, sessionIndex);
  639. }
  640. }
  641. return;
  642. }
  643. /**********************************************************************************
  644. * wdrv_ackEmulationAddYTag()
  645. **********************************************************************************
  646. * DESCRIPTION: Add Ytag to the Tcp Ack PAcket
  647. *
  648. * INPUTS: *pDot11Header - Pointer to the 802.11 heder
  649. * firstBdLength - The length of the first BD
  650. * activeIndex - The active index of the monitor session.
  651. * segmentSize - The segmentSize of the monitor session.
  652. *
  653. * OUTPUT: None
  654. *
  655. * RETURNS: None
  656. **********************************************************************************/
  657. /* Tcp Ack without Ytag */
  658. /* -------------------------------------------
  659. | 802.11 | SSAP | IP | TCP | Payload |
  660. | header | | header | header | |
  661. ------------------------------------------- */
  662. /* Tcp Ack with Ytag */
  663. /* ---------------------------------------------------------
  664. | 802.11 | TI | 802.11 SNAP | IP | TCP | Payload |
  665. | header | SNAP | header | header | header | |
  666. --------------------------------------------------------- */
  667. /* TI Snap */
  668. /* -------------------------------------------------------------------------
  669. | dsap | SSAP | Control | OUI | Type | AE | AE |Active |Segment |
  670. | 0xAA | 0xAA | 0x00 | 0x080028 | 0x60D0 | Type | Len | Index | Size |
  671. ------------------------------------------------------------------------- */
  672. static void wdrv_ackEmulationAddYTag(ackEmul_t* ackEmul, UINT8 *pDot11Header, UINT16 firstBdLength,
  673. UINT8 activeIndex, UINT32 segmentSize)
  674. {
  675. UINT8 *tempPtr;
  676. UINT32 moveLen;
  677. tempPtr = pDot11Header + WLAN_HDR_LEN;
  678. moveLen = firstBdLength - WLAN_HDR_LEN;
  679. os_memoryMove(NULL, tempPtr+TI_SNAP_HEADER_LEN+2+TI_SNAP_AE_LEN ,tempPtr,moveLen);
  680. os_memoryCopy(NULL, tempPtr,tiSnapHeader,TI_SNAP_HEADER_LEN);
  681. tempPtr += TI_SNAP_HEADER_LEN;
  682. *(UINT8*)tempPtr = TI_SNAP_AE_TYPE;
  683. tempPtr ++;
  684. *(UINT8*)tempPtr = TI_SNAP_AE_LEN; /* Length */
  685. tempPtr ++;
  686. *(UINT8*)tempPtr = activeIndex; /* Active Index */
  687. tempPtr ++;
  688. *(UINT16*)tempPtr = wlan_ntohs((UINT16)segmentSize); /* Segment Size */
  689. }
  690. /**********************************************************************************
  691. * wdrv_aeChackSnapWithYtag()
  692. **********************************************************************************
  693. * DESCRIPTION: Check if the packet include Ytag
  694. *
  695. * INPUTS: *pSnapHeader - Pointer to the SNAP heder
  696. *
  697. * OUTPUT: *tiSnapLen - The length of the first BD
  698. * *activeIndex - The active index.
  699. * *segmentSize - The segmentSize.
  700. *
  701. * RETURNS: Ok if include Ytag, otherwise NOK
  702. **********************************************************************************/
  703. static int wdrv_aeChackSnapWithYtag(ackEmul_t* ackEmul, UINT8 *pSnapHeader, UINT8 *tiSnapLen,
  704. UINT8 *activeIndex, UINT16 *segmentSize)
  705. {
  706. /* Chack if SNAP with Y TAG */
  707. if ((os_memoryCompare(ackEmul->hOs, pSnapHeader,tiSnapHeader,TI_SNAP_HEADER_LEN)== 0)&&
  708. (*(UINT8*)(pSnapHeader + TI_SNAP_HEADER_LEN) == TI_SNAP_AE_TYPE))
  709. {
  710. /* This packet include Ack with Y TAG */
  711. UINT8* tempPtr;
  712. UINT8 templen;
  713. tempPtr = pSnapHeader + TI_SNAP_HEADER_LEN+1;
  714. templen = *(UINT8*)tempPtr;
  715. *tiSnapLen = TI_SNAP_HEADER_LEN + 2 + templen;
  716. tempPtr ++;
  717. *activeIndex = (UINT8)(wlan_ntohs(*(UINT16*)tempPtr));
  718. tempPtr +=2;
  719. *segmentSize = (UINT16)(wlan_ntohl(*(UINT32*)tempPtr));
  720. return OK;
  721. }
  722. else
  723. {
  724. return NOK;
  725. }
  726. }
  727. int genera = 0;
  728. int modulo_off = 0;
  729. int mod_off = 0;
  730. int mod_on = 0;
  731. /**********************************************************************************
  732. * wdrv_aeWackReceive()
  733. **********************************************************************************
  734. * DESCRIPTION: Parse the wack info and generate emulated tcp ack
  735. *
  736. * INPUTS: station - The wack source station index.
  737. * wackInfo - The wackInfo
  738. *
  739. * OUTPUT: None
  740. *
  741. * RETURNS: None
  742. **********************************************************************************/
  743. void wdrv_aeWackReceive(ackEmul_t* ackEmul, UINT16 station, UINT8 wackInfo)
  744. {
  745. UINT8 ackCounterlowBits;
  746. UINT8 activeIndex;
  747. UINT32 oldAckNumber;
  748. UINT32 newAckNumber;
  749. UINT32 oldAckCounter;
  750. UINT32 newAckCounter;
  751. UINT32 segmentSize;
  752. UINT32 prevWackTimeStamp;
  753. UINT32 currentWackTimeStamp;
  754. UINT32 reorderProblemStatus;
  755. static UINT8 prev_wackInfo = 0xff;
  756. if(prev_wackInfo != wackInfo)
  757. {
  758. prev_wackInfo = wackInfo;
  759. /* extract the information from wackInfo */
  760. ackCounterlowBits = (wackInfo & 0xf);
  761. activeIndex = (wackInfo & 0x10) >> 4;
  762. if (ackCounterlowBits == 0)
  763. ackCounterlowBits = 0xF;
  764. else
  765. ackCounterlowBits --;
  766. if(ackCounterlowBits == 0xF)
  767. return;
  768. if(ackCounterlowBits == 0xE)
  769. {
  770. /* Reorder problem is possible */
  771. wdrv_aeWSourceDbSetSessionAckReorderProblem(ackEmul->pAckEmulDB, station,activeIndex,REORDER_PROBLEM_ON);
  772. return;
  773. }
  774. wdrv_aeWSourceDbGetSessionTimeStamp(ackEmul->pAckEmulDB, station,activeIndex,&prevWackTimeStamp);
  775. if(prevWackTimeStamp != 0)
  776. {
  777. currentWackTimeStamp = os_timeStampUs(ackEmul->hOs);
  778. if((WSOURCE_SESSION_TIME_OUT) < (currentWackTimeStamp - prevWackTimeStamp))
  779. {
  780. /* reset Wsource session */
  781. /*WLAN_OS_REPORT((" Reset Wsource session activeIndex %\n",activeIndex));*/
  782. wdrv_aeWSourceDbResetSession(ackEmul->pAckEmulDB, station, activeIndex);
  783. return;
  784. }
  785. wdrv_aeWSourceDbSetSessionTimeStamp(ackEmul->pAckEmulDB, station,activeIndex,currentWackTimeStamp);
  786. wdrv_aeWSourceDbGetSessionSegmentSize(ackEmul->pAckEmulDB, station,activeIndex,&segmentSize);
  787. if(segmentSize != 0)
  788. {
  789. wdrv_aeWSourceDbGetSessionAckNumber(ackEmul->pAckEmulDB, station,activeIndex,&oldAckNumber);
  790. wdrv_aeWSourceDbGetSessionAckCounter(ackEmul->pAckEmulDB, station,activeIndex,&oldAckCounter);
  791. /* newACK_counter = (Low_counter - (oldACK_counter mod 2^k) + 2^k + 3) mod 2^k - 3 + oldACK_counter*/
  792. newAckCounter = ((ackCounterlowBits - (oldAckCounter % K_FACTOR) + K_FACTOR + 3) % K_FACTOR) -3 + oldAckCounter;
  793. if(newAckCounter <= oldAckCounter)
  794. return;
  795. wdrv_aeWSourceDbGetSessionAckReorderProblem(ackEmul->pAckEmulDB, station,activeIndex,&reorderProblemStatus);
  796. if(reorderProblemStatus == REORDER_PROBLEM_ON)
  797. {
  798. newAckNumber = (newAckCounter * (segmentSize*2));
  799. }
  800. else
  801. {
  802. /* newACK_number = oldACK_number mod (Segment_Size*2) + Rx_Ack_count * (Segment_Size*2)*/
  803. newAckNumber = (oldAckNumber % (segmentSize*2)) + (newAckCounter * (segmentSize*2));
  804. }
  805. /* Generate ack */
  806. genera++;
  807. wdrv_aeGenerateAck(ackEmul, station,activeIndex,newAckNumber);
  808. wdrv_aeWSourceDbSetSessionAckNumber(ackEmul->pAckEmulDB, station,activeIndex,newAckNumber);
  809. wdrv_aeWSourceDbSetSessionAckCounter(ackEmul->pAckEmulDB, station,activeIndex,newAckCounter);
  810. }
  811. return;
  812. }
  813. }
  814. }
  815. /**********************************************************************************
  816. * wdrv_aeGenerateAck()
  817. **********************************************************************************
  818. * DESCRIPTION: Generate emulated TCP Ack
  819. *
  820. * INPUTS: sessionIndex -
  821. * activeIndex
  822. * ackNumber
  823. *
  824. * OUTPUT: None
  825. *
  826. * RETURNS: None
  827. **********************************************************************************/
  828. static void wdrv_aeGenerateAck(ackEmul_t* ackEmul, UINT16 stationIndex, UINT8 activeIndex ,UINT32 ackNumber)
  829. {
  830. mem_MSDU_T *pMsdu;
  831. UINT8 ipHeaderLen;
  832. UINT8 tcpHeaderLen;
  833. UINT8 *pTeplate;
  834. UINT8 *pNewPkt;
  835. UINT16 newPktLen;
  836. UINT8 *ipSource, *ipDest;
  837. UINT8 *pIpHeader, *pTcpHeader;
  838. UINT16 ipChecksum =0;
  839. UINT16 tcpChecksum =0;
  840. dot11_header_t *pDot11Header;
  841. UINT8 *pDAddr,*pSAddr;
  842. WLAN_REPORT_ERROR(ackEmul->hReport, ACK_EMUL_MODULE_LOG,
  843. ("wdrv_aeGenerateAck....==============================================\n"));
  844. wdrv_aeWSourceDbGetAckTemplate(ackEmul->pAckEmulDB, stationIndex, activeIndex, &pTeplate,&ipHeaderLen, &tcpHeaderLen);
  845. if(ipHeaderLen > 0)
  846. {
  847. newPktLen = ipHeaderLen+tcpHeaderLen;
  848. if(wlan_memMngrAllocMSDU(ackEmul->hMemMngr, &pMsdu,newPktLen+OFFSET_802_3_HDR,(allocatingModule_e)(ACK_EMUL_MODULE+ sizeof(DbTescriptor)))==NOK)
  849. {
  850. WLAN_OS_REPORT(( "WDRV_4X: GenerateAck - fail to allocate buildMsduPtr\n"));
  851. return;
  852. }
  853. pNewPkt = (UINT8*)memMgr_BufData(pMsdu->firstBDPtr)+ sizeof(DbTescriptor);
  854. os_memoryCopy(ackEmul->hOs, pNewPkt + OFFSET_802_3_HDR -2,pTeplate + WLAN_HDR_LEN+WLAN_SNAP_HDR_LEN -2,newPktLen+2);
  855. /* Extract Info from frame header */
  856. pDot11Header = (dot11_header_t *)pTeplate;
  857. pDAddr = (UINT8 *)&pDot11Header->address1;
  858. pSAddr = (UINT8 *)((pDot11Header->fc & DOT11_FC_FROM_DS)? &pDot11Header->address3 : &pDot11Header->address2);
  859. pMsdu->firstBDPtr->dataOffset = sizeof(DbTescriptor);
  860. pMsdu->firstBDPtr->length = newPktLen;
  861. pMsdu->dataLen = newPktLen+OFFSET_802_3_HDR;
  862. /* Calclate IP Checksum */
  863. pIpHeader = pNewPkt+OFFSET_802_3_HDR;
  864. ipChecksum = wdrv_IpChecksumCalc(ackEmul, ipHeaderLen,pIpHeader);
  865. /* Calclate TCP Checksum */
  866. pTcpHeader = pIpHeader + ipHeaderLen;
  867. *(UINT32*)(pTcpHeader+TCP_ACK_NUMBER_FIELD) = wlan_ntohl(ackNumber);
  868. ipSource = pIpHeader+IP_SRC_ADDRESS_FIELD;
  869. ipDest = pIpHeader+IP_DEST_ADDRESS_FIELD;
  870. tcpChecksum = wdrv_TcpChecksumCalc(ackEmul, tcpHeaderLen, ipSource, ipDest, pTcpHeader);
  871. /* Add the Checksum to the new packet */
  872. *(UINT16*)(pIpHeader+IP_CHECKSUM_FIELD) = wlan_ntohs(ipChecksum);
  873. *(UINT16*)(pTcpHeader+TCP_CHECKSUM_FIELD) = wlan_ntohs(tcpChecksum);
  874. /* Generate 802.3 Header */
  875. os_memoryCopy (ackEmul->hOs, pNewPkt, pDAddr, MAC_ADDR_LEN);
  876. os_memoryCopy (ackEmul->hOs, pNewPkt+MAC_ADDR_LEN, pSAddr, MAC_ADDR_LEN);
  877. /* Send the emulated ack to the bss Bridge*/
  878. os_receivePacket(ackEmul->hOs, pMsdu, (UINT16)pMsdu->dataLen);
  879. }
  880. }
  881. /****************************************************************************
  882. * wdrv_aeSetActive()
  883. ****************************************************************************
  884. * DESCRIPTION: Enable/ Desable Ack Emulation
  885. *
  886. * INPUTS:
  887. *
  888. * OUTPUT: None
  889. *
  890. * RETURNS: OK or NOK
  891. ****************************************************************************/
  892. void wdrv_aeSetActive(ackEmul_t* ackEmul, int status)
  893. {
  894. /* if (status == TRUE)
  895. {
  896. (void)whal_apiSetSend4xWackInfo(ackEmul->hWhalCtrl, 0);
  897. (void)whal_apiEnable4xWackFeature(ackEmul->hWhalCtrl);
  898. }
  899. if (status == FALSE)
  900. {
  901. (void)whal_apiSetSend4xWackInfo(ackEmul->hWhalCtrl, 0);
  902. (void)whal_apiDisable4xWackFeature(ackEmul->hWhalCtrl);
  903. }
  904. */
  905. ackEmul->ackEmulationActive = status;
  906. }
  907. int wdrv_aeGetActive(ackEmul_t* ackEmul )
  908. {
  909. return(ackEmul->ackEmulationActive);
  910. }
  911. /*
  912. **************************************************************************
  913. Function: wdrv_IpChecksumCalc
  914. Description: Calculate the 16 bit IP Checksum.
  915. ***************************************************************************
  916. */
  917. static UINT16 wdrv_IpChecksumCalc(ackEmul_t* ackEmul, UINT16 len_ip_header, UINT8 *buff)
  918. {
  919. UINT16 word16;
  920. UINT32 sum=0;
  921. UINT16 i;
  922. /* make 16 bit words out of every two adjacent 8 bit words in the packet*/
  923. /* and add them up*/
  924. for (i=0;i<len_ip_header;i=i+2){
  925. word16 = wlan_ntohs(*(UINT16*)(buff+i));
  926. sum = sum + (UINT32) word16;
  927. }
  928. /* take only 16 bits out of the 32 bit sum*/
  929. /*temp = (sum & 0xffff0000)>>16;*/
  930. sum = (sum & 0x0000ffff)+((sum & 0xffff0000)>>16);
  931. /* one's complement the result*/
  932. sum = ~sum;
  933. return ((UINT16) sum);
  934. }
  935. /*
  936. **************************************************************************
  937. Function: wdrv_TcpChecksumCalc
  938. Description: Calculate the 16 bit TCP Checksum.
  939. ***************************************************************************
  940. */
  941. static UINT16 wdrv_TcpChecksumCalc(ackEmul_t* ackEmul, UINT16 len_tcp_header,UINT8 *IpSource, UINT8 *IpDest ,UINT8 *buff)
  942. {
  943. UINT16 word16;
  944. UINT32 sum=0;
  945. UINT16 i;
  946. /* add a padding byte = 0 at the end of packet */
  947. buff[len_tcp_header]=0;
  948. /* make 16 bit words out of every two adjacent 8 bit words in the packet
  949. and add them up */
  950. for (i=0;i<len_tcp_header;i=i+2){
  951. word16 = wlan_ntohs(*(UINT16*)(buff+i));
  952. sum = sum + (UINT32) word16;
  953. }
  954. /* add the TCP pseudo header which contains:
  955. the IP source and destinationn addresses, TCP protocol & TCP length */
  956. word16 = wlan_ntohs(*(UINT16*)IpSource);
  957. sum = sum + (UINT32) word16;
  958. word16 = wlan_ntohs(*(UINT16*)(IpSource+2));
  959. sum = sum + (UINT32) word16;
  960. word16 = wlan_ntohs(*(UINT16*)IpDest);
  961. sum = sum + (UINT32) word16;
  962. word16 = wlan_ntohs(*(UINT16*)(IpDest+2));
  963. sum = sum + (UINT32) word16;
  964. sum = sum + (UINT32)len_tcp_header + 0x06;
  965. /* take only 16 bits out of the 32 bit sum */
  966. sum = (sum & 0x0000ffff)+((sum & 0xffff0000)>>16);
  967. /* one's complement the result */
  968. sum = ~sum;
  969. return ((UINT16) sum);
  970. }