mirror of
https://github.com/YikeStone/MT7601u.git
synced 2025-08-02 19:04:09 +05:30
448 lines
11 KiB
C
448 lines
11 KiB
C
/*
|
|
***************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 4F, No. 2 Technology 5th Rd.
|
|
* Science-based Industrial Park
|
|
* Hsin-chu, Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* All rights reserved. Ralink's source code is an unpublished work and the
|
|
* use of a copyright notice does not imply otherwise. This source code
|
|
* contains confidential trade secret material of Ralink Tech. Any attemp
|
|
* or participation in deciphering, decoding, reverse engineering or in any
|
|
* way altering the source code is stricitly prohibited, unless the prior
|
|
* written consent of Ralink Technology, Inc. is obtained.
|
|
***************************************************************************
|
|
|
|
Module Name:
|
|
cmm_mat.c
|
|
|
|
Abstract:
|
|
Support Mac Address Translation function.
|
|
|
|
Note:
|
|
MAC Address Translation(MAT) engine subroutines, we should just take care
|
|
packet to bridge.
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------------- ---------- ----------------------------------------------
|
|
Shiang 02-26-2007 Init version
|
|
*/
|
|
|
|
#ifdef MAT_SUPPORT
|
|
|
|
#include "rt_config.h"
|
|
|
|
|
|
extern MATProtoOps MATProtoIPHandle;
|
|
extern MATProtoOps MATProtoARPHandle;
|
|
extern MATProtoOps MATProtoPPPoEDisHandle;
|
|
extern MATProtoOps MATProtoPPPoESesHandle;
|
|
extern MATProtoOps MATProtoIPv6Handle;
|
|
|
|
extern UCHAR SNAP_802_1H[];
|
|
extern UCHAR SNAP_BRIDGE_TUNNEL[];
|
|
|
|
#define MAX_MAT_NODE_ENTRY_NUM 128 /* We support maximum 128 node entry for our system */
|
|
#define MAT_NODE_ENTRY_SIZE 40 /*28 // bytes //change to 40 for IPv6Mac Table */
|
|
|
|
typedef struct _MATNodeEntry
|
|
{
|
|
UCHAR data[MAT_NODE_ENTRY_SIZE];
|
|
struct _MATNodeEntry *next;
|
|
}MATNodeEntry, *PMATNodeEntry;
|
|
|
|
|
|
#ifdef KMALLOC_BATCH
|
|
/*static MATNodeEntry *MATNodeEntryPoll = NULL; */
|
|
#endif
|
|
|
|
static MATProtoTable MATProtoTb[]=
|
|
{
|
|
{ETH_P_IP, &MATProtoIPHandle}, /* IP handler */
|
|
{ETH_P_ARP, &MATProtoARPHandle}, /* ARP handler */
|
|
{ETH_P_PPP_DISC, &MATProtoPPPoEDisHandle}, /* PPPoE discovery stage handler */
|
|
{ETH_P_PPP_SES, &MATProtoPPPoESesHandle}, /* PPPoE session stage handler */
|
|
{ETH_P_IPV6, &MATProtoIPv6Handle}, /* IPv6 handler */
|
|
};
|
|
|
|
#define MAX_MAT_SUPPORT_PROTO_NUM (sizeof(MATProtoTb)/sizeof(MATProtoTable))
|
|
|
|
|
|
/* --------------------------------- Public Function-------------------------------- */
|
|
NDIS_STATUS MATDBEntryFree(
|
|
IN MAT_STRUCT *pMatStruct,
|
|
IN PUCHAR NodeEntry)
|
|
{
|
|
#ifdef KMALLOC_BATCH
|
|
MATNodeEntry *pPtr, *pMATNodeEntryPoll;
|
|
|
|
pMATNodeEntryPoll = (MATNodeEntry *)pAd->MatCfg.MATNodeEntryPoll;
|
|
pPtr = (MATNodeEntry *)NodeEntry;
|
|
NdisZeroMemory(pPtr, sizeof(MATNodeEntry));
|
|
if (pMATNodeEntryPoll->next)
|
|
{
|
|
pPtr->next = pMATNodeEntryPoll->next;
|
|
pMATNodeEntryPoll->next = pPtr;
|
|
} else {
|
|
pMATNodeEntryPoll->next = pPtr;
|
|
}
|
|
#else
|
|
os_free_mem(NULL, NodeEntry);
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
PUCHAR MATDBEntryAlloc(IN MAT_STRUCT *pMatStruct, IN UINT32 size)
|
|
{
|
|
#ifdef KMALLOC_BATCH
|
|
MATNodeEntry *pPtr = NULL, *pMATNodeEntryPoll;
|
|
pMATNodeEntryPoll = (MATNodeEntry *)pMatStruct->pMATNodeEntryPoll;
|
|
|
|
if (pMATNodeEntryPoll->next)
|
|
{
|
|
pPtr = pMATNodeEntryPoll->next;
|
|
pMATNodeEntryPoll->next = pPtr->next;
|
|
}
|
|
|
|
#else
|
|
UCHAR *pPtr = NULL;
|
|
|
|
os_alloc_mem(NULL, (PUCHAR *)&pPtr, size);
|
|
/*pPtr = kmalloc(size, MEM_ALLOC_FLAG); */
|
|
|
|
#endif
|
|
|
|
return (PUCHAR)pPtr;
|
|
}
|
|
|
|
|
|
VOID dumpPkt(PUCHAR pHeader, int len)
|
|
{
|
|
int i;
|
|
PSTRING tmp;
|
|
|
|
tmp = (PSTRING)pHeader;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("--StartDump\n"));
|
|
for(i=0;i<len; i++)
|
|
{
|
|
if ( (i%16==0) && (i!=0))
|
|
DBGPRINT(RT_DEBUG_OFF, ("\n"));
|
|
DBGPRINT(RT_DEBUG_OFF, ("%02x ", tmp[i]& 0xff));
|
|
}
|
|
DBGPRINT(RT_DEBUG_OFF, ("\n--EndDump\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
For each out-going packet, check the upper layer protocol type if need
|
|
to handled by our APCLI convert engine. If yes, call corresponding handler
|
|
to handle it.
|
|
|
|
Arguments:
|
|
pAd =>Pointer to our adapter
|
|
pPkt =>pointer to the 802.11 header of outgoing packet
|
|
ifIdx =>Interface Index want to dispatch to.
|
|
|
|
Return Value:
|
|
Success =>
|
|
TRUE
|
|
Mapped mac address if found, else return specific default mac address
|
|
depends on the upper layer protocol type.
|
|
Error =>
|
|
FALSE.
|
|
|
|
Note:
|
|
1.the pPktHdr must be a 802.3 packet.
|
|
2.Maybe we need a TxD arguments?
|
|
3.We check every packet here including group mac address becasue we need to
|
|
handle DHCP packet.
|
|
========================================================================
|
|
*/
|
|
PUCHAR MATEngineTxHandle(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPkt,
|
|
IN UINT ifIdx,
|
|
IN UCHAR OpMode)
|
|
{
|
|
PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL;
|
|
UINT16 protoType, protoType_ori;
|
|
INT i;
|
|
struct _MATProtoOps *pHandle = NULL;
|
|
PUCHAR retSkb = NULL;
|
|
BOOLEAN bVLANPkt = FALSE;
|
|
|
|
|
|
if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
|
|
return NULL;
|
|
|
|
pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
|
|
if (!pPktHdr)
|
|
return NULL;
|
|
|
|
protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12));
|
|
|
|
/* Get the upper layer protocol type of this 802.3 pkt. */
|
|
protoType = OS_NTOHS(protoType_ori);
|
|
|
|
/* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */
|
|
if (protoType == 0x8100)
|
|
{
|
|
protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4));
|
|
protoType = OS_NTOHS(protoType_ori);
|
|
bVLANPkt = TRUE;
|
|
}
|
|
|
|
|
|
/* For differnet protocol, dispatch to specific handler */
|
|
for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
|
|
{
|
|
if (protoType == MATProtoTb[i].protocol)
|
|
{
|
|
pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
|
|
pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN);
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
#ifdef APCLI_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].CurrentAddress[0];
|
|
#endif /* APCLI_SUPPORT */
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
if (pHandle->tx!=NULL)
|
|
retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr);
|
|
|
|
return retSkb;
|
|
}
|
|
}
|
|
return retSkb;
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
Routine Description:
|
|
Depends on the Received packet, check the upper layer protocol type
|
|
and search for specific mapping table to find out the real destination
|
|
MAC address.
|
|
|
|
Arguments:
|
|
pAd =>Pointer to our adapter
|
|
pPkt =>pointer to the 802.11 header of receviced packet
|
|
infIdx =>Interface Index want to dispatch to.
|
|
|
|
Return Value:
|
|
Success =>
|
|
Mapped mac address if found, else return specific default mac address
|
|
depends on the upper layer protocol type.
|
|
Error =>
|
|
NULL
|
|
|
|
Note:
|
|
========================================================================
|
|
*/
|
|
PUCHAR MATEngineRxHandle(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPkt,
|
|
IN UINT infIdx)
|
|
{
|
|
PUCHAR pMacAddr = NULL;
|
|
PUCHAR pLayerHdr = NULL, pPktHdr = NULL;
|
|
UINT16 protoType;
|
|
INT i =0;
|
|
struct _MATProtoOps *pHandle = NULL;
|
|
|
|
|
|
if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
|
|
return NULL;
|
|
|
|
pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
|
|
if (!pPktHdr)
|
|
return NULL;
|
|
|
|
/* If it's a multicast/broadcast packet, we do nothing. */
|
|
if (IS_GROUP_MAC(pPktHdr))
|
|
return NULL;
|
|
|
|
/* Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler */
|
|
protoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + 12)));
|
|
|
|
for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
|
|
{
|
|
if (protoType == MATProtoTb[i].protocol)
|
|
{
|
|
pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
|
|
pLayerHdr = (pPktHdr + MAT_ETHER_HDR_LEN);
|
|
/* RTMP_SEM_LOCK(&MATDBLock); */
|
|
if(pHandle->rx!=NULL)
|
|
pMacAddr = pHandle->rx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, NULL);
|
|
/* RTMP_SEM_UNLOCK(&MATDBLock); */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pMacAddr)
|
|
NdisMoveMemory(pPktHdr, pMacAddr, MAC_ADDR_LEN);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN MATPktRxNeedConvert(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNET_DEV net_dev)
|
|
{
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
#ifdef APCLI_SUPPORT
|
|
int i = 0;
|
|
|
|
/* Check if the packet will be send to apcli interface. */
|
|
while(i<MAX_APCLI_NUM)
|
|
{
|
|
/*BSSID match the ApCliBssid ?(from a valid AP) */
|
|
if ((pAd->ApCfg.ApCliTab[i].Valid == TRUE)
|
|
&& (net_dev == pAd->ApCfg.ApCliTab[i].dev))
|
|
return TRUE;
|
|
i++;
|
|
}
|
|
#endif /* APCLI_SUPPORT */
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS MATEngineExit(
|
|
IN RTMP_ADAPTER *pAd)
|
|
{
|
|
struct _MATProtoOps *pHandle = NULL;
|
|
int i;
|
|
|
|
if(pAd->MatCfg.status == MAT_ENGINE_STAT_EXITED)
|
|
return TRUE;
|
|
|
|
/* For each registered protocol, we call it's exit handler. */
|
|
for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
|
|
{
|
|
pHandle = MATProtoTb[i].pHandle;
|
|
if (pHandle->exit!=NULL)
|
|
pHandle->exit(&pAd->MatCfg);
|
|
}
|
|
|
|
#ifdef KMALLOC_BATCH
|
|
/* Free the memory used to store node entries. */
|
|
if (pAd->MatCfg.pMATNodeEntryPoll)
|
|
{
|
|
os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
|
|
pAd->MatCfg.pMATNodeEntryPoll = NULL;
|
|
}
|
|
#endif
|
|
|
|
pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS MATEngineInit(
|
|
IN RTMP_ADAPTER *pAd)
|
|
{
|
|
MATProtoOps *pHandle = NULL;
|
|
int i, status;
|
|
|
|
if(pAd->MatCfg.status == MAT_ENGINE_STAT_INITED)
|
|
return TRUE;
|
|
|
|
#ifdef KMALLOC_BATCH
|
|
/* Allocate memory for node entry, we totally allocate 128 entries and link them together. */
|
|
/* pAd->MatCfg.pMATNodeEntryPoll = kmalloc(sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM, GFP_KERNEL); */
|
|
os_alloc_mem_suspend(NULL, (UCHAR **)&(pAd->MatCfg.pMATNodeEntryPoll), sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
|
|
if (pAd->MatCfg.pMATNodeEntryPoll != NULL)
|
|
{
|
|
MATNodeEntry *pPtr=NULL;
|
|
|
|
NdisZeroMemory(pAd->MatCfg.pMATNodeEntryPoll, sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
|
|
pPtr = pAd->MatCfg.pMATNodeEntryPoll;
|
|
for (i = 0; i < (MAX_MAT_NODE_ENTRY_NUM -1); i++)
|
|
{
|
|
pPtr->next = (MATNodeEntry *)(pPtr+1);
|
|
pPtr = pPtr->next;
|
|
}
|
|
pPtr->next = NULL;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/* For each specific protocol, call it's init function. */
|
|
for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
|
|
{
|
|
pHandle = MATProtoTb[i].pHandle;
|
|
ASSERT(pHandle);
|
|
if (pHandle->init != NULL)
|
|
{
|
|
status = pHandle->init(&pAd->MatCfg);
|
|
if (status == FALSE)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("MATEngine Init Protocol (0x%x) failed, Stop the MAT Funciton initialization failed!\n", MATProtoTb[i].protocol));
|
|
goto init_failed;
|
|
}
|
|
DBGPRINT(RT_DEBUG_TRACE, ("MATEngine Init Protocol (0x%04x) success!\n", MATProtoTb[i].protocol));
|
|
}
|
|
}
|
|
|
|
NdisAllocateSpinLock(pAd, &pAd->MatCfg.MATDBLock);
|
|
pAd->MatCfg.pPriv = (VOID *)pAd;
|
|
pAd->MatCfg.status = MAT_ENGINE_STAT_INITED;
|
|
|
|
return TRUE;
|
|
|
|
init_failed:
|
|
/* For each specific protocol, call it's exit function. */
|
|
for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
|
|
{
|
|
if ((pHandle = MATProtoTb[i].pHandle) != NULL)
|
|
{
|
|
if (pHandle->exit != NULL)
|
|
{
|
|
status = pHandle->exit(&pAd->MatCfg);
|
|
if (status == FALSE)
|
|
goto init_failed;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef KMALLOC_BATCH
|
|
if (pAd->MatCfg.pMATNodeEntryPoll)
|
|
os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
|
|
pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
|
|
#endif /* KMALLOC_BATCH */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif /* MAT_SUPPORT */
|
|
|