Linux 3.3-rc6
[linux/fpc-iii.git] / drivers / staging / bcm / PHSModule.c
blob4aa2b71a40ebe40a1d5c27b8506443955e18e650
1 #include "headers.h"
3 static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
5 static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
7 static UINT CreateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI);
9 static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
11 static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule);
13 static BOOLEAN DerefPhsRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule);
15 static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry);
17 static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule);
19 static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable);
21 static int phs_compress(S_PHS_RULE *phs_members,unsigned char *in_buf,
22 unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
25 static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
26 unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
28 static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
29 S_PHS_RULE *phs_rules,UINT *header_size);
32 static ULONG PhsCompress(void* pvContext,
33 B_UINT16 uiVcid,
34 B_UINT16 uiClsId,
35 void *pvInputBuffer,
36 void *pvOutputBuffer,
37 UINT *pOldHeaderSize,
38 UINT *pNewHeaderSize );
40 static ULONG PhsDeCompress(void* pvContext,
41 B_UINT16 uiVcid,
42 void *pvInputBuffer,
43 void *pvOutputBuffer,
44 UINT *pInHeaderSize,
45 UINT *pOutHeaderSize);
49 #define IN
50 #define OUT
53 Function: PHSTransmit
55 Description: This routine handle PHS(Payload Header Suppression for Tx path.
56 It extracts a fragment of the NDIS_PACKET containing the header
57 to be suppressed.It then supresses the header by invoking PHS exported compress routine.
58 The header data after supression is copied back to the NDIS_PACKET.
61 Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context
62 IN Packet - NDIS packet containing data to be transmitted
63 IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
64 identify PHS rule to be applied.
65 B_UINT16 uiClassifierRuleID - Classifier Rule ID
66 BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
68 Return: STATUS_SUCCESS - If the send was successful.
69 Other - If an error occured.
72 int PHSTransmit(PMINI_ADAPTER Adapter,
73 struct sk_buff **pPacket,
74 USHORT Vcid,
75 B_UINT16 uiClassifierRuleID,
76 BOOLEAN bHeaderSuppressionEnabled,
77 UINT *PacketLen,
78 UCHAR bEthCSSupport)
81 //PHS Sepcific
82 UINT unPHSPktHdrBytesCopied = 0;
83 UINT unPhsOldHdrSize = 0;
84 UINT unPHSNewPktHeaderLen = 0;
85 /* Pointer to PHS IN Hdr Buffer */
86 PUCHAR pucPHSPktHdrInBuf =
87 Adapter->stPhsTxContextInfo.ucaHdrSupressionInBuf;
88 /* Pointer to PHS OUT Hdr Buffer */
89 PUCHAR pucPHSPktHdrOutBuf =
90 Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf;
91 UINT usPacketType;
92 UINT BytesToRemove=0;
93 BOOLEAN bPHSI = 0;
94 LONG ulPhsStatus = 0;
95 UINT numBytesCompressed = 0;
96 struct sk_buff *newPacket = NULL;
97 struct sk_buff *Packet = *pPacket;
99 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
101 if(!bEthCSSupport)
102 BytesToRemove=ETH_HLEN;
104 Accumulate the header upto the size we support supression
105 from NDIS packet
108 usPacketType=((struct ethhdr *)(Packet->data))->h_proto;
111 pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
112 //considering data after ethernet header
113 if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
116 unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
118 else
120 unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
123 if( (unPHSPktHdrBytesCopied > 0 ) &&
124 (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))
128 // Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
129 // Suppress only if IP Header and PHS Enabled For the Service Flow
130 if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
131 (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
132 (bHeaderSuppressionEnabled))
134 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);
137 unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
138 ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
139 Vcid,
140 uiClassifierRuleID,
141 pucPHSPktHdrInBuf,
142 pucPHSPktHdrOutBuf,
143 &unPhsOldHdrSize,
144 &unPHSNewPktHeaderLen);
145 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen);
147 if(unPHSNewPktHeaderLen == unPhsOldHdrSize)
149 if( ulPhsStatus == STATUS_PHS_COMPRESSED)
150 bPHSI = *pucPHSPktHdrOutBuf;
151 ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
154 if( ulPhsStatus == STATUS_PHS_COMPRESSED)
156 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed");
158 if(skb_cloned(Packet))
160 newPacket = skb_copy(Packet, GFP_ATOMIC);
162 if(newPacket == NULL)
163 return STATUS_FAILURE;
165 dev_kfree_skb(Packet);
166 *pPacket = Packet = newPacket;
167 pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
170 numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
172 memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
173 memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
174 skb_pull(Packet, numBytesCompressed);
176 return STATUS_SUCCESS;
179 else
181 //if one byte headroom is not available, increase it through skb_cow
182 if(!(skb_headroom(Packet) > 0))
184 if(skb_cow(Packet, 1))
186 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
187 return STATUS_FAILURE;
190 skb_push(Packet, 1);
192 // CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes. not needed .... hence corrupting it.
193 *(Packet->data + BytesToRemove) = bPHSI;
194 return STATUS_SUCCESS;
197 else
199 if(!bHeaderSuppressionEnabled)
201 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");
204 return STATUS_SUCCESS;
208 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");
209 return STATUS_SUCCESS;
212 int PHSReceive(PMINI_ADAPTER Adapter,
213 USHORT usVcid,
214 struct sk_buff *packet,
215 UINT *punPacketLen,
216 UCHAR *pucEthernetHdr,
217 UINT bHeaderSuppressionEnabled)
219 u32 nStandardPktHdrLen = 0;
220 u32 nTotalsupressedPktHdrBytes = 0;
221 int ulPhsStatus = 0;
222 PUCHAR pucInBuff = NULL ;
223 UINT TotalBytesAdded = 0;
224 if(!bHeaderSuppressionEnabled)
226 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
227 return ulPhsStatus;
230 pucInBuff = packet->data;
232 //Restore PHS suppressed header
233 nStandardPktHdrLen = packet->len;
234 ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
235 usVcid,
236 pucInBuff,
237 Adapter->ucaPHSPktRestoreBuf,
238 &nTotalsupressedPktHdrBytes,
239 &nStandardPktHdrLen);
241 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
242 nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
244 if(ulPhsStatus != STATUS_PHS_COMPRESSED)
246 skb_pull(packet, 1);
247 return STATUS_SUCCESS;
249 else
251 TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - PHSI_LEN;
252 if(TotalBytesAdded)
254 if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
255 skb_push(packet, TotalBytesAdded);
256 else
258 if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))
260 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
261 return STATUS_FAILURE;
264 skb_push(packet, TotalBytesAdded);
268 memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
271 return STATUS_SUCCESS;
274 void DumpFullPacket(UCHAR *pBuf,UINT nPktLen)
276 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
277 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");
278 BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);
281 //-----------------------------------------------------------------------------
282 // Procedure: phs_init
284 // Description: This routine is responsible for allocating memory for classifier and
285 // PHS rules.
287 // Arguments:
288 // pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
290 // Returns:
291 // TRUE(1) -If allocation of memory was success full.
292 // FALSE -If allocation of memory fails.
293 //-----------------------------------------------------------------------------
294 int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter)
296 int i;
297 S_SERVICEFLOW_TABLE *pstServiceFlowTable;
298 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function ");
300 if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
301 return -EINVAL;
303 pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
304 kzalloc(sizeof(S_SERVICEFLOW_TABLE), GFP_KERNEL);
306 if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
308 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
309 return -ENOMEM;
312 pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
313 for(i=0;i<MAX_SERVICEFLOWS;i++)
315 S_SERVICEFLOW_ENTRY sServiceFlow = pstServiceFlowTable->stSFList[i];
316 sServiceFlow.pstClassifierTable = kzalloc(sizeof(S_CLASSIFIER_TABLE), GFP_KERNEL);
317 if(!sServiceFlow.pstClassifierTable)
319 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
320 free_phs_serviceflow_rules(pPhsdeviceExtension->
321 pstServiceFlowPhsRulesTable);
322 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
323 return -ENOMEM;
327 pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
329 if(pPhsdeviceExtension->CompressedTxBuffer == NULL)
331 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
332 free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
333 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
334 return -ENOMEM;
337 pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
338 if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
340 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
341 kfree(pPhsdeviceExtension->CompressedTxBuffer);
342 free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
343 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
344 return -ENOMEM;
349 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull");
350 return STATUS_SUCCESS;
354 int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt)
356 if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)
358 free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
359 pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
362 kfree(pPHSDeviceExt->CompressedTxBuffer);
363 pPHSDeviceExt->CompressedTxBuffer = NULL;
365 kfree(pPHSDeviceExt->UnCompressedRxBuffer);
366 pPHSDeviceExt->UnCompressedRxBuffer = NULL;
368 return 0;
373 //PHS functions
374 /*++
375 PhsUpdateClassifierRule
377 Routine Description:
378 Exported function to add or modify a PHS Rule.
380 Arguments:
381 IN void* pvContext - PHS Driver Specific Context
382 IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
383 IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
384 IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
386 Return Value:
388 0 if successful,
389 >0 Error.
391 --*/
392 ULONG PhsUpdateClassifierRule(IN void* pvContext,
393 IN B_UINT16 uiVcid ,
394 IN B_UINT16 uiClsId ,
395 IN S_PHS_RULE *psPhsRule,
396 IN B_UINT8 u8AssociatedPHSI)
398 ULONG lStatus =0;
399 UINT nSFIndex =0 ;
400 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
401 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
405 PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
407 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n");
409 if(pDeviceExtension == NULL)
411 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");
412 return ERR_PHS_INVALID_DEVICE_EXETENSION;
416 if(u8AssociatedPHSI == 0)
418 return ERR_PHS_INVALID_PHS_RULE;
421 /* Retrieve the SFID Entry Index for requested Service Flow */
423 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
424 uiVcid,&pstServiceFlowEntry);
426 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
428 /* This is a new SF. Create a mapping entry for this */
429 lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
430 pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
431 return lStatus;
434 /* SF already Exists Add PHS Rule to existing SF */
435 lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
436 pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
438 return lStatus;
441 /*++
442 PhsDeletePHSRule
444 Routine Description:
445 Deletes the specified phs Rule within Vcid
447 Arguments:
448 IN void* pvContext - PHS Driver Specific Context
449 IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
450 IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
452 Return Value:
454 0 if successful,
455 >0 Error.
457 --*/
459 ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)
461 ULONG lStatus =0;
462 UINT nSFIndex =0, nClsidIndex =0 ;
463 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
464 S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
465 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
468 PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
470 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
472 if(pDeviceExtension)
475 //Retrieve the SFID Entry Index for requested Service Flow
476 nSFIndex = GetServiceFlowEntry(pDeviceExtension
477 ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);
479 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
481 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
482 return ERR_SF_MATCH_FAIL;
485 pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
486 if(pstClassifierRulesTable)
488 for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
490 if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
492 if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
493 if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
494 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
495 if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
496 kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
497 memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
498 sizeof(S_CLASSIFIER_ENTRY));
505 return lStatus;
508 /*++
509 PhsDeleteClassifierRule
511 Routine Description:
512 Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
514 Arguments:
515 IN void* pvContext - PHS Driver Specific Context
516 IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
517 IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
519 Return Value:
521 0 if successful,
522 >0 Error.
524 --*/
525 ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 uiClsId)
527 ULONG lStatus =0;
528 UINT nSFIndex =0, nClsidIndex =0 ;
529 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
530 S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
531 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
532 PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
534 if(pDeviceExtension)
536 //Retrieve the SFID Entry Index for requested Service Flow
537 nSFIndex = GetServiceFlowEntry(pDeviceExtension
538 ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
539 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
541 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n");
542 return ERR_SF_MATCH_FAIL;
545 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
546 uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
547 if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
549 if(pstClassifierEntry->pstPhsRule)
551 if(pstClassifierEntry->pstPhsRule->u8RefCnt)
552 pstClassifierEntry->pstPhsRule->u8RefCnt--;
553 if(0==pstClassifierEntry->pstPhsRule->u8RefCnt)
554 kfree(pstClassifierEntry->pstPhsRule);
557 memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
560 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
561 uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
563 if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
565 kfree(pstClassifierEntry->pstPhsRule);
566 memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
569 return lStatus;
572 /*++
573 PhsDeleteSFRules
575 Routine Description:
576 Exported function to Delete a all PHS Rules for the SFID.
578 Arguments:
579 IN void* pvContext - PHS Driver Specific Context
580 IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
582 Return Value:
584 0 if successful,
585 >0 Error.
587 --*/
588 ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid)
591 ULONG lStatus =0;
592 UINT nSFIndex =0, nClsidIndex =0 ;
593 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
594 S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
595 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
596 PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
597 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n");
599 if(pDeviceExtension)
601 //Retrieve the SFID Entry Index for requested Service Flow
602 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
603 uiVcid,&pstServiceFlowEntry);
604 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
606 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
607 return ERR_SF_MATCH_FAIL;
610 pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
611 if(pstClassifierRulesTable)
613 for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
615 if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
617 if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
618 .pstPhsRule->u8RefCnt)
619 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
620 .pstPhsRule->u8RefCnt--;
621 if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
622 .pstPhsRule->u8RefCnt)
623 kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
624 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
625 .pstPhsRule = NULL;
627 memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
628 if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule)
630 if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
631 .pstPhsRule->u8RefCnt)
632 pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
633 .pstPhsRule->u8RefCnt--;
634 if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
635 .pstPhsRule->u8RefCnt)
636 kfree(pstClassifierRulesTable
637 ->stOldPhsRulesList[nClsidIndex].pstPhsRule);
638 pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
639 .pstPhsRule = NULL;
641 memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
644 pstServiceFlowEntry->bUsed = FALSE;
645 pstServiceFlowEntry->uiVcid = 0;
649 return lStatus;
653 /*++
654 PhsCompress
656 Routine Description:
657 Exported function to compress the data using PHS.
659 Arguments:
660 IN void* pvContext - PHS Driver Specific Context.
661 IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
662 IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
663 IN void *pvInputBuffer - The Input buffer containg packet header data
664 IN void *pvOutputBuffer - The output buffer returned by this function after PHS
665 IN UINT *pOldHeaderSize - The actual size of the header before PHS
666 IN UINT *pNewHeaderSize - The new size of the header after applying PHS
668 Return Value:
670 0 if successful,
671 >0 Error.
673 --*/
674 ULONG PhsCompress(IN void* pvContext,
675 IN B_UINT16 uiVcid,
676 IN B_UINT16 uiClsId,
677 IN void *pvInputBuffer,
678 OUT void *pvOutputBuffer,
679 OUT UINT *pOldHeaderSize,
680 OUT UINT *pNewHeaderSize )
682 UINT nSFIndex =0, nClsidIndex =0 ;
683 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
684 S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
685 S_PHS_RULE *pstPhsRule = NULL;
686 ULONG lStatus =0;
687 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
691 PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
694 if(pDeviceExtension == NULL)
696 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n");
697 lStatus = STATUS_PHS_NOCOMPRESSION ;
698 return lStatus;
702 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n");
705 //Retrieve the SFID Entry Index for requested Service Flow
706 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
707 uiVcid,&pstServiceFlowEntry);
708 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
710 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n");
711 lStatus = STATUS_PHS_NOCOMPRESSION ;
712 return lStatus;
715 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
716 uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry);
718 if(nClsidIndex == PHS_INVALID_TABLE_INDEX)
720 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n");
721 lStatus = STATUS_PHS_NOCOMPRESSION ;
722 return lStatus;
726 //get rule from SF id,Cls ID pair and proceed
727 pstPhsRule = pstClassifierEntry->pstPhsRule;
729 if(!ValidatePHSRuleComplete(pstPhsRule))
731 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n");
732 lStatus = STATUS_PHS_NOCOMPRESSION ;
733 return lStatus;
736 //Compress Packet
737 lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer,
738 (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize);
740 if(lStatus == STATUS_PHS_COMPRESSED)
742 pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
743 pstPhsRule->PHSModifiedNumPackets++;
745 else
746 pstPhsRule->PHSErrorNumPackets++;
748 return lStatus;
751 /*++
752 PhsDeCompress
754 Routine Description:
755 Exported function to restore the packet header in Rx path.
757 Arguments:
758 IN void* pvContext - PHS Driver Specific Context.
759 IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
760 IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
761 OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
762 OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
764 Return Value:
766 0 if successful,
767 >0 Error.
769 --*/
770 ULONG PhsDeCompress(IN void* pvContext,
771 IN B_UINT16 uiVcid,
772 IN void *pvInputBuffer,
773 OUT void *pvOutputBuffer,
774 OUT UINT *pInHeaderSize,
775 OUT UINT *pOutHeaderSize )
777 UINT nSFIndex =0, nPhsRuleIndex =0 ;
778 S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
779 S_PHS_RULE *pstPhsRule = NULL;
780 UINT phsi;
781 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
782 PPHS_DEVICE_EXTENSION pDeviceExtension=
783 (PPHS_DEVICE_EXTENSION)pvContext;
785 *pInHeaderSize = 0;
787 if(pDeviceExtension == NULL)
789 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
790 return ERR_PHS_INVALID_DEVICE_EXETENSION;
793 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
795 phsi = *((unsigned char *)(pvInputBuffer));
796 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
797 if(phsi == UNCOMPRESSED_PACKET )
799 return STATUS_PHS_NOCOMPRESSION;
802 //Retrieve the SFID Entry Index for requested Service Flow
803 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
804 uiVcid,&pstServiceFlowEntry);
805 if(nSFIndex == PHS_INVALID_TABLE_INDEX)
807 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
808 return ERR_SF_MATCH_FAIL;
811 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi,
812 eActiveClassifierRuleContext,&pstPhsRule);
813 if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
815 //Phs Rule does not exist in active rules table. Lets try in the old rules table.
816 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
817 phsi,eOldClassifierRuleContext,&pstPhsRule);
818 if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
820 return ERR_PHSRULE_MATCH_FAIL;
825 *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
826 (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize);
828 pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
830 pstPhsRule->PHSModifiedNumPackets++;
831 return STATUS_PHS_COMPRESSED;
835 //-----------------------------------------------------------------------------
836 // Procedure: free_phs_serviceflow_rules
838 // Description: This routine is responsible for freeing memory allocated for PHS rules.
840 // Arguments:
841 // rules - ptr to S_SERVICEFLOW_TABLE structure.
843 // Returns:
844 // Does not return any value.
845 //-----------------------------------------------------------------------------
847 static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable)
849 int i,j;
850 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
852 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
853 if(psServiceFlowRulesTable)
855 for(i=0;i<MAX_SERVICEFLOWS;i++)
857 S_SERVICEFLOW_ENTRY stServiceFlowEntry =
858 psServiceFlowRulesTable->stSFList[i];
859 S_CLASSIFIER_TABLE *pstClassifierRulesTable =
860 stServiceFlowEntry.pstClassifierTable;
862 if(pstClassifierRulesTable)
864 for(j=0;j<MAX_PHSRULE_PER_SF;j++)
866 if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule)
868 if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
869 ->u8RefCnt)
870 pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
871 ->u8RefCnt--;
872 if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
873 ->u8RefCnt)
874 kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
875 pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
877 if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule)
879 if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
880 ->u8RefCnt)
881 pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
882 ->u8RefCnt--;
883 if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
884 ->u8RefCnt)
885 kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
886 pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
889 kfree(pstClassifierRulesTable);
890 stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
895 kfree(psServiceFlowRulesTable);
896 psServiceFlowRulesTable = NULL;
901 static BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule)
903 if(psPhsRule)
905 if(!psPhsRule->u8PHSI)
907 // PHSI is not valid
908 return FALSE;
911 if(!psPhsRule->u8PHSS)
913 //PHSS Is Undefined
914 return FALSE;
917 //Check if PHSF is defines for the PHS Rule
918 if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF
920 return FALSE;
922 return TRUE;
924 else
926 return FALSE;
930 UINT GetServiceFlowEntry(IN S_SERVICEFLOW_TABLE *psServiceFlowTable,
931 IN B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry)
933 int i;
934 for(i=0;i<MAX_SERVICEFLOWS;i++)
936 if(psServiceFlowTable->stSFList[i].bUsed)
938 if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid)
940 *ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
941 return i;
946 *ppstServiceFlowEntry = NULL;
947 return PHS_INVALID_TABLE_INDEX;
951 UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
952 IN B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
953 OUT S_CLASSIFIER_ENTRY **ppstClassifierEntry)
955 int i;
956 S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
957 for(i=0;i<MAX_PHSRULE_PER_SF;i++)
960 if(eClsContext == eActiveClassifierRuleContext)
962 psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
964 else
966 psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
969 if(psClassifierRules->bUsed)
971 if(psClassifierRules->uiClassifierRuleId == uiClsid)
973 *ppstClassifierEntry = psClassifierRules;
974 return i;
980 *ppstClassifierEntry = NULL;
981 return PHS_INVALID_TABLE_INDEX;
984 static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
985 IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
986 OUT S_PHS_RULE **ppstPhsRule)
988 int i;
989 S_CLASSIFIER_ENTRY *pstClassifierRule = NULL;
990 for(i=0;i<MAX_PHSRULE_PER_SF;i++)
992 if(eClsContext == eActiveClassifierRuleContext)
994 pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
996 else
998 pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
1000 if(pstClassifierRule->bUsed)
1002 if(pstClassifierRule->u8PHSI == uiPHSI)
1004 *ppstPhsRule = pstClassifierRule->pstPhsRule;
1005 return i;
1011 *ppstPhsRule = NULL;
1012 return PHS_INVALID_TABLE_INDEX;
1015 UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,
1016 IN S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,
1017 B_UINT8 u8AssociatedPHSI)
1020 S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
1021 UINT uiStatus = 0;
1022 int iSfIndex;
1023 BOOLEAN bFreeEntryFound =FALSE;
1024 //Check for a free entry in SFID table
1025 for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++)
1027 if(!psServiceFlowTable->stSFList[iSfIndex].bUsed)
1029 bFreeEntryFound = TRUE;
1030 break;
1034 if(!bFreeEntryFound)
1035 return ERR_SFTABLE_FULL;
1038 psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
1039 uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule,
1040 eActiveClassifierRuleContext,u8AssociatedPHSI);
1041 if(uiStatus == PHS_SUCCESS)
1043 //Add entry at free index to the SF
1044 psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
1045 psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
1048 return uiStatus;
1052 UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
1053 IN B_UINT16 uiClsId,IN S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,
1054 S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI)
1056 S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
1057 UINT uiStatus =PHS_SUCCESS;
1058 UINT nClassifierIndex = 0;
1059 S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
1060 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1061 psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
1063 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
1065 /* Check if the supplied Classifier already exists */
1066 nClassifierIndex =GetClassifierEntry(
1067 pstServiceFlowEntry->pstClassifierTable,uiClsId,
1068 eActiveClassifierRuleContext,&pstClassifierEntry);
1069 if(nClassifierIndex == PHS_INVALID_TABLE_INDEX)
1072 The Classifier doesn't exist. So its a new classifier being added.
1073 Add new entry to associate PHS Rule to the Classifier
1076 uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,
1077 psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI);
1078 return uiStatus;
1082 The Classifier exists.The PHS Rule for this classifier
1083 is being modified
1085 if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI)
1087 if(pstClassifierEntry->pstPhsRule == NULL)
1088 return ERR_PHS_INVALID_PHS_RULE;
1091 This rule already exists if any fields are changed for this PHS
1092 rule update them.
1094 /* If any part of PHSF is valid then we update PHSF */
1095 if(psPhsRule->u8PHSFLength)
1097 //update PHSF
1098 memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
1099 psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
1101 if(psPhsRule->u8PHSFLength)
1103 //update PHSFLen
1104 pstClassifierEntry->pstPhsRule->u8PHSFLength =
1105 psPhsRule->u8PHSFLength;
1107 if(psPhsRule->u8PHSMLength)
1109 //update PHSM
1110 memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
1111 psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
1113 if(psPhsRule->u8PHSMLength)
1115 //update PHSM Len
1116 pstClassifierEntry->pstPhsRule->u8PHSMLength =
1117 psPhsRule->u8PHSMLength;
1119 if(psPhsRule->u8PHSS)
1121 //update PHSS
1122 pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
1125 //update PHSV
1126 pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
1129 else
1132 A new rule is being set for this classifier.
1134 uiStatus=UpdateClassifierPHSRule( uiClsId, pstClassifierEntry,
1135 psaClassifiertable, psPhsRule, u8AssociatedPHSI);
1140 return uiStatus;
1143 static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
1144 S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1145 E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI)
1147 UINT iClassifierIndex = 0;
1148 BOOLEAN bFreeEntryFound = FALSE;
1149 S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
1150 UINT nStatus = PHS_SUCCESS;
1151 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1152 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule");
1153 if(psaClassifiertable == NULL)
1155 return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
1158 if(eClsContext == eOldClassifierRuleContext)
1160 /* If An Old Entry for this classifier ID already exists in the
1161 old rules table replace it. */
1163 iClassifierIndex =
1164 GetClassifierEntry(psaClassifiertable, uiClsId,
1165 eClsContext,&psClassifierRules);
1166 if(iClassifierIndex != PHS_INVALID_TABLE_INDEX)
1169 The Classifier already exists in the old rules table
1170 Lets replace the old classifier with the new one.
1172 bFreeEntryFound = TRUE;
1176 if(!bFreeEntryFound)
1179 Continue to search for a free location to add the rule
1181 for(iClassifierIndex = 0; iClassifierIndex <
1182 MAX_PHSRULE_PER_SF; iClassifierIndex++)
1184 if(eClsContext == eActiveClassifierRuleContext)
1186 psClassifierRules =
1187 &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
1189 else
1191 psClassifierRules =
1192 &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1195 if(!psClassifierRules->bUsed)
1197 bFreeEntryFound = TRUE;
1198 break;
1203 if(!bFreeEntryFound)
1205 if(eClsContext == eActiveClassifierRuleContext)
1207 return ERR_CLSASSIFIER_TABLE_FULL;
1209 else
1211 //Lets replace the oldest rule if we are looking in old Rule table
1212 if(psaClassifiertable->uiOldestPhsRuleIndex >=
1213 MAX_PHSRULE_PER_SF)
1215 psaClassifiertable->uiOldestPhsRuleIndex =0;
1218 iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
1219 psClassifierRules =
1220 &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1222 (psaClassifiertable->uiOldestPhsRuleIndex)++;
1226 if(eClsContext == eOldClassifierRuleContext)
1228 if(psClassifierRules->pstPhsRule == NULL)
1230 psClassifierRules->pstPhsRule = kmalloc(sizeof(S_PHS_RULE),GFP_KERNEL);
1232 if(NULL == psClassifierRules->pstPhsRule)
1233 return ERR_PHSRULE_MEMALLOC_FAIL;
1236 psClassifierRules->bUsed = TRUE;
1237 psClassifierRules->uiClassifierRuleId = uiClsId;
1238 psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
1239 psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
1241 /* Update The PHS rule */
1242 memcpy(psClassifierRules->pstPhsRule,
1243 psPhsRule, sizeof(S_PHS_RULE));
1245 else
1247 nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
1248 psaClassifiertable,psPhsRule,u8AssociatedPHSI);
1250 return nStatus;
1254 static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
1255 IN S_CLASSIFIER_ENTRY *pstClassifierEntry,
1256 S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1257 B_UINT8 u8AssociatedPHSI)
1259 S_PHS_RULE *pstAddPhsRule = NULL;
1260 UINT nPhsRuleIndex = 0;
1261 BOOLEAN bPHSRuleOrphaned = FALSE;
1262 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1263 psPhsRule->u8RefCnt =0;
1265 /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/
1266 bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable,
1267 pstClassifierEntry->pstPhsRule);
1269 //Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF
1270 nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI,
1271 eActiveClassifierRuleContext, &pstAddPhsRule);
1272 if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex)
1274 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
1276 if(psPhsRule->u8PHSI == 0)
1278 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
1279 return ERR_PHS_INVALID_PHS_RULE;
1281 //Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId
1282 if(FALSE == bPHSRuleOrphaned)
1284 pstClassifierEntry->pstPhsRule = kmalloc(sizeof(S_PHS_RULE), GFP_KERNEL);
1285 if(NULL == pstClassifierEntry->pstPhsRule)
1287 return ERR_PHSRULE_MEMALLOC_FAIL;
1290 memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE));
1293 else
1295 //Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule
1296 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
1297 if(bPHSRuleOrphaned)
1299 kfree(pstClassifierEntry->pstPhsRule);
1300 pstClassifierEntry->pstPhsRule = NULL;
1302 pstClassifierEntry->pstPhsRule = pstAddPhsRule;
1305 pstClassifierEntry->bUsed = TRUE;
1306 pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
1307 pstClassifierEntry->uiClassifierRuleId = uiClsId;
1308 pstClassifierEntry->pstPhsRule->u8RefCnt++;
1309 pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
1311 return PHS_SUCCESS;
1315 static BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule)
1317 if(pstPhsRule==NULL)
1318 return FALSE;
1319 if(pstPhsRule->u8RefCnt)
1320 pstPhsRule->u8RefCnt--;
1321 if(0==pstPhsRule->u8RefCnt)
1323 /*if(pstPhsRule->u8PHSI)
1324 //Store the currently active rule into the old rules list
1325 CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/
1326 return TRUE;
1328 else
1330 return FALSE;
1334 void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension)
1336 int i,j,k,l;
1337 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1338 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n");
1339 for(i=0;i<MAX_SERVICEFLOWS;i++)
1341 S_SERVICEFLOW_ENTRY stServFlowEntry =
1342 pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
1343 if(stServFlowEntry.bUsed)
1345 for(j=0;j<MAX_PHSRULE_PER_SF;j++)
1347 for(l=0;l<2;l++)
1349 S_CLASSIFIER_ENTRY stClsEntry;
1350 if(l==0)
1352 stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
1353 if(stClsEntry.bUsed)
1354 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n");
1356 else
1358 stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
1359 if(stClsEntry.bUsed)
1360 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n");
1362 if(stClsEntry.bUsed)
1365 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X",stServFlowEntry.uiVcid);
1366 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X",stClsEntry.uiClassifierRuleId);
1367 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X",stClsEntry.u8PHSI);
1368 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
1369 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X",stClsEntry.pstPhsRule->u8PHSI);
1370 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength);
1371 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
1372 for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
1374 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSF[k]);
1376 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
1377 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
1378 for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
1380 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSM[k]);
1382 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS);
1383 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X",stClsEntry.pstPhsRule->u8PHSV);
1384 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
1393 //-----------------------------------------------------------------------------
1394 // Procedure: phs_decompress
1396 // Description: This routine restores the static fields within the packet.
1398 // Arguments:
1399 // in_buf - ptr to incoming packet buffer.
1400 // out_buf - ptr to output buffer where the suppressed header is copied.
1401 // decomp_phs_rules - ptr to PHS rule.
1402 // header_size - ptr to field which holds the phss or phsf_length.
1404 // Returns:
1405 // size -The number of bytes of dynamic fields present with in the incoming packet
1406 // header.
1407 // 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
1408 //-----------------------------------------------------------------------------
1410 int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
1411 S_PHS_RULE *decomp_phs_rules,UINT *header_size)
1413 int phss,size=0;
1414 S_PHS_RULE *tmp_memb;
1415 int bit,i=0;
1416 unsigned char *phsf,*phsm;
1417 int in_buf_len = *header_size-1;
1418 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1419 in_buf++;
1420 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n");
1421 *header_size = 0;
1423 if((decomp_phs_rules == NULL ))
1424 return 0;
1427 tmp_memb = decomp_phs_rules;
1428 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
1429 //*header_size = tmp_memb->u8PHSFLength;
1430 phss = tmp_memb->u8PHSS;
1431 phsf = tmp_memb->u8PHSF;
1432 phsm = tmp_memb->u8PHSM;
1434 if(phss > MAX_PHS_LENGTHS)
1435 phss = MAX_PHS_LENGTHS;
1436 //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));
1437 while((phss > 0) && (size < in_buf_len))
1439 bit = ((*phsm << i)& SUPPRESS);
1441 if(bit == SUPPRESS)
1443 *out_buf = *phsf;
1444 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
1445 phss,*phsf,*out_buf);
1447 else
1449 *out_buf = *in_buf;
1450 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
1451 phss,*in_buf,*out_buf);
1452 in_buf++;
1453 size++;
1455 out_buf++;
1456 phsf++;
1457 phss--;
1458 i++;
1459 *header_size=*header_size + 1;
1461 if(i > MAX_NO_BIT)
1463 i=0;
1464 phsm++;
1467 return size;
1473 //-----------------------------------------------------------------------------
1474 // Procedure: phs_compress
1476 // Description: This routine suppresses the static fields within the packet.Before
1477 // that it will verify the fields to be suppressed with the corresponding fields in the
1478 // phsf. For verification it checks the phsv field of PHS rule. If set and verification
1479 // succeeds it suppresses the field.If any one static field is found different none of
1480 // the static fields are suppressed then the packet is sent as uncompressed packet with
1481 // phsi=0.
1483 // Arguments:
1484 // phs_rule - ptr to PHS rule.
1485 // in_buf - ptr to incoming packet buffer.
1486 // out_buf - ptr to output buffer where the suppressed header is copied.
1487 // header_size - ptr to field which holds the phss.
1489 // Returns:
1490 // size-The number of bytes copied into the output buffer i.e dynamic fields
1491 // 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails.
1492 //-----------------------------------------------------------------------------
1493 static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf
1494 ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
1496 unsigned char *old_addr = out_buf;
1497 int supress = 0;
1498 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1499 if(phs_rule == NULL)
1501 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!");
1502 *out_buf = ZERO_PHSI;
1503 return STATUS_PHS_NOCOMPRESSION;
1507 if(phs_rule->u8PHSS <= *new_header_size)
1509 *header_size = phs_rule->u8PHSS;
1511 else
1513 *header_size = *new_header_size;
1515 //To copy PHSI
1516 out_buf++;
1517 supress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF,
1518 phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size);
1520 if(supress == STATUS_PHS_COMPRESSED)
1522 *old_addr = (unsigned char)phs_rule->u8PHSI;
1523 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI);
1525 else
1527 *old_addr = ZERO_PHSI;
1528 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed");
1530 return supress;
1534 //-----------------------------------------------------------------------------
1535 // Procedure: verify_suppress_phsf
1537 // Description: This routine verifies the fields of the packet and if all the
1538 // static fields are equal it adds the phsi of that PHS rule.If any static
1539 // field differs it woun't suppress any field.
1541 // Arguments:
1542 // rules_set - ptr to classifier_rules.
1543 // in_buffer - ptr to incoming packet buffer.
1544 // out_buffer - ptr to output buffer where the suppressed header is copied.
1545 // phsf - ptr to phsf.
1546 // phsm - ptr to phsm.
1547 // phss - variable holding phss.
1549 // Returns:
1550 // size-The number of bytes copied into the output buffer i.e dynamic fields.
1551 // 0 -Packet has failed the verification.
1552 //-----------------------------------------------------------------------------
1554 static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
1555 unsigned char *phsf,unsigned char *phsm,unsigned int phss,
1556 unsigned int phsv,UINT* new_header_size)
1558 unsigned int size=0;
1559 int bit,i=0;
1560 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1561 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm);
1564 if(phss>(*new_header_size))
1566 phss=*new_header_size;
1568 while(phss > 0)
1570 bit = ((*phsm << i)& SUPPRESS);
1571 if(bit == SUPPRESS)
1574 if(*in_buffer != *phsf)
1576 if(phsv == VERIFY)
1578 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);
1579 return STATUS_PHS_NOCOMPRESSION;
1582 else
1583 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);
1585 else
1587 *out_buffer = *in_buffer;
1588 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d out %d",*in_buffer,*out_buffer);
1589 out_buffer++;
1590 size++;
1592 in_buffer++;
1593 phsf++;
1594 phss--;
1595 i++;
1596 if(i > MAX_NO_BIT)
1598 i=0;
1599 phsm++;
1602 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success");
1603 *new_header_size = size;
1604 return STATUS_PHS_COMPRESSED;