#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 supresses the header by invoking PHS exported compress routine. The header data after supression is copied back to the NDIS_PACKET. Input parameters: IN PMINI_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 occured.*/ int PHSTransmit(PMINI_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.ucaHdrSupressionInBuf; /* Pointer to PHS OUT Hdr Buffer */ PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf; 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 supression 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 Supress 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 PHSRecieve(PMINI_ADAPTER Adapter, USHORT usVcid, struct sk_buff *packet, UINT *punPacketLen, UCHAR *pucEthernetHdr, UINT bHeaderSuppressionEnabled){ u32 nStandardPktHdrLen = 0; u32 nTotalsupressedPktHdrBytes = 0; int ulPhsStatus = 0; PUCHAR pucInBuff = NULL ; UINT TotalBytesAdded = 0; if(!bHeaderSuppressionEnabled) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,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, &nTotalsupressedPktHdrBytes, &nStandardPktHdrLen); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", nTotalsupressedPktHdrBytes,nStandardPktHdrLen); if(ulPhsStatus != STATUS_PHS_COMPRESSED) { skb_pull(packet, 1); return STATUS_SUCCESS; } else { TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - 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){ PMINI_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,PMINI_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 Successfull"); 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; PMINI_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; PMINI_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. Load more
#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 supresses the header by invoking PHS exported compress routine. The header data after supression is copied back to the NDIS_PACKET. Input parameters: IN PMINI_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 occured. */ int PHSTransmit(PMINI_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.ucaHdrSupressionInBuf; /* Pointer to PHS OUT Hdr Buffer */ PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf; 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 supression 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 Supress 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 PHSRecieve(PMINI_ADAPTER Adapter, USHORT usVcid, struct sk_buff *packet, UINT *punPacketLen, UCHAR *pucEthernetHdr, UINT bHeaderSuppressionEnabled) { u32 nStandardPktHdrLen = 0; u32 nTotalsupressedPktHdrBytes = 0; int ulPhsStatus = 0; PUCHAR pucInBuff = NULL ; UINT TotalBytesAdded = 0; if(!bHeaderSuppressionEnabled) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,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, &nTotalsupressedPktHdrBytes, &nStandardPktHdrLen); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", nTotalsupressedPktHdrBytes,nStandardPktHdrLen); if(ulPhsStatus != STATUS_PHS_COMPRESSED) { skb_pull(packet, 1); return STATUS_SUCCESS; } else { TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - 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) { PMINI_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,PMINI_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 Successfull"); 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; PMINI_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; PMINI_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)); } }