1611 lines · 49.9 KB · C
RawDownload
#include "headers.h" static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI); static UINT UpdateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule); static BOOLEAN DerefPhsRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule); static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry); static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule); static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable); static int phs_compress(S_PHS_RULE   *phs_members,unsigned char *in_buf,						unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );  static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,								unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size ); static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\						  S_PHS_RULE   *phs_rules,UINT *header_size);  static ULONG PhsCompress(void* pvContext,				  B_UINT16 uiVcid,				  B_UINT16 uiClsId,				  void *pvInputBuffer,				  void *pvOutputBuffer,				  UINT *pOldHeaderSize,				  UINT *pNewHeaderSize ); static ULONG PhsDeCompress(void* pvContext,				  B_UINT16 uiVcid,				  void *pvInputBuffer,				  void *pvOutputBuffer,				  UINT *pInHeaderSize,				  UINT *pOutHeaderSize);   #define IN#define OUT /*Function:				PHSTransmit Description:			This routine handle PHS(Payload Header Suppression for Tx path.					It extracts a fragment of the NDIS_PACKET containing the header					to be suppressed. It then suppresses the header by invoking PHS exported compress routine.					The header data after suppression is copied back to the NDIS_PACKET.  Input parameters:		IN struct bcm_mini_adapter *Adapter         - Miniport Adapter Context						IN Packet 				- NDIS packet containing data to be transmitted						IN USHORT Vcid        - vcid pertaining to connection on which the packet is being sent.Used to										        identify PHS rule to be applied.						B_UINT16 uiClassifierRuleID - Classifier Rule ID						BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF. Return:					STATUS_SUCCESS - If the send was successful.						Other  - If an error occurred.*/ int PHSTransmit(struct bcm_mini_adapter *Adapter,					 struct sk_buff	**pPacket,					 USHORT Vcid,					 B_UINT16 uiClassifierRuleID,					 BOOLEAN bHeaderSuppressionEnabled,					 UINT *PacketLen,					 UCHAR bEthCSSupport){ 	//PHS Sepcific	UINT    unPHSPktHdrBytesCopied = 0;	UINT	unPhsOldHdrSize = 0;	UINT	unPHSNewPktHeaderLen = 0;	/* Pointer to PHS IN Hdr Buffer */	PUCHAR pucPHSPktHdrInBuf =				Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;	/* Pointer to PHS OUT Hdr Buffer */	PUCHAR  pucPHSPktHdrOutBuf =					Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;	UINT       usPacketType;	UINT       BytesToRemove=0;	BOOLEAN  bPHSI = 0;	LONG ulPhsStatus = 0;	UINT 	numBytesCompressed = 0;	struct sk_buff *newPacket = NULL;	struct sk_buff *Packet = *pPacket; 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit"); 	if(!bEthCSSupport)		BytesToRemove=ETH_HLEN;	/*		Accumulate the header upto the size we support suppression		from NDIS packet	*/ 	usPacketType=((struct ethhdr *)(Packet->data))->h_proto;  	pucPHSPktHdrInBuf = Packet->data + BytesToRemove;	//considering data after ethernet header	if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)	{ 		unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);	}	else	{		unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;	} 	if( (unPHSPktHdrBytesCopied > 0 ) &&		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))	{  		// Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.	// Suppress only if IP Header and PHS Enabled For the Service Flow		if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||			(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&			(bHeaderSuppressionEnabled))		{				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);  				unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;				ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,					Vcid,					uiClassifierRuleID,					pucPHSPktHdrInBuf,					pucPHSPktHdrOutBuf,					&unPhsOldHdrSize,					&unPHSNewPktHeaderLen);				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size  %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen); 				if(unPHSNewPktHeaderLen == unPhsOldHdrSize)				{					if(  ulPhsStatus == STATUS_PHS_COMPRESSED)							bPHSI = *pucPHSPktHdrOutBuf;					ulPhsStatus = STATUS_PHS_NOCOMPRESSION;				} 				if(  ulPhsStatus == STATUS_PHS_COMPRESSED)				{					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed"); 					if(skb_cloned(Packet))					{						newPacket = skb_copy(Packet, GFP_ATOMIC); 						if(newPacket == NULL)							return STATUS_FAILURE; 						dev_kfree_skb(Packet);						*pPacket = Packet = newPacket;						pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;					} 					numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN); 					memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);					memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);					skb_pull(Packet, numBytesCompressed); 					return STATUS_SUCCESS;				} 				else				{					//if one byte headroom is not available, increase it through skb_cow					if(!(skb_headroom(Packet) > 0))					{						if(skb_cow(Packet, 1))						{							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");							return STATUS_FAILURE;						}					}					skb_push(Packet, 1); 					// CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes.  not needed .... hence corrupting it.					*(Packet->data + BytesToRemove) = bPHSI;					return STATUS_SUCCESS;			}		}		else		{			if(!bHeaderSuppressionEnabled)			{				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");			} 			return STATUS_SUCCESS;		}	} 	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");	return STATUS_SUCCESS;} int PHSReceive(struct bcm_mini_adapter *Adapter,					USHORT usVcid,					struct sk_buff *packet,					UINT *punPacketLen,					UCHAR *pucEthernetHdr,					UINT	bHeaderSuppressionEnabled){	u32   nStandardPktHdrLen            		= 0;	u32   nTotalsuppressedPktHdrBytes  = 0;	int     ulPhsStatus 		= 0;	PUCHAR pucInBuff = NULL ;	UINT TotalBytesAdded = 0;	if(!bHeaderSuppressionEnabled)	{		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");		return ulPhsStatus;	} 	pucInBuff = packet->data; 	//Restore  PHS suppressed header	nStandardPktHdrLen = packet->len;	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,		usVcid,		pucInBuff,		Adapter->ucaPHSPktRestoreBuf,		&nTotalsuppressedPktHdrBytes,		&nStandardPktHdrLen); 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",					nTotalsuppressedPktHdrBytes,nStandardPktHdrLen); 	if(ulPhsStatus != STATUS_PHS_COMPRESSED)	{		skb_pull(packet, 1);		return STATUS_SUCCESS;	}	else	{		TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN;		if(TotalBytesAdded)		{			if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))				skb_push(packet, TotalBytesAdded);			else			{				if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))				{					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");					return STATUS_FAILURE;				} 				skb_push(packet, TotalBytesAdded);			}		} 		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);	} 	return STATUS_SUCCESS;} void DumpFullPacket(UCHAR *pBuf,UINT nPktLen){	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");    BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);} //-----------------------------------------------------------------------------// Procedure:   phs_init//// Description: This routine is responsible for allocating memory for classifier and// PHS rules.//// Arguments:// pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc//// Returns:// TRUE(1)	-If allocation of memory was success full.// FALSE	-If allocation of memory fails.//-----------------------------------------------------------------------------int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension, struct bcm_mini_adapter *Adapter){	int i;	S_SERVICEFLOW_TABLE *pstServiceFlowTable;    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function "); 	if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)		return -EINVAL; 	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =		kzalloc(sizeof(S_SERVICEFLOW_TABLE), GFP_KERNEL);     if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)	{		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");		return -ENOMEM;	} 	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;	for(i=0;i<MAX_SERVICEFLOWS;i++)	{		S_SERVICEFLOW_ENTRY sServiceFlow = pstServiceFlowTable->stSFList[i];		sServiceFlow.pstClassifierTable = kzalloc(sizeof(S_CLASSIFIER_TABLE), GFP_KERNEL);		if(!sServiceFlow.pstClassifierTable)		{			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");			free_phs_serviceflow_rules(pPhsdeviceExtension->                pstServiceFlowPhsRulesTable);			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;			return -ENOMEM;		}	} 	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);     if(pPhsdeviceExtension->CompressedTxBuffer == NULL)	{		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;		return -ENOMEM;	}     pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);	if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)	{		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");		kfree(pPhsdeviceExtension->CompressedTxBuffer);		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;		return -ENOMEM;	}   	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");	return STATUS_SUCCESS;}  int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt){	if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)	{		free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);		pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;	} 	kfree(pPHSDeviceExt->CompressedTxBuffer);	pPHSDeviceExt->CompressedTxBuffer = NULL; 	kfree(pPHSDeviceExt->UnCompressedRxBuffer);	pPHSDeviceExt->UnCompressedRxBuffer = NULL; 	return 0;}   //PHS functions/*++PhsUpdateClassifierRule Routine Description:    Exported function to add or modify a PHS Rule. Arguments:	IN void* pvContext - PHS Driver Specific Context	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.	IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table. Return Value:     0 if successful,    >0 Error. --*/ULONG PhsUpdateClassifierRule(IN void* pvContext,								IN B_UINT16  uiVcid ,								IN B_UINT16  uiClsId   ,								IN S_PHS_RULE *psPhsRule,								IN B_UINT8  u8AssociatedPHSI){	ULONG lStatus =0;	UINT nSFIndex =0 ;	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);   	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n"); 	if(pDeviceExtension == NULL)	{		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");		return ERR_PHS_INVALID_DEVICE_EXETENSION;	}  	if(u8AssociatedPHSI == 0)	{		return ERR_PHS_INVALID_PHS_RULE;	} 	/* Retrieve the SFID Entry Index for requested Service Flow */ 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,	                uiVcid,&pstServiceFlowEntry);     if(nSFIndex == PHS_INVALID_TABLE_INDEX)	{		/* This is a new SF. Create a mapping entry for this */		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,		      pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);		return lStatus;	} 	/* SF already Exists Add PHS Rule to existing SF */  	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,  	          pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);     return lStatus;} /*++PhsDeletePHSRule Routine Description:   Deletes the specified phs Rule within Vcid Arguments:	IN void* pvContext - PHS Driver Specific Context	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted. Return Value:     0 if successful,    >0 Error. --*/ ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI){	ULONG lStatus =0;	UINT nSFIndex =0, nClsidIndex =0 ;	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;	S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n"); 	if(pDeviceExtension)	{ 		//Retrieve the SFID Entry Index for requested Service Flow		nSFIndex = GetServiceFlowEntry(pDeviceExtension		      ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);        if(nSFIndex == PHS_INVALID_TABLE_INDEX)		{			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");			return ERR_SF_MATCH_FAIL;		} 		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;		if(pstClassifierRulesTable)		{			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)			{				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)				{					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI)					{						if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)							pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;						if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)							kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);						memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,							sizeof(S_CLASSIFIER_ENTRY));					}				}

Lines 1–500 of 1611.