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 70BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) 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 fount 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; 97 ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH); 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 116unsigned 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 */ 144unsigned 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 */ 183BOOL WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, 184 unsigned int cbFrameLength, BOOL bWEP, BOOL bExtIV) 185{ 186unsigned 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 258