rtmp_apcli.c

来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 408 行

C
408
字号
/*
 ***************************************************************************
 * Ralink Tech Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2006, 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:
	rtmp_apcli.c

	Abstract:
	apcli convert engine subroutines, we should just take care data packet.

	Revision History:
	Who			When			What
	--------	----------		----------------------------------------------
	Shiang      June/16/06  	init version for RT2561/2661
*/

#ifdef APCLI_SUPPORT

#include "rtmp_apcli.h"

typedef struct _UWRProtoTable
{
	UINT16 					protoCode;
	struct _UWRProtoEntry	*pHandle;	
}UWRProtoTable, PUWRProtoTable;

extern UWRProtoEntry apCliIPHandler;
extern UWRProtoEntry apCliARPHandler;
extern UWRProtoEntry apCliPPPoEDisHandler;
extern UWRProtoEntry apCliPPPoESesHandler;

extern UCHAR SNAP_802_1H[];
extern UCHAR SNAP_BRIDGE_TUNNEL[];

static UWRProtoTable UWRProtoTb[]=
{
	{ETH_P_IP, 		&apCliIPHandler},		// IP handler
	{ETH_P_ARP, 		&apCliARPHandler},		// ARP handler
	{ETH_P_PPP_DISC,	&apCliPPPoEDisHandler}, // PPPoE discovery stage handler
	{ETH_P_PPP_SES,		&apCliPPPoESesHandler},	// PPPoE session stage handler
//	{0x0,    			NULL},					
};

#define MAX_SUPPORT_PROTOCOL_NUM (sizeof(UWRProtoTb)/sizeof(UWRProtoTable))

#define APCLI_NODE_ENTRY_SIZE	28	// bytes
#define APCLI_NODE_ENTRY_NUM	127	// We support maxima 127 node entry for our system
typedef struct _UWRNodeEntry
{
	UCHAR data[APCLI_NODE_ENTRY_SIZE];
	struct _UWRNodeEntry *next;
}UWRNodeEntry, *PUWRNodeEntry;

static int UWREngineInited = 0;
static int UWREngineExited = 1;
spinlock_t apcli_db_lock;

#ifdef KMALLOC_BATCH
static UWRNodeEntry *UWRNodeEntryPoll = NULL;

NDIS_STATUS UWRNodeEntryFree(PUCHAR NodeEntry)
{
	UWRNodeEntry *pPtr;

	pPtr = (UWRNodeEntry *)NodeEntry;
	memset(pPtr, 0, sizeof(UWRNodeEntry));
	if (UWRNodeEntryPoll->next)
	{
		pPtr->next = UWRNodeEntryPoll->next;
		UWRNodeEntryPoll->next = pPtr;
	} else {
		UWRNodeEntryPoll->next = pPtr;
	}

	return TRUE;
}

PUCHAR UWRNodeEntryAlloc(VOID)
{
	struct _UWRNodeEntry *pPtr = NULL;
	
	if (UWRNodeEntryPoll->next)
	{
		pPtr = UWRNodeEntryPoll->next;
		UWRNodeEntryPoll->next = pPtr->next;
	}
	
	return (PUCHAR)pPtr;
}

#endif

VOID dumpPkt(PUCHAR pHeader, int len)
{
	int i;
	char *tmp;

	tmp = pHeader;

	printk("--StartDump\n");
	for(i=0;i<len; i++)
	{
		if ( (i%16==0) && (i!=0))
			printk("\n");
		printk("%02x ", tmp[i]& 0xff);
	}
	printk("\n--EndDump\n");

	return;
}

