| #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)); |
| } |
| } |
| } |
| } |
| |
| } |
| return lStatus; |
| } |
| |
| /*++ |
| PhsDeleteClassifierRule |
| |
| Routine Description: |
| Exported function to Delete a PHS Rule for the SFID,CLSID Pair. |
| |
| 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. |
| |
| Return Value: |
| |
| 0 if successful, |
| >0 Error. |
| |
| --*/ |
| ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 uiClsId) |
| { |
| ULONG lStatus =0; |
| UINT nSFIndex =0, nClsidIndex =0 ; |
| S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; |
| S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; |
| |
| 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; |
| } |
| |
| nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, |
| uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry); |
| if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) |
| { |
| if(pstClassifierEntry->pstPhsRule) |
| { |
| if(pstClassifierEntry->pstPhsRule->u8RefCnt) |
| pstClassifierEntry->pstPhsRule->u8RefCnt--; |
| if(0==pstClassifierEntry->pstPhsRule->u8RefCnt) |
| kfree(pstClassifierEntry->pstPhsRule); |
| |
| } |
| memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY)); |
| } |
| |
| nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, |
| uiClsId,eOldClassifierRuleContext,&pstClassifierEntry); |
| |
| if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) |
| { |
| kfree(pstClassifierEntry->pstPhsRule); |
| memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY)); |
| } |
| } |
| return lStatus; |
| } |
| |
| /*++ |
| PhsDeleteSFRules |
| |
| Routine Description: |
| Exported function to Delete a all PHS Rules for the SFID. |
| |
| Arguments: |
| IN void* pvContext - PHS Driver Specific Context |
| IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted |
| |
| Return Value: |
| |
| 0 if successful, |
| >0 Error. |
| |
| --*/ |
| ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid) |
| { |
| |
| 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].pstPhsRule) |
| { |
| if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt) |
| pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt--; |
| if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt) |
| kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule); |
| pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] |
| .pstPhsRule = NULL; |
| } |
| memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY)); |
| if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) |
| { |
| if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt) |
| pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt--; |
| if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] |
| .pstPhsRule->u8RefCnt) |
| kfree(pstClassifierRulesTable |
| ->stOldPhsRulesList[nClsidIndex].pstPhsRule); |
| pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] |
| .pstPhsRule = NULL; |
| } |
| memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY)); |
| } |
| } |
| pstServiceFlowEntry->bUsed = FALSE; |
| pstServiceFlowEntry->uiVcid = 0; |
| |
| } |
| |
| return lStatus; |
| } |
| |
| |
| /*++ |
| PhsCompress |
| |
| Routine Description: |
| Exported function to compress the data using PHS. |
| |
| Arguments: |
| IN void* pvContext - PHS Driver Specific Context. |
| IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies. |
| IN UINT uiClsId - The Classifier ID to which current packet header compression applies. |
| IN void *pvInputBuffer - The Input buffer containg packet header data |
| IN void *pvOutputBuffer - The output buffer returned by this function after PHS |
| IN UINT *pOldHeaderSize - The actual size of the header before PHS |
| IN UINT *pNewHeaderSize - The new size of the header after applying PHS |
| |
| Return Value: |
| |
| 0 if successful, |
| >0 Error. |
| |
| --*/ |
| ULONG PhsCompress(IN void* pvContext, |
| IN B_UINT16 uiVcid, |
| IN B_UINT16 uiClsId, |
| IN void *pvInputBuffer, |
| OUT void *pvOutputBuffer, |
| OUT UINT *pOldHeaderSize, |
| OUT UINT *pNewHeaderSize ) |
| { |
| UINT nSFIndex =0, nClsidIndex =0 ; |
| S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; |
| S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; |
| S_PHS_RULE *pstPhsRule = NULL; |
| ULONG lStatus =0; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| |
| |
| |
| PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; |
| |
| |
| if(pDeviceExtension == NULL) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n"); |
| lStatus = STATUS_PHS_NOCOMPRESSION ; |
| return lStatus; |
| |
| } |
| |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n"); |
| |
| |
| //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_SEND, DBG_LVL_ALL,"SFID Match Failed\n"); |
| lStatus = STATUS_PHS_NOCOMPRESSION ; |
| return lStatus; |
| } |
| |
| nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, |
| uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry); |
| |
| if(nClsidIndex == PHS_INVALID_TABLE_INDEX) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n"); |
| lStatus = STATUS_PHS_NOCOMPRESSION ; |
| return lStatus; |
| } |
| |
| |
| //get rule from SF id,Cls ID pair and proceed |
| pstPhsRule = pstClassifierEntry->pstPhsRule; |
| |
| if(!ValidatePHSRuleComplete(pstPhsRule)) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n"); |
| lStatus = STATUS_PHS_NOCOMPRESSION ; |
| return lStatus; |
| } |
| |
| //Compress Packet |
| lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer, |
| (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize); |
| |
| if(lStatus == STATUS_PHS_COMPRESSED) |
| { |
| pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1; |
| pstPhsRule->PHSModifiedNumPackets++; |
| } |
| else |
| pstPhsRule->PHSErrorNumPackets++; |
| |
| return lStatus; |
| } |
| |
| /*++ |
| PhsDeCompress |
| |
| Routine Description: |
| Exported function to restore the packet header in Rx path. |
| |
| Arguments: |
| IN void* pvContext - PHS Driver Specific Context. |
| IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies. |
| IN void *pvInputBuffer - The Input buffer containg suppressed packet header data |
| OUT void *pvOutputBuffer - The output buffer returned by this function after restoration |
| OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter. |
| |
| Return Value: |
| |
| 0 if successful, |
| >0 Error. |
| |
| --*/ |
| ULONG PhsDeCompress(IN void* pvContext, |
| IN B_UINT16 uiVcid, |
| IN void *pvInputBuffer, |
| OUT void *pvOutputBuffer, |
| OUT UINT *pInHeaderSize, |
| OUT UINT *pOutHeaderSize ) |
| { |
| UINT nSFIndex =0, nPhsRuleIndex =0 ; |
| S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; |
| S_PHS_RULE *pstPhsRule = NULL; |
| UINT phsi; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| PPHS_DEVICE_EXTENSION pDeviceExtension= |
| (PPHS_DEVICE_EXTENSION)pvContext; |
| |
| *pInHeaderSize = 0; |
| |
| if(pDeviceExtension == NULL) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n"); |
| return ERR_PHS_INVALID_DEVICE_EXETENSION; |
| } |
| |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n"); |
| |
| phsi = *((unsigned char *)(pvInputBuffer)); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi); |
| if(phsi == UNCOMPRESSED_PACKET ) |
| { |
| return STATUS_PHS_NOCOMPRESSION; |
| } |
| |
| //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_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n"); |
| return ERR_SF_MATCH_FAIL; |
| } |
| |
| nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi, |
| eActiveClassifierRuleContext,&pstPhsRule); |
| if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) |
| { |
| //Phs Rule does not exist in active rules table. Lets try in the old rules table. |
| nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, |
| phsi,eOldClassifierRuleContext,&pstPhsRule); |
| if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) |
| { |
| return ERR_PHSRULE_MATCH_FAIL; |
| } |
| |
| } |
| |
| *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer, |
| (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize); |
| |
| pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1; |
| |
| pstPhsRule->PHSModifiedNumPackets++; |
| return STATUS_PHS_COMPRESSED; |
| } |
| |
| |
| //----------------------------------------------------------------------------- |
| // Procedure: free_phs_serviceflow_rules |
| // |
| // Description: This routine is responsible for freeing memory allocated for PHS rules. |
| // |
| // Arguments: |
| // rules - ptr to S_SERVICEFLOW_TABLE structure. |
| // |
| // Returns: |
| // Does not return any value. |
| //----------------------------------------------------------------------------- |
| |
| static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) |
| { |
| int i,j; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n"); |
| if(psServiceFlowRulesTable) |
| { |
| for(i=0;i<MAX_SERVICEFLOWS;i++) |
| { |
| S_SERVICEFLOW_ENTRY stServiceFlowEntry = |
| psServiceFlowRulesTable->stSFList[i]; |
| S_CLASSIFIER_TABLE *pstClassifierRulesTable = |
| stServiceFlowEntry.pstClassifierTable; |
| |
| if(pstClassifierRulesTable) |
| { |
| for(j=0;j<MAX_PHSRULE_PER_SF;j++) |
| { |
| if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) |
| { |
| if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule |
| ->u8RefCnt) |
| pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule |
| ->u8RefCnt--; |
| if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule |
| ->u8RefCnt) |
| kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule); |
| pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL; |
| } |
| if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) |
| { |
| if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule |
| ->u8RefCnt) |
| pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule |
| ->u8RefCnt--; |
| if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule |
| ->u8RefCnt) |
| kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule); |
| pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL; |
| } |
| } |
| kfree(pstClassifierRulesTable); |
| stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL; |
| } |
| } |
| } |
| |
| kfree(psServiceFlowRulesTable); |
| psServiceFlowRulesTable = NULL; |
| } |
| |
| |
| |
| static BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule) |
| { |
| if(psPhsRule) |
| { |
| if(!psPhsRule->u8PHSI) |
| { |
| // PHSI is not valid |
| return FALSE; |
| } |
| |
| if(!psPhsRule->u8PHSS) |
| { |
| //PHSS Is Undefined |
| return FALSE; |
| } |
| |
| //Check if PHSF is defines for the PHS Rule |
| if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF |
| { |
| return FALSE; |
| } |
| return TRUE; |
| } |
| else |
| { |
| return FALSE; |
| } |
| } |
| |
| UINT GetServiceFlowEntry(IN S_SERVICEFLOW_TABLE *psServiceFlowTable, |
| IN B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry) |
| { |
| int i; |
| for(i=0;i<MAX_SERVICEFLOWS;i++) |
| { |
| if(psServiceFlowTable->stSFList[i].bUsed) |
| { |
| if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid) |
| { |
| *ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i]; |
| return i; |
| } |
| } |
| } |
| |
| *ppstServiceFlowEntry = NULL; |
| return PHS_INVALID_TABLE_INDEX; |
| } |
| |
| |
| UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, |
| IN B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, |
| OUT S_CLASSIFIER_ENTRY **ppstClassifierEntry) |
| { |
| int i; |
| S_CLASSIFIER_ENTRY *psClassifierRules = NULL; |
| for(i=0;i<MAX_PHSRULE_PER_SF;i++) |
| { |
| |
| if(eClsContext == eActiveClassifierRuleContext) |
| { |
| psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i]; |
| } |
| else |
| { |
| psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i]; |
| } |
| |
| if(psClassifierRules->bUsed) |
| { |
| if(psClassifierRules->uiClassifierRuleId == uiClsid) |
| { |
| *ppstClassifierEntry = psClassifierRules; |
| return i; |
| } |
| } |
| |
| } |
| |
| *ppstClassifierEntry = NULL; |
| return PHS_INVALID_TABLE_INDEX; |
| } |
| |
| static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, |
| IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, |
| OUT S_PHS_RULE **ppstPhsRule) |
| { |
| int i; |
| S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; |
| for(i=0;i<MAX_PHSRULE_PER_SF;i++) |
| { |
| if(eClsContext == eActiveClassifierRuleContext) |
| { |
| pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i]; |
| } |
| else |
| { |
| pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i]; |
| } |
| if(pstClassifierRule->bUsed) |
| { |
| if(pstClassifierRule->u8PHSI == uiPHSI) |
| { |
| *ppstPhsRule = pstClassifierRule->pstPhsRule; |
| return i; |
| } |
| } |
| |
| } |
| |
| *ppstPhsRule = NULL; |
| return PHS_INVALID_TABLE_INDEX; |
| } |
| |
| UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId, |
| IN S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule, |
| B_UINT8 u8AssociatedPHSI) |
| { |
| |
| S_CLASSIFIER_TABLE *psaClassifiertable = NULL; |
| UINT uiStatus = 0; |
| int iSfIndex; |
| BOOLEAN bFreeEntryFound =FALSE; |
| //Check for a free entry in SFID table |
| for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++) |
| { |
| if(!psServiceFlowTable->stSFList[iSfIndex].bUsed) |
| { |
| bFreeEntryFound = TRUE; |
| break; |
| } |
| } |
| |
| if(!bFreeEntryFound) |
| return ERR_SFTABLE_FULL; |
| |
| |
| psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable; |
| uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule, |
| eActiveClassifierRuleContext,u8AssociatedPHSI); |
| if(uiStatus == PHS_SUCCESS) |
| { |
| //Add entry at free index to the SF |
| psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE; |
| psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid; |
| } |
| |
| return uiStatus; |
| |
| } |
| |
| UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, |
| IN B_UINT16 uiClsId,IN S_SERVICEFLOW_ENTRY *pstServiceFlowEntry, |
| S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI) |
| { |
| S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; |
| UINT uiStatus =PHS_SUCCESS; |
| UINT nClassifierIndex = 0; |
| S_CLASSIFIER_TABLE *psaClassifiertable = NULL; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| psaClassifiertable = pstServiceFlowEntry->pstClassifierTable; |
| |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>"); |
| |
| /* Check if the supplied Classifier already exists */ |
| nClassifierIndex =GetClassifierEntry( |
| pstServiceFlowEntry->pstClassifierTable,uiClsId, |
| eActiveClassifierRuleContext,&pstClassifierEntry); |
| if(nClassifierIndex == PHS_INVALID_TABLE_INDEX) |
| { |
| /* |
| The Classifier doesn't exist. So its a new classifier being added. |
| Add new entry to associate PHS Rule to the Classifier |
| */ |
| |
| uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable, |
| psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI); |
| return uiStatus; |
| } |
| |
| /* |
| The Classifier exists.The PHS Rule for this classifier |
| is being modified |
| */ |
| if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) |
| { |
| if(pstClassifierEntry->pstPhsRule == NULL) |
| return ERR_PHS_INVALID_PHS_RULE; |
| |
| /* |
| This rule already exists if any fields are changed for this PHS |
| rule update them. |
| */ |
| /* If any part of PHSF is valid then we update PHSF */ |
| if(psPhsRule->u8PHSFLength) |
| { |
| //update PHSF |
| memcpy(pstClassifierEntry->pstPhsRule->u8PHSF, |
| psPhsRule->u8PHSF , MAX_PHS_LENGTHS); |
| } |
| if(psPhsRule->u8PHSFLength) |
| { |
| //update PHSFLen |
| pstClassifierEntry->pstPhsRule->u8PHSFLength = |
| psPhsRule->u8PHSFLength; |
| } |
| if(psPhsRule->u8PHSMLength) |
| { |
| //update PHSM |
| memcpy(pstClassifierEntry->pstPhsRule->u8PHSM, |
| psPhsRule->u8PHSM, MAX_PHS_LENGTHS); |
| } |
| if(psPhsRule->u8PHSMLength) |
| { |
| //update PHSM Len |
| pstClassifierEntry->pstPhsRule->u8PHSMLength = |
| psPhsRule->u8PHSMLength; |
| } |
| if(psPhsRule->u8PHSS) |
| { |
| //update PHSS |
| pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS; |
| } |
| |
| //update PHSV |
| pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV; |
| |
| } |
| else |
| { |
| /* |
| A new rule is being set for this classifier. |
| */ |
| uiStatus=UpdateClassifierPHSRule( uiClsId, pstClassifierEntry, |
| psaClassifiertable, psPhsRule, u8AssociatedPHSI); |
| } |
| |
| |
| |
| return uiStatus; |
| } |
| |
| static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, |
| S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, |
| E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI) |
| { |
| UINT iClassifierIndex = 0; |
| BOOLEAN bFreeEntryFound = FALSE; |
| S_CLASSIFIER_ENTRY *psClassifierRules = NULL; |
| UINT nStatus = PHS_SUCCESS; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule"); |
| if(psaClassifiertable == NULL) |
| { |
| return ERR_INVALID_CLASSIFIERTABLE_FOR_SF; |
| } |
| |
| if(eClsContext == eOldClassifierRuleContext) |
| { |
| /* If An Old Entry for this classifier ID already exists in the |
| old rules table replace it. */ |
| |
| iClassifierIndex = |
| GetClassifierEntry(psaClassifiertable, uiClsId, |
| eClsContext,&psClassifierRules); |
| if(iClassifierIndex != PHS_INVALID_TABLE_INDEX) |
| { |
| /* |
| The Classifier already exists in the old rules table |
| Lets replace the old classifier with the new one. |
| */ |
| bFreeEntryFound = TRUE; |
| } |
| } |
| |
| if(!bFreeEntryFound) |
| { |
| /* |
| Continue to search for a free location to add the rule |
| */ |
| for(iClassifierIndex = 0; iClassifierIndex < |
| MAX_PHSRULE_PER_SF; iClassifierIndex++) |
| { |
| if(eClsContext == eActiveClassifierRuleContext) |
| { |
| psClassifierRules = |
| &psaClassifiertable->stActivePhsRulesList[iClassifierIndex]; |
| } |
| else |
| { |
| psClassifierRules = |
| &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; |
| } |
| |
| if(!psClassifierRules->bUsed) |
| { |
| bFreeEntryFound = TRUE; |
| break; |
| } |
| } |
| } |
| |
| if(!bFreeEntryFound) |
| { |
| if(eClsContext == eActiveClassifierRuleContext) |
| { |
| return ERR_CLSASSIFIER_TABLE_FULL; |
| } |
| else |
| { |
| //Lets replace the oldest rule if we are looking in old Rule table |
| if(psaClassifiertable->uiOldestPhsRuleIndex >= |
| MAX_PHSRULE_PER_SF) |
| { |
| psaClassifiertable->uiOldestPhsRuleIndex =0; |
| } |
| |
| iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex; |
| psClassifierRules = |
| &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; |
| |
| (psaClassifiertable->uiOldestPhsRuleIndex)++; |
| } |
| } |
| |
| if(eClsContext == eOldClassifierRuleContext) |
| { |
| if(psClassifierRules->pstPhsRule == NULL) |
| { |
| psClassifierRules->pstPhsRule = kmalloc(sizeof(S_PHS_RULE),GFP_KERNEL); |
| |
| if(NULL == psClassifierRules->pstPhsRule) |
| return ERR_PHSRULE_MEMALLOC_FAIL; |
| } |
| |
| psClassifierRules->bUsed = TRUE; |
| psClassifierRules->uiClassifierRuleId = uiClsId; |
| psClassifierRules->u8PHSI = psPhsRule->u8PHSI; |
| psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule; |
| |
| /* Update The PHS rule */ |
| memcpy(psClassifierRules->pstPhsRule, |
| psPhsRule, sizeof(S_PHS_RULE)); |
| } |
| else |
| { |
| nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules, |
| psaClassifiertable,psPhsRule,u8AssociatedPHSI); |
| } |
| return nStatus; |
| } |
| |
| |
| static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, |
| IN S_CLASSIFIER_ENTRY *pstClassifierEntry, |
| S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, |
| B_UINT8 u8AssociatedPHSI) |
| { |
| S_PHS_RULE *pstAddPhsRule = NULL; |
| UINT nPhsRuleIndex = 0; |
| BOOLEAN bPHSRuleOrphaned = FALSE; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| psPhsRule->u8RefCnt =0; |
| |
| /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/ |
| bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable, |
| pstClassifierEntry->pstPhsRule); |
| |
| //Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF |
| nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI, |
| eActiveClassifierRuleContext, &pstAddPhsRule); |
| if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier"); |
| |
| if(psPhsRule->u8PHSI == 0) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n"); |
| return ERR_PHS_INVALID_PHS_RULE; |
| } |
| //Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId |
| if(FALSE == bPHSRuleOrphaned) |
| { |
| pstClassifierEntry->pstPhsRule = kmalloc(sizeof(S_PHS_RULE), GFP_KERNEL); |
| if(NULL == pstClassifierEntry->pstPhsRule) |
| { |
| return ERR_PHSRULE_MEMALLOC_FAIL; |
| } |
| } |
| memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE)); |
| |
| } |
| else |
| { |
| //Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule"); |
| if(bPHSRuleOrphaned) |
| { |
| kfree(pstClassifierEntry->pstPhsRule); |
| pstClassifierEntry->pstPhsRule = NULL; |
| } |
| pstClassifierEntry->pstPhsRule = pstAddPhsRule; |
| |
| } |
| pstClassifierEntry->bUsed = TRUE; |
| pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI; |
| pstClassifierEntry->uiClassifierRuleId = uiClsId; |
| pstClassifierEntry->pstPhsRule->u8RefCnt++; |
| pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule; |
| |
| return PHS_SUCCESS; |
| |
| } |
| |
| static BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule) |
| { |
| if(pstPhsRule==NULL) |
| return FALSE; |
| if(pstPhsRule->u8RefCnt) |
| pstPhsRule->u8RefCnt--; |
| if(0==pstPhsRule->u8RefCnt) |
| { |
| /*if(pstPhsRule->u8PHSI) |
| //Store the currently active rule into the old rules list |
| CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/ |
| return TRUE; |
| } |
| else |
| { |
| return FALSE; |
| } |
| } |
| |
| void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension) |
| { |
| int i,j,k,l; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n"); |
| for(i=0;i<MAX_SERVICEFLOWS;i++) |
| { |
| S_SERVICEFLOW_ENTRY stServFlowEntry = |
| pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i]; |
| if(stServFlowEntry.bUsed) |
| { |
| for(j=0;j<MAX_PHSRULE_PER_SF;j++) |
| { |
| for(l=0;l<2;l++) |
| { |
| S_CLASSIFIER_ENTRY stClsEntry; |
| if(l==0) |
| { |
| stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j]; |
| if(stClsEntry.bUsed) |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n"); |
| } |
| else |
| { |
| stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j]; |
| if(stClsEntry.bUsed) |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n"); |
| } |
| if(stClsEntry.bUsed) |
| { |
| |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X",stServFlowEntry.uiVcid); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X",stClsEntry.uiClassifierRuleId); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X",stClsEntry.u8PHSI); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n"); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X",stClsEntry.pstPhsRule->u8PHSI); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : "); |
| for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSF[k]); |
| } |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X",stClsEntry.pstPhsRule->u8PHSMLength); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :"); |
| for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSM[k]); |
| } |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X",stClsEntry.pstPhsRule->u8PHSV); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n"); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| //----------------------------------------------------------------------------- |
| // Procedure: phs_decompress |
| // |
| // Description: This routine restores the static fields within the packet. |
| // |
| // Arguments: |
| // in_buf - ptr to incoming packet buffer. |
| // out_buf - ptr to output buffer where the suppressed header is copied. |
| // decomp_phs_rules - ptr to PHS rule. |
| // header_size - ptr to field which holds the phss or phsf_length. |
| // |
| // Returns: |
| // size -The number of bytes of dynamic fields present with in the incoming packet |
| // header. |
| // 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed. |
| //----------------------------------------------------------------------------- |
| |
| int phs_decompress(unsigned char *in_buf,unsigned char *out_buf, |
| S_PHS_RULE *decomp_phs_rules,UINT *header_size) |
| { |
| int phss,size=0; |
| S_PHS_RULE *tmp_memb; |
| int bit,i=0; |
| unsigned char *phsf,*phsm; |
| int in_buf_len = *header_size-1; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| in_buf++; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n"); |
| *header_size = 0; |
| |
| if((decomp_phs_rules == NULL )) |
| return 0; |
| |
| |
| tmp_memb = decomp_phs_rules; |
| //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi)); |
| //*header_size = tmp_memb->u8PHSFLength; |
| phss = tmp_memb->u8PHSS; |
| phsf = tmp_memb->u8PHSF; |
| phsm = tmp_memb->u8PHSM; |
| |
| if(phss > MAX_PHS_LENGTHS) |
| phss = MAX_PHS_LENGTHS; |
| //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index)); |
| while((phss > 0) && (size < in_buf_len)) |
| { |
| bit = ((*phsm << i)& SUPPRESS); |
| |
| if(bit == SUPPRESS) |
| { |
| *out_buf = *phsf; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d", |
| phss,*phsf,*out_buf); |
| } |
| else |
| { |
| *out_buf = *in_buf; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d", |
| phss,*in_buf,*out_buf); |
| in_buf++; |
| size++; |
| } |
| out_buf++; |
| phsf++; |
| phss--; |
| i++; |
| *header_size=*header_size + 1; |
| |
| if(i > MAX_NO_BIT) |
| { |
| i=0; |
| phsm++; |
| } |
| } |
| return size; |
| } |
| |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| // Procedure: phs_compress |
| // |
| // Description: This routine suppresses the static fields within the packet.Before |
| // that it will verify the fields to be suppressed with the corresponding fields in the |
| // phsf. For verification it checks the phsv field of PHS rule. If set and verification |
| // succeeds it suppresses the field.If any one static field is found different none of |
| // the static fields are suppressed then the packet is sent as uncompressed packet with |
| // phsi=0. |
| // |
| // Arguments: |
| // phs_rule - ptr to PHS rule. |
| // in_buf - ptr to incoming packet buffer. |
| // out_buf - ptr to output buffer where the suppressed header is copied. |
| // header_size - ptr to field which holds the phss. |
| // |
| // Returns: |
| // size-The number of bytes copied into the output buffer i.e dynamic fields |
| // 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails. |
| //----------------------------------------------------------------------------- |
| static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf |
| ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size) |
| { |
| unsigned char *old_addr = out_buf; |
| int suppress = 0; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| if(phs_rule == NULL) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!"); |
| *out_buf = ZERO_PHSI; |
| return STATUS_PHS_NOCOMPRESSION; |
| } |
| |
| |
| if(phs_rule->u8PHSS <= *new_header_size) |
| { |
| *header_size = phs_rule->u8PHSS; |
| } |
| else |
| { |
| *header_size = *new_header_size; |
| } |
| //To copy PHSI |
| out_buf++; |
| suppress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF, |
| phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size); |
| |
| if(suppress == STATUS_PHS_COMPRESSED) |
| { |
| *old_addr = (unsigned char)phs_rule->u8PHSI; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI); |
| } |
| else |
| { |
| *old_addr = ZERO_PHSI; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed"); |
| } |
| return suppress; |
| } |
| |
| |
| //----------------------------------------------------------------------------- |
| // Procedure: verify_suppress_phsf |
| // |
| // Description: This routine verifies the fields of the packet and if all the |
| // static fields are equal it adds the phsi of that PHS rule.If any static |
| // field differs it woun't suppress any field. |
| // |
| // Arguments: |
| // rules_set - ptr to classifier_rules. |
| // in_buffer - ptr to incoming packet buffer. |
| // out_buffer - ptr to output buffer where the suppressed header is copied. |
| // phsf - ptr to phsf. |
| // phsm - ptr to phsm. |
| // phss - variable holding phss. |
| // |
| // Returns: |
| // size-The number of bytes copied into the output buffer i.e dynamic fields. |
| // 0 -Packet has failed the verification. |
| //----------------------------------------------------------------------------- |
| |
| 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) |
| { |
| unsigned int size=0; |
| int bit,i=0; |
| struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm); |
| |
| |
| if(phss>(*new_header_size)) |
| { |
| phss=*new_header_size; |
| } |
| while(phss > 0) |
| { |
| bit = ((*phsm << i)& SUPPRESS); |
| if(bit == SUPPRESS) |
| { |
| |
| if(*in_buffer != *phsf) |
| { |
| if(phsv == VERIFY) |
| { |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",phss,*in_buffer,*phsf); |
| return STATUS_PHS_NOCOMPRESSION; |
| } |
| } |
| else |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field %d buf %d phsf %d",phss,*in_buffer,*phsf); |
| } |
| else |
| { |
| *out_buffer = *in_buffer; |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d out %d",*in_buffer,*out_buffer); |
| out_buffer++; |
| size++; |
| } |
| in_buffer++; |
| phsf++; |
| phss--; |
| i++; |
| if(i > MAX_NO_BIT) |
| { |
| i=0; |
| phsm++; |
| } |
| } |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success"); |
| *new_header_size = size; |
| return STATUS_PHS_COMPRESSED; |
| } |
| |
| |
| |
| |
| |
| |