blob: 0a41bbe24e6c27ad269912bad5abea5e89cdb9d5 [file] [log] [blame]
Forest Bond92b96792009-06-13 07:38:31 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: wctl.c
20 *
21 * Purpose: handle WMAC duplicate filter & defragment
22 *
23 * Author: Jerry Chen
24 *
25 * Date: Jun. 27, 2002
26 *
27 * Functions:
28 * WCTLbIsDuplicate - Test if duplicate packet
29 * WCTLuSearchDFCB - Search DeFragment Control Database
30 * WCTLuInsertDFCB - Insert DeFragment Control Database
31 * WCTLbHandleFragment - Handle received fragment packet
32 *
33 * Revision History:
34 *
35 */
36
Forest Bond92b96792009-06-13 07:38:31 -040037#include "wctl.h"
Forest Bond92b96792009-06-13 07:38:31 -040038#include "device.h"
Forest Bond92b96792009-06-13 07:38:31 -040039#include "card.h"
Forest Bond92b96792009-06-13 07:38:31 -040040#include "tmacro.h"
Forest Bond92b96792009-06-13 07:38:31 -040041
42/*--------------------- Static Definitions -------------------------*/
43
44/*--------------------- Static Classes ----------------------------*/
45
46/*--------------------- Static Variables --------------------------*/
47// static int msglevel =MSG_LEVEL_INFO;
48/*--------------------- Static Functions --------------------------*/
49
50/*--------------------- Export Variables --------------------------*/
51
52
53
54/*
55 * Description:
56 * Scan Rx cache. Return TRUE if packet is duplicate, else
57 * inserts in receive cache and returns FALSE.
58 *
59 * Parameters:
60 * In:
61 * pCache - Receive packets history
62 * pMACHeader - 802.11 MAC Header of received packet
63 * Out:
64 * none
65 *
66 * Return Value: TRUE if packet duplicate; otherwise FALSE
67 *
68 */
69
70BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
71{
Andres Morecc856e62010-05-17 21:34:01 -030072 unsigned int uIndex;
73 unsigned int ii;
Forest Bond92b96792009-06-13 07:38:31 -040074 PSCacheEntry pCacheEntry;
75
76 if (IS_FC_RETRY(pMACHeader)) {
77
78 uIndex = pCache->uInPtr;
79 for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
80 pCacheEntry = &(pCache->asCacheEntry[uIndex]);
81 if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
82 (IS_ETH_ADDRESS_EQUAL (&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) &&
83 (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->wFrameCtl))
84 ) {
85 /* Duplicate match */
86 return TRUE;
87 }
88 ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
89 }
90 }
91 /* Not fount in cache - insert */
92 pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
93 pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
Andres More9a0e7562010-04-13 21:54:48 -030094 memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -040095 pCacheEntry->wFrameCtl = pMACHeader->wFrameCtl;
96 ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
97 return FALSE;
98}
99
100/*
101 * Description:
102 * Found if sequence number of received fragment packet in Defragment Database
103 *
104 * Parameters:
105 * In:
106 * pDevice - Pointer to adapter
107 * pMACHeader - 802.11 MAC Header of received packet
108 * Out:
109 * none
110 *
111 * Return Value: index number in Defragment Database
112 *
113 */
Andres More33d33e422010-05-19 23:50:00 -0300114
Andres Morecc856e62010-05-17 21:34:01 -0300115unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
Forest Bond92b96792009-06-13 07:38:31 -0400116{
Andres Morecc856e62010-05-17 21:34:01 -0300117 unsigned int ii;
Forest Bond92b96792009-06-13 07:38:31 -0400118
Andres More33d33e422010-05-19 23:50:00 -0300119 for (ii = 0; ii < pDevice->cbDFCB; ii++) {
120 if ((pDevice->sRxDFCB[ii].bInUse == TRUE) &&
121 (IS_ETH_ADDRESS_EQUAL(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
122 &(pMACHeader->abyAddr2[0])))) {
123 return ii;
124 }
125 }
126 return pDevice->cbDFCB;
Forest Bond92b96792009-06-13 07:38:31 -0400127}
128
Forest Bond92b96792009-06-13 07:38:31 -0400129/*
130 * Description:
131 * Insert received fragment packet in Defragment Database
132 *
133 * Parameters:
134 * In:
135 * pDevice - Pointer to adapter
136 * pMACHeader - 802.11 MAC Header of received packet
137 * Out:
138 * none
139 *
140 * Return Value: index number in Defragment Database
141 *
142 */
Andres Morecc856e62010-05-17 21:34:01 -0300143unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
Forest Bond92b96792009-06-13 07:38:31 -0400144{
Andres Morecc856e62010-05-17 21:34:01 -0300145 unsigned int ii;
Forest Bond92b96792009-06-13 07:38:31 -0400146
147 if (pDevice->cbFreeDFCB == 0)
148 return(pDevice->cbDFCB);
Andres More33d33e422010-05-19 23:50:00 -0300149 for (ii = 0; ii < pDevice->cbDFCB; ii++) {
Forest Bond92b96792009-06-13 07:38:31 -0400150 if (pDevice->sRxDFCB[ii].bInUse == FALSE) {
151 pDevice->cbFreeDFCB--;
152 pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
153 pDevice->sRxDFCB[ii].bInUse = TRUE;
154 pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
155 pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
Andres More9a0e7562010-04-13 21:54:48 -0300156 memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
157 &(pMACHeader->abyAddr2[0]),
158 ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -0400159 return(ii);
160 }
161 }
162 return(pDevice->cbDFCB);
163}
164
165
166/*
167 * Description:
168 * Handle received fragment packet
169 *
170 * Parameters:
171 * In:
172 * pDevice - Pointer to adapter
173 * pMACHeader - 802.11 MAC Header of received packet
174 * cbFrameLength - Frame length
175 * bWEP - is WEP packet
176 * Out:
177 * none
178 *
179 * Return Value: TRUE if it is valid fragment packet and we have resource to defragment; otherwise FALSE
180 *
181 */
Andres Morecc856e62010-05-17 21:34:01 -0300182BOOL WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader,
183 unsigned int cbFrameLength, BOOL bWEP, BOOL bExtIV)
Forest Bond92b96792009-06-13 07:38:31 -0400184{
Andres Morecc856e62010-05-17 21:34:01 -0300185unsigned int uHeaderSize;
Forest Bond92b96792009-06-13 07:38:31 -0400186
187
188 if (bWEP == TRUE) {
189 uHeaderSize = 28;
190 if (bExtIV)
191 // ExtIV
192 uHeaderSize +=4;
193 }
194 else {
195 uHeaderSize = 24;
196 }
197
198 if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
199 pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
200 if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
201 // duplicate, we must flush previous DCB
202 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
203 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
204 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
205 }
206 else {
207 pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
208 if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
209 return(FALSE);
210 }
211 }
212 // reserve 8 byte to match MAC RX Buffer
213 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 8);
214// pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
215 memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
216 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
217 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
218 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
219 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
220 return(FALSE);
221 }
222 else {
223 pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
224 if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
225 if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
226 (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
227 ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
228
229 memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
230 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
231 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
232 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
233 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
234 }
235 else {
236 // seq error or frag # error flush DFCB
237 pDevice->cbFreeDFCB++;
238 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
239 return(FALSE);
240 }
241 }
242 else {
243 return(FALSE);
244 }
245 if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
246 //enq defragcontrolblock
247 pDevice->cbFreeDFCB++;
248 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
249 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
250 return(TRUE);
251 }
252 return(FALSE);
253 }
254}
255
256