PUCHAR get80211UpperLayerProto(
	IN PUCHAR 			pHeader,
	IN PRXD_STRUC		pRxD)
{
	USHORT	DataSize, Msdu2Size;
	HEADER_802_11 		*p80211Hdr;
	PUCHAR				pProto=NULL;
	
	if (!pHeader)
		return NULL;

	pProto = (UCHAR *)pHeader;
	p80211Hdr = (PHEADER_802_11)pHeader;

	// If it's a WDS acket, shift the addr4
	if ((p80211Hdr->FC.FrDs == 1) && (p80211Hdr->FC.ToDs == 1))
    {
    	pProto += LENGTH_802_11_WITH_ADDR4;
		DataSize = (USHORT)pRxD->DataByteCnt - LENGTH_802_11_WITH_ADDR4;
	}
    else
    {
    	pProto += LENGTH_802_11;
		DataSize = (USHORT)pRxD->DataByteCnt - LENGTH_802_11;
    }

	// If it's a QoS packet, shift more 2 bytes
	if (p80211Hdr->FC.SubType & 0x08)
    {
        pProto += 2;
		DataSize -= 2;
    }

	//Check for Ralink specific aggregate packet
	if (p80211Hdr->FC.Order)
    {
		Msdu2Size = *pProto + (*(pProto+1) << 8);
        if ((Msdu2Size <= 1536) && (Msdu2Size < DataSize))
        {
			pProto += 2;
        }
	}

	// Handle 802.1h or bridge tunnel data
	if (NdisEqualMemory(SNAP_802_1H, pProto, 6) ||
	    NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pProto, 6))
	{
		pProto += 6;
	}

	return pProto;

}


