1703 lines · 49.7 KB · C
RawDownload
#include "headers.h" static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,					    B_UINT16 uiClsId,					    struct bcm_phs_table *psServiceFlowTable,					    struct bcm_phs_rule *psPhsRule,					    B_UINT8 u8AssociatedPHSI); static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,					    B_UINT16  uiClsId,					    struct bcm_phs_entry *pstServiceFlowEntry,					    struct bcm_phs_rule *psPhsRule,					    B_UINT8 u8AssociatedPHSI); static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,				    struct bcm_phs_classifier_table *psaClassifiertable,				    struct bcm_phs_rule *psPhsRule,				    enum bcm_phs_classifier_context eClsContext,				    B_UINT8 u8AssociatedPHSI); static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,				    struct bcm_phs_classifier_entry *pstClassifierEntry,				    struct bcm_phs_classifier_table *psaClassifiertable,				    struct bcm_phs_rule *psPhsRule,				    B_UINT8 u8AssociatedPHSI); static bool ValidatePHSRuleComplete(const struct bcm_phs_rule *psPhsRule); static bool DerefPhsRule(B_UINT16 uiClsId,			 struct bcm_phs_classifier_table *psaClassifiertable,			 struct bcm_phs_rule *pstPhsRule); static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,			       B_UINT32 uiClsid,			       enum bcm_phs_classifier_context eClsContext,			       struct bcm_phs_classifier_entry **ppstClassifierEntry); static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,			    B_UINT32 uiPHSI,			    enum bcm_phs_classifier_context eClsContext,			    struct bcm_phs_rule **ppstPhsRule); static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable); static int phs_compress(struct bcm_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,			  struct bcm_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,		bool 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;	bool 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 successful. * FALSE	-If allocation of memory fails. */int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,	     struct bcm_mini_adapter *Adapter){	int i;	struct bcm_phs_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(struct bcm_phs_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++) {		struct bcm_phs_entry sServiceFlow =			pstServiceFlowTable->stSFList[i];		sServiceFlow.pstClassifierTable =			kzalloc(sizeof(struct bcm_phs_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 struct bcm_phs_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 struct bcm_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 struct bcm_phs_rule *psPhsRule,			      IN B_UINT8 u8AssociatedPHSI){	ULONG lStatus = 0;	UINT nSFIndex = 0;	struct bcm_phs_entry *pstServiceFlowEntry = NULL;	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);	struct bcm_phs_extension *pDeviceExtension =		(struct bcm_phs_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. */

Lines 1–500 of 1703.