Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wctl.c
Go to the documentation of this file.
1 /*
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 
37 #include "wctl.h"
38 #include "device.h"
39 #include "card.h"
40 #include "tmacro.h"
41 
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 
71 {
72  unsigned int uIndex;
73  unsigned int ii;
74  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  (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]),
83  &(pMACHeader->abyAddr2[0]))) &&
84  (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->wFrameCtl))
85  ) {
86  /* Duplicate match */
87  return TRUE;
88  }
89  ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
90  }
91  }
92  /* Not found in cache - insert */
93  pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
94  pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
95  memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
96  pCacheEntry->wFrameCtl = pMACHeader->wFrameCtl;
98  return FALSE;
99 }
100 
101 /*
102  * Description:
103  * Found if sequence number of received fragment packet in Defragment Database
104  *
105  * Parameters:
106  * In:
107  * pDevice - Pointer to adapter
108  * pMACHeader - 802.11 MAC Header of received packet
109  * Out:
110  * none
111  *
112  * Return Value: index number in Defragment Database
113  *
114  */
115 
116 unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
117 {
118  unsigned int ii;
119 
120  for (ii = 0; ii < pDevice->cbDFCB; ii++) {
121  if ((pDevice->sRxDFCB[ii].bInUse == TRUE) &&
122  (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
123  &(pMACHeader->abyAddr2[0])))) {
124  return ii;
125  }
126  }
127  return pDevice->cbDFCB;
128 }
129 
130 /*
131  * Description:
132  * Insert received fragment packet in Defragment Database
133  *
134  * Parameters:
135  * In:
136  * pDevice - Pointer to adapter
137  * pMACHeader - 802.11 MAC Header of received packet
138  * Out:
139  * none
140  *
141  * Return Value: index number in Defragment Database
142  *
143  */
144 unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
145 {
146  unsigned int ii;
147 
148  if (pDevice->cbFreeDFCB == 0)
149  return(pDevice->cbDFCB);
150  for (ii = 0; ii < pDevice->cbDFCB; ii++) {
151  if (pDevice->sRxDFCB[ii].bInUse == FALSE) {
152  pDevice->cbFreeDFCB--;
153  pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
154  pDevice->sRxDFCB[ii].bInUse = TRUE;
155  pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
156  pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
157  memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
158  &(pMACHeader->abyAddr2[0]),
159  ETH_ALEN);
160  return(ii);
161  }
162  }
163  return(pDevice->cbDFCB);
164 }
165 
166 
167 /*
168  * Description:
169  * Handle received fragment packet
170  *
171  * Parameters:
172  * In:
173  * pDevice - Pointer to adapter
174  * pMACHeader - 802.11 MAC Header of received packet
175  * cbFrameLength - Frame length
176  * bWEP - is WEP packet
177  * Out:
178  * none
179  *
180  * Return Value: TRUE if it is valid fragment packet and we have resource to defragment; otherwise FALSE
181  *
182  */
184  unsigned int cbFrameLength, BOOL bWEP, BOOL bExtIV)
185 {
186 unsigned int uHeaderSize;
187 
188 
189  if (bWEP == TRUE) {
190  uHeaderSize = 28;
191  if (bExtIV)
192  // ExtIV
193  uHeaderSize +=4;
194  }
195  else {
196  uHeaderSize = 24;
197  }
198 
199  if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
200  pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
201  if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
202  // duplicate, we must flush previous DCB
203  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
204  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
205  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
206  }
207  else {
208  pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
209  if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
210  return(FALSE);
211  }
212  }
213  // reserve 8 byte to match MAC RX Buffer
214  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 8);
215 // pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
216  memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
217  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
218  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
219  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
220  //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
221  return(FALSE);
222  }
223  else {
224  pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
225  if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
226  if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
227  (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
228  ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
229 
230  memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
231  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
232  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
233  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
234  //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
235  }
236  else {
237  // seq error or frag # error flush DFCB
238  pDevice->cbFreeDFCB++;
239  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
240  return(FALSE);
241  }
242  }
243  else {
244  return(FALSE);
245  }
246  if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
247  //enq defragcontrolblock
248  pDevice->cbFreeDFCB++;
249  pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
250  //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
251  return(TRUE);
252  }
253  return(FALSE);
254  }
255 }
256 
257