/*
	========================================================================
	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
		pHeader =>pointer to the 802.11 header of outgoing packet 

	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 UWRMacUpdaterForTxPkt(
	IN PRTMP_ADAPTER	pAd,
	IN struct sk_buff	*pSkb,
	IN PTXD_STRUC		pTxD)
{
	PUCHAR 		pLayerHdr = NULL, pPktHdr = NULL;
	UINT16		protoType;
	INT			i;
	struct _UWRProtoEntry 	*pHandle = NULL;
	PUCHAR  retSkb = NULL;
#ifndef THREAD_ISR
	ULONG	IrqFlags;
#endif

	pPktHdr = pSkb->data;
	if (!pPktHdr)
		return NULL;
	
	// Get the upper layer protocol type of this 802.3 pkt.
	protoType = ntohs(*((UINT16 *)(pPktHdr + 12)));
	//DBGPRINT(RT_DEBUG_TRACE,"%s(): protoType=0x%04x\n", __FUNCTION__, protoType);
	// For differnet protocol, dispatch to specific handler
	for (i=0; i<MAX_SUPPORT_PROTOCOL_NUM; i++)
	{
		if (protoType == UWRProtoTb[i].protoCode)
		{
			pHandle = UWRProtoTb[i].pHandle;	// the pHandle must not be null!
			pLayerHdr = (pPktHdr + APCLI_ETHER_HDR_LEN);
#ifndef THREAD_ISR
			RTMP_SEM_LOCK(&apcli_db_lock, IrqFlags);
#endif
			if (pHandle->tx!=NULL)
				retSkb = pHandle->tx(pAd, pSkb, pLayerHdr);
#ifndef THREAD_ISR
			RTMP_SEM_UNLOCK(&apcli_db_lock, IrqFlags);
#endif
			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
		pHeader =>pointer to the 802.11 header of receviced packet 
		pRxD	=>pointer to the RxDesc of the receviced packet.

	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 UWRMacConverterForRxPkt(
	IN PRTMP_ADAPTER	 pAd,
	IN struct sk_buff	 *pSkb,
	IN struct net_device *net_dev)
{
	PUCHAR				pMacAddr = NULL;
	PUCHAR 		pLayerHdr = NULL, pPktHdr = NULL;
	UINT16		protoType;
	INT			i =0;
	struct _UWRProtoEntry 	*pHandle = NULL;
	ULONG  IrqFlags;

	pPktHdr = pSkb->data;
	if (!pPktHdr)
		return NULL;

	// If it's a multicast/broadcast packet, we do nothing.
	if (APCLI_MAC_ADDR_IS_GROUP(pPktHdr))
		return NULL;

	// Check if the packet will be send to apcli interface.
	while(i<MAX_APCLI_ENTRY)
	{
		//BSSID match the ApCliBssid ?(from a valid AP)
		if ((pAd->ApCliTab.ApCliEntry[i].Valid == TRUE) && 
			(net_dev == pAd->ApCliTab.ApCliEntry[i].dev))
			break;
		i++;
	}

	if(i == MAX_APCLI_ENTRY)
		return NULL;

	// Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler
	protoType = ntohs(*((UINT16 *)(pPktHdr + 12)));
	DBGPRINT(RT_DEBUG_INFO, "%s(): protoType=0x%04x\n", __FUNCTION__, protoType);
	for (i=0; i<MAX_SUPPORT_PROTOCOL_NUM; i++)
	{
		if (protoType == UWRProtoTb[i].protoCode)
		{
			pHandle = UWRProtoTb[i].pHandle;	// the pHandle must not be null!
			pLayerHdr = (pPktHdr + APCLI_ETHER_HDR_LEN);
			RTMP_SEM_LOCK(&apcli_db_lock, IrqFlags);
			if(pHandle->rx!=NULL)
				pMacAddr = pHandle->rx(pAd, pSkb, pLayerHdr);
			RTMP_SEM_UNLOCK(&apcli_db_lock, IrqFlags);
			break;
		}
	}

	if (pMacAddr)
		memcpy(pPktHdr, pMacAddr, MAC_ADDR_LEN);

	return NULL;

}


NDIS_STATUS APCLIConvertEngineExit(VOID)
{
	struct _UWRProtoEntry 	*pHandle = NULL;
	int i;

	if(UWREngineExited)
		return TRUE;
	
	// For each registered protocol, we call it's exit handler.
	for (i=0; i<MAX_SUPPORT_PROTOCOL_NUM; i++)
	{
		if (UWRProtoTb[i].pHandle != NULL)
		{
			pHandle = UWRProtoTb[i].pHandle;
			if (pHandle->exit!=NULL)
				pHandle->exit();
		}
	}

#ifdef KMALLOC_BATCH
	// Free the memory used to store node entries.
	if (UWRNodeEntryPoll) 
		kfree(UWRNodeEntryPoll);
#endif

	UWREngineExited = 1;
	
	return TRUE;
	
}


NDIS_STATUS APCLIConvertEngineInit(VOID)
{
	struct _UWRProtoEntry 	*pHandle = NULL;
	int i;

	if(UWREngineInited)
		return TRUE;
	
#ifdef KMALLOC_BATCH
	// Allocate memory for node entry, we totally allocate 127 entries and link list them together.
	UWRNodeEntryPoll = (UWRNodeEntry *)kmalloc(sizeof(UWRNodeEntry) * APCLI_NODE_ENTRY_NUM, MEM_ALLOC_FLAG);
	if (UWRNodeEntryPoll)
	{
		struct _UWRNodeEntry    *pPtr=NULL;

		memset(UWRNodeEntryPoll, 0, sizeof(UWRNodeEntry) * APCLI_NODE_ENTRY_NUM);
		pPtr = UWRNodeEntryPoll;
		for (i=0; i<(APCLI_NODE_ENTRY_NUM -1); i++)
		{
			pPtr->next = (struct _UWRNodeEntry *)(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_SUPPORT_PROTOCOL_NUM; i++)
	{
		if (UWRProtoTb[i].pHandle != NULL)
		{
			pHandle = UWRProtoTb[i].pHandle;
			if (pHandle->init!=NULL)
				pHandle->init();
		}
	}

	RTMP_SEM_INIT(&apcli_db_lock);

	UWREngineInited = 1;
	return TRUE;
}

#endif  //Endif of "APCLI_SUPPORT"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?