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 41/*--------------------- Static Definitions -------------------------*/ 42 43/*--------------------- Static Classes ----------------------------*/ 44 45/*--------------------- Static Variables --------------------------*/ 46// static int msglevel =MSG_LEVEL_INFO; 47/*--------------------- Static Functions --------------------------*/ 48 49/*--------------------- Export Variables --------------------------*/ 50 51 52 53/* 54 * Description: 55 * Scan Rx cache. Return true if packet is duplicate, else 56 * inserts in receive cache and returns false. 57 * 58 * Parameters: 59 * In: 60 * pCache - Receive packets history 61 * pMACHeader - 802.11 MAC Header of received packet 62 * Out: 63 * none 64 * 65 * Return Value: true if packet duplicate; otherwise false 66 * 67 */ 68 69bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) 70{ 71 unsigned int uIndex; 72 unsigned int ii; 73 PSCacheEntry pCacheEntry; 74 75 if (IS_FC_RETRY(pMACHeader)) { 76 77 uIndex = pCache->uInPtr; 78 for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) { 79 pCacheEntry = &(pCache->asCacheEntry[uIndex]); 80 if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) && 81 (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) 82 ) { 83 /* Duplicate match */ 84 return true; 85 } 86 ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH); 87 } 88 } 89 /* Not fount in cache - insert */ 90 pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr]; 91 pCacheEntry->wFmSequence = pMACHeader->wSeqCtl; 92 memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN); 93 ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH); 94 return false; 95} 96 97/* 98 * Description: 99 * Found if sequence number of received fragment packet in Defragment Database 100 * 101 * Parameters: 102 * In: 103 * pDevice - Pointer to adapter 104 * pMACHeader - 802.11 MAC Header of received packet 105 * Out: 106 * none 107 * 108 * Return Value: index number in Defragment Database 109 * 110 */ 111unsigned int WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader) 112{ 113unsigned int ii; 114 115 for(ii=0;ii<pDevice->cbDFCB;ii++) { 116 if ((pDevice->sRxDFCB[ii].bInUse == true) && 117 (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) 118 ) { 119 // 120 return(ii); 121 } 122 } 123 return(pDevice->cbDFCB); 124} 125 126 127/* 128 * Description: 129 * Insert received fragment packet in Defragment Database 130 * 131 * Parameters: 132 * In: 133 * pDevice - Pointer to adapter 134 * pMACHeader - 802.11 MAC Header of received packet 135 * Out: 136 * none 137 * 138 * Return Value: index number in Defragment Database 139 * 140 */ 141unsigned int WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader) 142{ 143unsigned int ii; 144 145 if (pDevice->cbFreeDFCB == 0) 146 return(pDevice->cbDFCB); 147 for(ii=0;ii<pDevice->cbDFCB;ii++) { 148 if (pDevice->sRxDFCB[ii].bInUse == false) { 149 pDevice->cbFreeDFCB--; 150 pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime; 151 pDevice->sRxDFCB[ii].bInUse = true; 152 pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4); 153 pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F); 154 memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN); 155 return(ii); 156 } 157 } 158 return(pDevice->cbDFCB); 159} 160 161 162/* 163 * Description: 164 * Handle received fragment packet 165 * 166 * Parameters: 167 * In: 168 * pDevice - Pointer to adapter 169 * pMACHeader - 802.11 MAC Header of received packet 170 * cbFrameLength - Frame length 171 * bWEP - is WEP packet 172 * Out: 173 * none 174 * 175 * Return Value: true if it is valid fragment packet and we have resource to defragment; otherwise false 176 * 177 */ 178bool WCTLbHandleFragment (PSDevice pDevice, PS802_11Header pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV) 179{ 180unsigned int uHeaderSize; 181 182 183 if (bWEP == true) { 184 uHeaderSize = 28; 185 if (bExtIV) 186 // ExtIV 187 uHeaderSize +=4; 188 } 189 else { 190 uHeaderSize = 24; 191 } 192 193 if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) { 194 pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader); 195 if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) { 196 // duplicate, we must flush previous DCB 197 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime; 198 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4); 199 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F); 200 } 201 else { 202 pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader); 203 if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) { 204 return(false); 205 } 206 } 207 // reserve 4 byte to match MAC RX Buffer 208 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (unsigned char *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4); 209 memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength); 210 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength; 211 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength; 212 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; 213 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); 214 return(false); 215 } 216 else { 217 pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader); 218 if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) { 219 if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) && 220 (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) && 221 ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) { 222 223 memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((unsigned char *) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize)); 224 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize); 225 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize); 226 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; 227 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); 228 } 229 else { 230 // seq error or frag # error flush DFCB 231 pDevice->cbFreeDFCB++; 232 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false; 233 return(false); 234 } 235 } 236 else { 237 return(false); 238 } 239 if (IS_LAST_FRAGMENT_PKT(pMACHeader)) { 240 //enq defragcontrolblock 241 pDevice->cbFreeDFCB++; 242 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false; 243 //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); 244 return(true); 245 } 246 return(false); 247 } 248} 249 250 251