3 static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,
5 struct bcm_phs_table *psServiceFlowTable,
6 struct bcm_phs_rule *psPhsRule,
7 B_UINT8 u8AssociatedPHSI);
9 static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,
11 struct bcm_phs_entry *pstServiceFlowEntry,
12 struct bcm_phs_rule *psPhsRule,
13 B_UINT8 u8AssociatedPHSI);
15 static UINT CreateClassifierPHSRule(B_UINT16 uiClsId,
16 struct bcm_phs_classifier_table *psaClassifiertable,
17 struct bcm_phs_rule *psPhsRule,
18 enum bcm_phs_classifier_context eClsContext,
19 B_UINT8 u8AssociatedPHSI);
21 static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,
22 struct bcm_phs_classifier_entry *pstClassifierEntry,
23 struct bcm_phs_classifier_table *psaClassifiertable,
24 struct bcm_phs_rule *psPhsRule,
25 B_UINT8 u8AssociatedPHSI);
27 static bool ValidatePHSRuleComplete(const struct bcm_phs_rule *psPhsRule);
29 static bool DerefPhsRule(B_UINT16 uiClsId,
30 struct bcm_phs_classifier_table *psaClassifiertable,
31 struct bcm_phs_rule *pstPhsRule);
33 static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,
35 enum bcm_phs_classifier_context eClsContext,
36 struct bcm_phs_classifier_entry **ppstClassifierEntry);
38 static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,
40 enum bcm_phs_classifier_context eClsContext,
41 struct bcm_phs_rule **ppstPhsRule);
43 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
45 static int phs_compress(struct bcm_phs_rule *phs_members,
46 unsigned char *in_buf,
47 unsigned char *out_buf,
48 unsigned int *header_size,
49 UINT *new_header_size);
51 static int verify_suppress_phsf(unsigned char *in_buffer,
52 unsigned char *out_buffer,
57 UINT *new_header_size);
59 static int phs_decompress(unsigned char *in_buf,
60 unsigned char *out_buf,
61 struct bcm_phs_rule *phs_rules,
64 static ULONG PhsCompress(void *pvContext,
70 UINT *pNewHeaderSize);
72 static ULONG PhsDeCompress(void *pvContext,
77 UINT *pOutHeaderSize);
83 * Function: PHSTransmit
84 * Description: This routine handle PHS(Payload Header Suppression for Tx path.
85 * It extracts a fragment of the NDIS_PACKET containing the header
86 * to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
87 * The header data after suppression is copied back to the NDIS_PACKET.
89 * Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
90 * IN Packet - NDIS packet containing data to be transmitted
91 * IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
92 * identify PHS rule to be applied.
93 * B_UINT16 uiClassifierRuleID - Classifier Rule ID
94 * BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
96 * Return: STATUS_SUCCESS - If the send was successful.
97 * Other - If an error occurred.
100 int PHSTransmit(struct bcm_mini_adapter *Adapter,
101 struct sk_buff **pPacket,
103 B_UINT16 uiClassifierRuleID,
104 bool bHeaderSuppressionEnabled,
109 UINT unPHSPktHdrBytesCopied = 0;
110 UINT unPhsOldHdrSize = 0;
111 UINT unPHSNewPktHeaderLen = 0;
112 /* Pointer to PHS IN Hdr Buffer */
113 PUCHAR pucPHSPktHdrInBuf =
114 Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
115 /* Pointer to PHS OUT Hdr Buffer */
116 PUCHAR pucPHSPktHdrOutBuf =
117 Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
119 UINT BytesToRemove = 0;
121 LONG ulPhsStatus = 0;
122 UINT numBytesCompressed = 0;
123 struct sk_buff *newPacket = NULL;
124 struct sk_buff *Packet = *pPacket;
126 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
130 BytesToRemove = ETH_HLEN;
132 * Accumulate the header upto the size we support suppression
136 usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
138 pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
139 /* considering data after ethernet header */
140 if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
141 unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
143 unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
145 if ((unPHSPktHdrBytesCopied > 0) &&
146 (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
149 * Step 2 Suppress Header using PHS and fill into intermediate
150 * ucaPHSPktHdrOutBuf.
151 * Suppress only if IP Header and PHS Enabled For the
154 if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
155 (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
156 (bHeaderSuppressionEnabled)) {
158 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
160 "\nTrying to PHS Compress Using Classifier rule 0x%X",
162 unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
163 ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
169 &unPHSNewPktHeaderLen);
170 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
172 "\nPHS Old header Size : %d New Header Size %d\n",
173 unPhsOldHdrSize, unPHSNewPktHeaderLen);
175 if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
177 if (ulPhsStatus == STATUS_PHS_COMPRESSED)
178 bPHSI = *pucPHSPktHdrOutBuf;
180 ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
183 if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
185 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
186 PHS_SEND, DBG_LVL_ALL,
187 "PHS Sending packet Compressed");
189 if (skb_cloned(Packet)) {
191 skb_copy(Packet, GFP_ATOMIC);
193 if (newPacket == NULL)
194 return STATUS_FAILURE;
196 dev_kfree_skb(Packet);
197 *pPacket = Packet = newPacket;
199 Packet->data + BytesToRemove;
202 numBytesCompressed = unPhsOldHdrSize -
203 (unPHSNewPktHeaderLen + PHSI_LEN);
205 memcpy(pucPHSPktHdrInBuf + numBytesCompressed,
207 unPHSNewPktHeaderLen + PHSI_LEN);
208 memcpy(Packet->data + numBytesCompressed,
209 Packet->data, BytesToRemove);
210 skb_pull(Packet, numBytesCompressed);
212 return STATUS_SUCCESS;
214 /* if one byte headroom is not available,
215 * increase it through skb_cow
217 if (!(skb_headroom(Packet) > 0)) {
219 if (skb_cow(Packet, 1)) {
220 BCM_DEBUG_PRINT(Adapter,
224 return STATUS_FAILURE;
230 * CAUTION: The MAC Header is getting corrupted
231 * here for IP CS - can be saved by copying 14
232 * Bytes. not needed .... hence corrupting it.
234 *(Packet->data + BytesToRemove) = bPHSI;
235 return STATUS_SUCCESS;
239 if (!bHeaderSuppressionEnabled)
240 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
241 PHS_SEND, DBG_LVL_ALL,
242 "\nHeader Suppression Disabled For SF: No PHS\n");
244 return STATUS_SUCCESS;
248 /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
249 * "PHSTransmit : Dumping data packet After PHS"); */
250 return STATUS_SUCCESS;
253 int PHSReceive(struct bcm_mini_adapter *Adapter,
255 struct sk_buff *packet,
257 UCHAR *pucEthernetHdr,
258 UINT bHeaderSuppressionEnabled)
260 u32 nStandardPktHdrLen = 0;
261 u32 nTotalsuppressedPktHdrBytes = 0;
263 PUCHAR pucInBuff = NULL;
264 UINT TotalBytesAdded = 0;
266 if (!bHeaderSuppressionEnabled) {
267 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
269 "\nPhs Disabled for incoming packet");
273 pucInBuff = packet->data;
275 /* Restore PHS suppressed header */
276 nStandardPktHdrLen = packet->len;
277 ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
280 Adapter->ucaPHSPktRestoreBuf,
281 &nTotalsuppressedPktHdrBytes,
282 &nStandardPktHdrLen);
284 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
285 "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
286 nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
288 if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
290 return STATUS_SUCCESS;
292 TotalBytesAdded = nStandardPktHdrLen -
293 nTotalsuppressedPktHdrBytes - PHSI_LEN;
295 if (TotalBytesAdded) {
296 if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
297 skb_push(packet, TotalBytesAdded);
299 if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
300 BCM_DEBUG_PRINT(Adapter,
301 DBG_TYPE_PRINTK, 0, 0,
302 "cow failed in receive\n");
303 return STATUS_FAILURE;
306 skb_push(packet, TotalBytesAdded);
310 memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf,
314 return STATUS_SUCCESS;
317 void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
319 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
321 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
322 "Dumping Data Packet");
323 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
328 * Procedure: phs_init
330 * Description: This routine is responsible for allocating memory for classifier
334 * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules
335 * and PHS Rules , RX, TX buffer etc
338 * TRUE(1) -If allocation of memory was successful.
339 * FALSE -If allocation of memory fails.
341 int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,
342 struct bcm_mini_adapter *Adapter)
345 struct bcm_phs_table *pstServiceFlowTable;
347 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
348 "\nPHS:phs_init function");
350 if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
353 pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
354 kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
356 if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
357 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
359 "\nAllocation ServiceFlowPhsRulesTable failed");
363 pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
364 for (i = 0; i < MAX_SERVICEFLOWS; i++) {
365 struct bcm_phs_entry sServiceFlow =
366 pstServiceFlowTable->stSFList[i];
367 sServiceFlow.pstClassifierTable =
368 kzalloc(sizeof(struct bcm_phs_classifier_table),
370 if (!sServiceFlow.pstClassifierTable) {
371 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
372 DBG_LVL_ALL, "\nAllocation failed");
373 free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
374 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
379 pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
380 if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
381 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
382 DBG_LVL_ALL, "\nAllocation failed");
383 free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
384 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
388 pPhsdeviceExtension->UnCompressedRxBuffer =
389 kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
390 if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
391 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
392 DBG_LVL_ALL, "\nAllocation failed");
393 kfree(pPhsdeviceExtension->CompressedTxBuffer);
394 free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
395 pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
399 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
400 "\n phs_init Successful");
401 return STATUS_SUCCESS;
404 int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
406 if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
407 free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
408 pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
411 kfree(pPHSDeviceExt->CompressedTxBuffer);
412 pPHSDeviceExt->CompressedTxBuffer = NULL;
414 kfree(pPHSDeviceExt->UnCompressedRxBuffer);
415 pPHSDeviceExt->UnCompressedRxBuffer = NULL;
422 * PhsUpdateClassifierRule
424 * Routine Description:
425 * Exported function to add or modify a PHS Rule.
428 * IN void* pvContext - PHS Driver Specific Context
429 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
430 * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
431 * IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
438 ULONG PhsUpdateClassifierRule(IN void *pvContext,
440 IN B_UINT16 uiClsId ,
441 IN struct bcm_phs_rule *psPhsRule,
442 IN B_UINT8 u8AssociatedPHSI)
446 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
447 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
448 struct bcm_phs_extension *pDeviceExtension =
449 (struct bcm_phs_extension *)pvContext;
451 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
452 "PHS With Corr2 Changes\n");
454 if (pDeviceExtension == NULL) {
455 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
456 DBG_LVL_ALL, "Invalid Device Extension\n");
457 return ERR_PHS_INVALID_DEVICE_EXETENSION;
460 if (u8AssociatedPHSI == 0)
461 return ERR_PHS_INVALID_PHS_RULE;
463 /* Retrieve the SFID Entry Index for requested Service Flow */
464 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
465 uiVcid, &pstServiceFlowEntry);
467 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
468 /* This is a new SF. Create a mapping entry for this */
469 lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
470 pDeviceExtension->pstServiceFlowPhsRulesTable,
476 /* SF already Exists Add PHS Rule to existing SF */
477 lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
488 * Routine Description:
489 * Deletes the specified phs Rule within Vcid
492 * IN void* pvContext - PHS Driver Specific Context
493 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
494 * IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
501 ULONG PhsDeletePHSRule(IN void *pvContext,
505 UINT nSFIndex = 0, nClsidIndex = 0;
506 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
507 struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
508 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
509 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
510 struct bcm_phs_classifier_entry *curr_entry;
512 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
515 if (pDeviceExtension) {
516 /* Retrieve the SFID Entry Index for requested Service Flow */
517 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
518 uiVcid, &pstServiceFlowEntry);
520 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
521 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
522 DBG_LVL_ALL, "SFID Match Failed\n");
523 return ERR_SF_MATCH_FAIL;
526 pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
527 if (pstClassifierRulesTable) {
528 for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
529 curr_entry = &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
530 if (curr_entry->bUsed &&
531 curr_entry->pstPhsRule &&
532 (curr_entry->pstPhsRule->u8PHSI == u8PHSI)) {
534 if (curr_entry->pstPhsRule->u8RefCnt)
535 curr_entry->pstPhsRule->u8RefCnt--;
537 if (0 == curr_entry->pstPhsRule->u8RefCnt)
538 kfree(curr_entry->pstPhsRule);
542 sizeof(struct bcm_phs_classifier_entry));
551 * PhsDeleteClassifierRule
553 * Routine Description:
554 * Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
557 * IN void* pvContext - PHS Driver Specific Context
558 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
559 * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
566 ULONG PhsDeleteClassifierRule(IN void *pvContext,
570 UINT nSFIndex = 0, nClsidIndex = 0;
571 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
572 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
573 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
574 struct bcm_phs_extension *pDeviceExtension =
575 (struct bcm_phs_extension *)pvContext;
577 if (!pDeviceExtension)
580 /* Retrieve the SFID Entry Index for requested Service Flow */
581 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
582 uiVcid, &pstServiceFlowEntry);
583 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
584 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
585 DBG_LVL_ALL, "SFID Match Failed\n");
586 return ERR_SF_MATCH_FAIL;
590 GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
592 eActiveClassifierRuleContext,
593 &pstClassifierEntry);
595 if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
596 (!pstClassifierEntry->bUnclassifiedPHSRule)) {
597 if (pstClassifierEntry->pstPhsRule) {
598 if (pstClassifierEntry->pstPhsRule->u8RefCnt)
599 pstClassifierEntry->pstPhsRule->u8RefCnt--;
601 if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
602 kfree(pstClassifierEntry->pstPhsRule);
604 memset(pstClassifierEntry, 0,
605 sizeof(struct bcm_phs_classifier_entry));
609 GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
611 eOldClassifierRuleContext,
612 &pstClassifierEntry);
614 if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
615 (!pstClassifierEntry->bUnclassifiedPHSRule)) {
616 kfree(pstClassifierEntry->pstPhsRule);
617 memset(pstClassifierEntry, 0,
618 sizeof(struct bcm_phs_classifier_entry));
628 * Routine Description:
629 * Exported function to Delete a all PHS Rules for the SFID.
632 * IN void* pvContext - PHS Driver Specific Context
633 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
640 ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
642 UINT nSFIndex = 0, nClsidIndex = 0;
643 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
644 struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
645 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
646 struct bcm_phs_extension *pDeviceExtension =
647 (struct bcm_phs_extension *)pvContext;
648 struct bcm_phs_classifier_entry *curr_clsf_entry;
649 struct bcm_phs_classifier_entry *curr_rules_list;
651 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
654 if (!pDeviceExtension)
657 /* Retrieve the SFID Entry Index for requested Service Flow */
658 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
659 uiVcid, &pstServiceFlowEntry);
660 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
661 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
662 DBG_LVL_ALL, "SFID Match Failed\n");
663 return ERR_SF_MATCH_FAIL;
666 pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
667 if (pstClassifierRulesTable) {
668 for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
670 &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
673 &pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex];
675 if (curr_clsf_entry->pstPhsRule) {
677 if (curr_clsf_entry->pstPhsRule->u8RefCnt)
678 curr_clsf_entry->pstPhsRule->u8RefCnt--;
680 if (0 == curr_clsf_entry->pstPhsRule->u8RefCnt)
681 kfree(curr_clsf_entry->pstPhsRule);
683 curr_clsf_entry->pstPhsRule = NULL;
685 memset(curr_clsf_entry, 0,
686 sizeof(struct bcm_phs_classifier_entry));
687 if (curr_rules_list->pstPhsRule) {
689 if (curr_rules_list->pstPhsRule->u8RefCnt)
690 curr_rules_list->pstPhsRule->u8RefCnt--;
692 if (0 == curr_rules_list->pstPhsRule->u8RefCnt)
693 kfree(curr_rules_list->pstPhsRule);
695 curr_rules_list->pstPhsRule = NULL;
697 memset(curr_rules_list, 0,
698 sizeof(struct bcm_phs_classifier_entry));
701 pstServiceFlowEntry->bUsed = false;
702 pstServiceFlowEntry->uiVcid = 0;
711 * Routine Description:
712 * Exported function to compress the data using PHS.
715 * IN void* pvContext - PHS Driver Specific Context.
716 * IN B_UINT16 uiVcid - The Service Flow ID to which current
717 * packet header compression applies.
718 * IN UINT uiClsId - The Classifier ID to which current packet
719 * header compression applies.
720 * IN void *pvInputBuffer - The Input buffer containg packet header
722 * IN void *pvOutputBuffer - The output buffer returned by this
724 * IN UINT *pOldHeaderSize - The actual size of the header before PHS
725 * IN UINT *pNewHeaderSize - The new size of the header after applying
733 static ULONG PhsCompress(IN void *pvContext,
736 IN void *pvInputBuffer,
737 OUT void *pvOutputBuffer,
738 OUT UINT *pOldHeaderSize,
739 OUT UINT *pNewHeaderSize)
741 UINT nSFIndex = 0, nClsidIndex = 0;
742 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
743 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
744 struct bcm_phs_rule *pstPhsRule = NULL;
746 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
747 struct bcm_phs_extension *pDeviceExtension =
748 (struct bcm_phs_extension *)pvContext;
750 if (pDeviceExtension == NULL) {
751 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
752 "Invalid Device Extension\n");
753 lStatus = STATUS_PHS_NOCOMPRESSION;
757 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
758 "Suppressing header\n");
760 /* Retrieve the SFID Entry Index for requested Service Flow */
761 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
762 uiVcid, &pstServiceFlowEntry);
763 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
764 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
765 "SFID Match Failed\n");
766 lStatus = STATUS_PHS_NOCOMPRESSION;
770 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
771 uiClsId, eActiveClassifierRuleContext,
772 &pstClassifierEntry);
774 if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
775 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
776 "No PHS Rule Defined For Classifier\n");
777 lStatus = STATUS_PHS_NOCOMPRESSION;
781 /* get rule from SF id,Cls ID pair and proceed */
782 pstPhsRule = pstClassifierEntry->pstPhsRule;
783 if (!ValidatePHSRuleComplete(pstPhsRule)) {
784 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
785 "PHS Rule Defined For Classifier But Not Complete\n");
786 lStatus = STATUS_PHS_NOCOMPRESSION;
790 /* Compress Packet */
791 lStatus = phs_compress(pstPhsRule,
792 (PUCHAR)pvInputBuffer,
793 (PUCHAR)pvOutputBuffer,
797 if (lStatus == STATUS_PHS_COMPRESSED) {
798 pstPhsRule->PHSModifiedBytes +=
799 *pOldHeaderSize - *pNewHeaderSize - 1;
800 pstPhsRule->PHSModifiedNumPackets++;
802 pstPhsRule->PHSErrorNumPackets++;
811 * Routine Description:
812 * Exported function to restore the packet header in Rx path.
815 * IN void* pvContext - PHS Driver Specific Context.
816 * IN B_UINT16 uiVcid - The Service Flow ID to which current
817 * packet header restoration applies.
818 * IN void *pvInputBuffer - The Input buffer containg suppressed
820 * OUT void *pvOutputBuffer - The output buffer returned by this
821 * function after restoration
822 * OUT UINT *pHeaderSize - The packet header size after restoration
823 * is returned in this parameter.
830 static ULONG PhsDeCompress(IN void *pvContext,
832 IN void *pvInputBuffer,
833 OUT void *pvOutputBuffer,
834 OUT UINT *pInHeaderSize,
835 OUT UINT *pOutHeaderSize)
837 UINT nSFIndex = 0, nPhsRuleIndex = 0;
838 struct bcm_phs_entry *pstServiceFlowEntry = NULL;
839 struct bcm_phs_rule *pstPhsRule = NULL;
841 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
842 struct bcm_phs_extension *pDeviceExtension =
843 (struct bcm_phs_extension *)pvContext;
846 if (pDeviceExtension == NULL) {
847 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
848 DBG_LVL_ALL, "Invalid Device Extension\n");
849 return ERR_PHS_INVALID_DEVICE_EXETENSION;
852 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
853 "Restoring header\n");
855 phsi = *((unsigned char *)(pvInputBuffer));
856 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
857 "PHSI To Be Used For restore : %x\n", phsi);
858 if (phsi == UNCOMPRESSED_PACKET)
859 return STATUS_PHS_NOCOMPRESSION;
861 /* Retrieve the SFID Entry Index for requested Service Flow */
862 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
863 uiVcid, &pstServiceFlowEntry);
864 if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
865 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
867 "SFID Match Failed During Lookup\n");
868 return ERR_SF_MATCH_FAIL;
871 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
873 eActiveClassifierRuleContext,
875 if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
876 /* Phs Rule does not exist in active rules table. Lets try
877 * in the old rules table. */
878 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
880 eOldClassifierRuleContext,
882 if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
883 return ERR_PHSRULE_MATCH_FAIL;
886 *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
887 (PUCHAR)pvOutputBuffer,
891 pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
893 pstPhsRule->PHSModifiedNumPackets++;
894 return STATUS_PHS_COMPRESSED;
898 * Procedure: free_phs_serviceflow_rules
900 * Description: This routine is responsible for freeing memory allocated for
904 * rules - ptr to S_SERVICEFLOW_TABLE structure.
907 * Does not return any value.
909 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
912 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
913 struct bcm_phs_classifier_entry *curr_act_rules_list;
914 struct bcm_phs_classifier_entry *curr_old_rules_list;
916 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
919 if (!psServiceFlowRulesTable)
922 for (i = 0; i < MAX_SERVICEFLOWS; i++) {
923 struct bcm_phs_entry stServiceFlowEntry =
924 psServiceFlowRulesTable->stSFList[i];
925 struct bcm_phs_classifier_table *pstClassifierRulesTable =
926 stServiceFlowEntry.pstClassifierTable;
928 if (pstClassifierRulesTable) {
929 for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
930 curr_act_rules_list =
931 &pstClassifierRulesTable->stActivePhsRulesList[j];
933 curr_old_rules_list =
934 &pstClassifierRulesTable->stOldPhsRulesList[j];
936 if (curr_act_rules_list->pstPhsRule) {
938 if (curr_act_rules_list->pstPhsRule->u8RefCnt)
939 curr_act_rules_list->pstPhsRule->u8RefCnt--;
941 if (0 == curr_act_rules_list->pstPhsRule->u8RefCnt)
942 kfree(curr_act_rules_list->pstPhsRule);
944 curr_act_rules_list->pstPhsRule = NULL;
947 if (curr_old_rules_list->pstPhsRule) {
949 if (curr_old_rules_list->pstPhsRule->u8RefCnt)
950 curr_old_rules_list->pstPhsRule->u8RefCnt--;
952 if (0 == curr_old_rules_list->pstPhsRule->u8RefCnt)
953 kfree(curr_old_rules_list->pstPhsRule);
955 curr_old_rules_list->pstPhsRule = NULL;
958 kfree(pstClassifierRulesTable);
959 stServiceFlowEntry.pstClassifierTable =
960 pstClassifierRulesTable = NULL;
966 kfree(psServiceFlowRulesTable);
967 psServiceFlowRulesTable = NULL;
970 static bool ValidatePHSRuleComplete(IN const struct bcm_phs_rule *psPhsRule)
975 psPhsRule->u8PHSFLength);
978 UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
980 struct bcm_phs_entry **ppstServiceFlowEntry)
983 struct bcm_phs_entry *curr_sf_list;
985 for (i = 0; i < MAX_SERVICEFLOWS; i++) {
986 curr_sf_list = &psServiceFlowTable->stSFList[i];
987 if (curr_sf_list->bUsed && (curr_sf_list->uiVcid == uiVcid)) {
988 *ppstServiceFlowEntry = curr_sf_list;
993 *ppstServiceFlowEntry = NULL;
994 return PHS_INVALID_TABLE_INDEX;
997 static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
999 enum bcm_phs_classifier_context eClsContext,
1000 OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
1003 struct bcm_phs_classifier_entry *psClassifierRules = NULL;
1005 for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
1007 if (eClsContext == eActiveClassifierRuleContext)
1009 &pstClassifierTable->stActivePhsRulesList[i];
1012 &pstClassifierTable->stOldPhsRulesList[i];
1014 if (psClassifierRules->bUsed &&
1015 (psClassifierRules->uiClassifierRuleId == uiClsid)) {
1016 *ppstClassifierEntry = psClassifierRules;
1021 *ppstClassifierEntry = NULL;
1022 return PHS_INVALID_TABLE_INDEX;
1025 static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
1027 enum bcm_phs_classifier_context eClsContext,
1028 OUT struct bcm_phs_rule **ppstPhsRule)
1031 struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
1033 for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
1034 if (eClsContext == eActiveClassifierRuleContext)
1036 &pstClassifierTable->stActivePhsRulesList[i];
1039 &pstClassifierTable->stOldPhsRulesList[i];
1041 if (pstClassifierRule->bUsed &&
1042 (pstClassifierRule->u8PHSI == uiPHSI)) {
1043 *ppstPhsRule = pstClassifierRule->pstPhsRule;
1048 *ppstPhsRule = NULL;
1049 return PHS_INVALID_TABLE_INDEX;
1052 static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,
1053 IN B_UINT16 uiClsId,
1054 IN struct bcm_phs_table *psServiceFlowTable,
1055 struct bcm_phs_rule *psPhsRule,
1056 B_UINT8 u8AssociatedPHSI)
1058 struct bcm_phs_classifier_table *psaClassifiertable = NULL;
1061 bool bFreeEntryFound = false;
1062 struct bcm_phs_entry *curr_list;
1064 /* Check for a free entry in SFID table */
1065 for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
1066 curr_list = &psServiceFlowTable->stSFList[iSfIndex];
1067 if (!curr_list->bUsed) {
1068 bFreeEntryFound = TRUE;
1073 if (!bFreeEntryFound)
1074 return ERR_SFTABLE_FULL;
1076 psaClassifiertable = curr_list->pstClassifierTable;
1077 uiStatus = CreateClassifierPHSRule(uiClsId,
1080 eActiveClassifierRuleContext,
1082 if (uiStatus == PHS_SUCCESS) {
1083 /* Add entry at free index to the SF */
1084 curr_list->bUsed = TRUE;
1085 curr_list->uiVcid = uiVcid;
1091 static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
1092 IN B_UINT16 uiClsId,
1093 IN struct bcm_phs_entry *pstServiceFlowEntry,
1094 struct bcm_phs_rule *psPhsRule,
1095 B_UINT8 u8AssociatedPHSI)
1097 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
1098 UINT uiStatus = PHS_SUCCESS;
1099 UINT nClassifierIndex = 0;
1100 struct bcm_phs_classifier_table *psaClassifiertable = NULL;
1101 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1103 psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
1105 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
1108 /* Check if the supplied Classifier already exists */
1109 nClassifierIndex = GetClassifierEntry(
1110 pstServiceFlowEntry->pstClassifierTable,
1112 eActiveClassifierRuleContext,
1113 &pstClassifierEntry);
1115 if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
1117 * The Classifier doesn't exist. So its a new classifier being
1119 * Add new entry to associate PHS Rule to the Classifier
1122 uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
1124 eActiveClassifierRuleContext,
1130 * The Classifier exists.The PHS Rule for this classifier
1134 if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
1135 if (pstClassifierEntry->pstPhsRule == NULL)
1136 return ERR_PHS_INVALID_PHS_RULE;
1139 * This rule already exists if any fields are changed for this
1140 * PHS rule update them.
1142 /* If any part of PHSF is valid then we update PHSF */
1143 if (psPhsRule->u8PHSFLength) {
1145 memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
1150 if (psPhsRule->u8PHSFLength) {
1151 /* update PHSFLen */
1152 pstClassifierEntry->pstPhsRule->u8PHSFLength =
1153 psPhsRule->u8PHSFLength;
1156 if (psPhsRule->u8PHSMLength) {
1158 memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
1163 if (psPhsRule->u8PHSMLength) {
1164 /* update PHSM Len */
1165 pstClassifierEntry->pstPhsRule->u8PHSMLength =
1166 psPhsRule->u8PHSMLength;
1169 if (psPhsRule->u8PHSS) {
1171 pstClassifierEntry->pstPhsRule->u8PHSS =
1176 pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
1178 /* A new rule is being set for this classifier. */
1179 uiStatus = UpdateClassifierPHSRule(uiClsId,
1189 static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
1190 struct bcm_phs_classifier_table *psaClassifiertable,
1191 struct bcm_phs_rule *psPhsRule,
1192 enum bcm_phs_classifier_context eClsContext,
1193 B_UINT8 u8AssociatedPHSI)
1195 UINT iClassifierIndex = 0;
1196 bool bFreeEntryFound = false;
1197 struct bcm_phs_classifier_entry *psClassifierRules = NULL;
1198 UINT nStatus = PHS_SUCCESS;
1199 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1201 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
1202 "Inside CreateClassifierPHSRule");
1204 if (psaClassifiertable == NULL)
1205 return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
1207 if (eClsContext == eOldClassifierRuleContext) {
1209 * If An Old Entry for this classifier ID already exists in the
1210 * old rules table replace it.
1213 iClassifierIndex = GetClassifierEntry(psaClassifiertable,
1216 &psClassifierRules);
1218 if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
1220 * The Classifier already exists in the old rules table
1221 * Lets replace the old classifier with the new one.
1223 bFreeEntryFound = TRUE;
1227 if (!bFreeEntryFound) {
1228 /* Continue to search for a free location to add the rule */
1229 for (iClassifierIndex = 0; iClassifierIndex <
1230 MAX_PHSRULE_PER_SF; iClassifierIndex++) {
1231 if (eClsContext == eActiveClassifierRuleContext)
1232 psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
1234 psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1236 if (!psClassifierRules->bUsed) {
1237 bFreeEntryFound = TRUE;
1243 if (!bFreeEntryFound) {
1245 if (eClsContext == eActiveClassifierRuleContext)
1246 return ERR_CLSASSIFIER_TABLE_FULL;
1248 /* Lets replace the oldest rule if we are looking in
1250 if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
1251 psaClassifiertable->uiOldestPhsRuleIndex = 0;
1254 psaClassifiertable->uiOldestPhsRuleIndex;
1256 &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1258 (psaClassifiertable->uiOldestPhsRuleIndex)++;
1262 if (eClsContext == eOldClassifierRuleContext) {
1264 if (psClassifierRules->pstPhsRule == NULL) {
1266 psClassifierRules->pstPhsRule =
1267 kmalloc(sizeof(struct bcm_phs_rule),
1270 if (NULL == psClassifierRules->pstPhsRule)
1271 return ERR_PHSRULE_MEMALLOC_FAIL;
1274 psClassifierRules->bUsed = TRUE;
1275 psClassifierRules->uiClassifierRuleId = uiClsId;
1276 psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
1277 psClassifierRules->bUnclassifiedPHSRule =
1278 psPhsRule->bUnclassifiedPHSRule;
1280 /* Update The PHS rule */
1281 memcpy(psClassifierRules->pstPhsRule, psPhsRule,
1282 sizeof(struct bcm_phs_rule));
1284 nStatus = UpdateClassifierPHSRule(uiClsId,
1293 static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
1294 IN struct bcm_phs_classifier_entry *pstClassifierEntry,
1295 struct bcm_phs_classifier_table *psaClassifiertable,
1296 struct bcm_phs_rule *psPhsRule,
1297 B_UINT8 u8AssociatedPHSI)
1299 struct bcm_phs_rule *pstAddPhsRule = NULL;
1300 UINT nPhsRuleIndex = 0;
1301 bool bPHSRuleOrphaned = false;
1302 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1304 psPhsRule->u8RefCnt = 0;
1306 /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
1307 bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
1308 pstClassifierEntry->pstPhsRule);
1310 /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in
1311 * Classifier table for this SF */
1312 nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
1313 eActiveClassifierRuleContext,
1315 if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
1317 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1319 "\nAdding New PHSRuleEntry For Classifier");
1321 if (psPhsRule->u8PHSI == 0) {
1322 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1323 DBG_LVL_ALL, "\nError PHSI is Zero\n");
1324 return ERR_PHS_INVALID_PHS_RULE;
1327 /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for
1329 if (false == bPHSRuleOrphaned) {
1331 pstClassifierEntry->pstPhsRule =
1332 kmalloc(sizeof(struct bcm_phs_rule),
1334 if (NULL == pstClassifierEntry->pstPhsRule)
1335 return ERR_PHSRULE_MEMALLOC_FAIL;
1337 memcpy(pstClassifierEntry->pstPhsRule, psPhsRule,
1338 sizeof(struct bcm_phs_rule));
1340 /* Step 2.b PHS Rule Exists Tie uiClsId with the existing
1342 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1344 "\nTying Classifier to Existing PHS Rule");
1345 if (bPHSRuleOrphaned) {
1346 kfree(pstClassifierEntry->pstPhsRule);
1347 pstClassifierEntry->pstPhsRule = NULL;
1349 pstClassifierEntry->pstPhsRule = pstAddPhsRule;
1352 pstClassifierEntry->bUsed = TRUE;
1353 pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
1354 pstClassifierEntry->uiClassifierRuleId = uiClsId;
1355 pstClassifierEntry->pstPhsRule->u8RefCnt++;
1356 pstClassifierEntry->bUnclassifiedPHSRule =
1357 pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
1362 static bool DerefPhsRule(IN B_UINT16 uiClsId,
1363 struct bcm_phs_classifier_table *psaClassifiertable,
1364 struct bcm_phs_rule *pstPhsRule)
1366 if (pstPhsRule == NULL)
1369 if (pstPhsRule->u8RefCnt)
1370 pstPhsRule->u8RefCnt--;
1372 return (0 == pstPhsRule->u8RefCnt);
1375 static void dbg_print_st_cls_entry(struct bcm_mini_adapter *ad,
1376 struct bcm_phs_entry *st_serv_flow_entry,
1377 struct bcm_phs_classifier_entry *st_cls_entry)
1381 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X", st_serv_flow_entry->uiVcid);
1382 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X", st_cls_entry->uiClassifierRuleId);
1383 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X", st_cls_entry->u8PHSI);
1384 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
1385 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X", st_cls_entry->pstPhsRule->u8PHSI);
1386 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", st_cls_entry->pstPhsRule->u8PHSFLength);
1387 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
1389 for (k = 0 ; k < st_cls_entry->pstPhsRule->u8PHSFLength; k++)
1390 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", st_cls_entry->pstPhsRule->u8PHSF[k]);
1391 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X", st_cls_entry->pstPhsRule->u8PHSMLength);
1392 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
1394 for (k = 0; k < st_cls_entry->pstPhsRule->u8PHSMLength; k++)
1395 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", st_cls_entry->pstPhsRule->u8PHSM[k]);
1396 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", st_cls_entry->pstPhsRule->u8PHSS);
1397 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X", st_cls_entry->pstPhsRule->u8PHSV);
1398 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
1401 static void phsrules_per_sf_dbg_print(struct bcm_mini_adapter *ad,
1402 struct bcm_phs_entry *st_serv_flow_entry)
1405 struct bcm_phs_classifier_entry st_cls_entry;
1407 for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
1409 for (l = 0; l < 2; l++) {
1412 st_cls_entry = st_serv_flow_entry->pstClassifierTable->stActivePhsRulesList[j];
1413 if (st_cls_entry.bUsed)
1417 (DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
1418 "\n Active PHS Rule :\n");
1420 st_cls_entry = st_serv_flow_entry->pstClassifierTable->stOldPhsRulesList[j];
1421 if (st_cls_entry.bUsed)
1425 (DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
1426 "\n Old PHS Rule :\n");
1429 if (st_cls_entry.bUsed) {
1430 dbg_print_st_cls_entry(ad,
1438 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
1441 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1443 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,
1444 "\n Dumping PHS Rules :\n");
1446 for (i = 0; i < MAX_SERVICEFLOWS; i++) {
1448 struct bcm_phs_entry stServFlowEntry =
1449 pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
1451 if (!stServFlowEntry.bUsed)
1454 phsrules_per_sf_dbg_print(Adapter, &stServFlowEntry);
1459 * Procedure: phs_decompress
1461 * Description: This routine restores the static fields within the packet.
1464 * in_buf - ptr to incoming packet buffer.
1465 * out_buf - ptr to output buffer where the suppressed
1467 * decomp_phs_rules - ptr to PHS rule.
1468 * header_size - ptr to field which holds the phss or
1472 * size - The number of bytes of dynamic fields present with in the
1473 * incoming packet header.
1474 * 0 - If PHS rule is NULL.If PHSI is 0 indicateing packet as
1477 static int phs_decompress(unsigned char *in_buf,
1478 unsigned char *out_buf,
1479 struct bcm_phs_rule *decomp_phs_rules,
1483 struct bcm_phs_rule *tmp_memb;
1485 unsigned char *phsf, *phsm;
1486 int in_buf_len = *header_size - 1;
1487 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1491 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
1495 if (decomp_phs_rules == NULL)
1498 tmp_memb = decomp_phs_rules;
1500 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
1501 * "\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
1502 * header_size = tmp_memb->u8PHSFLength;
1504 phss = tmp_memb->u8PHSS;
1505 phsf = tmp_memb->u8PHSF;
1506 phsm = tmp_memb->u8PHSM;
1508 if (phss > MAX_PHS_LENGTHS)
1509 phss = MAX_PHS_LENGTHS;
1512 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
1514 * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
1516 while ((phss > 0) && (size < in_buf_len)) {
1517 bit = ((*phsm << i) & SUPPRESS);
1519 if (bit == SUPPRESS) {
1521 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
1523 "\nDECOMP:In phss %d phsf %d output %d",
1524 phss, *phsf, *out_buf);
1527 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
1529 "\nDECOMP:In phss %d input %d output %d",
1530 phss, *in_buf, *out_buf);
1538 *header_size = *header_size + 1;
1540 if (i > MAX_NO_BIT) {
1550 * Procedure: phs_compress
1552 * Description: This routine suppresses the static fields within the packet.
1553 * Before that it will verify the fields to be suppressed with the corresponding
1554 * fields in the phsf. For verification it checks the phsv field of PHS rule.
1555 * If set and verification succeeds it suppresses the field.If any one static
1556 * field is found different none of the static fields are suppressed then the
1557 * packet is sent as uncompressed packet with phsi=0.
1560 * phs_rule - ptr to PHS rule.
1561 * in_buf - ptr to incoming packet buffer.
1562 * out_buf - ptr to output buffer where the suppressed header is
1564 * header_size - ptr to field which holds the phss.
1567 * size - The number of bytes copied into the output buffer i.e
1569 * 0 - If PHS rule is NULL.If PHSV field is not set. If the
1570 * verification fails.
1572 static int phs_compress(struct bcm_phs_rule *phs_rule,
1573 unsigned char *in_buf,
1574 unsigned char *out_buf,
1576 UINT *new_header_size)
1578 unsigned char *old_addr = out_buf;
1580 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1582 if (phs_rule == NULL) {
1583 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1584 "\nphs_compress(): phs_rule null!");
1585 *out_buf = ZERO_PHSI;
1586 return STATUS_PHS_NOCOMPRESSION;
1589 if (phs_rule->u8PHSS <= *new_header_size)
1590 *header_size = phs_rule->u8PHSS;
1592 *header_size = *new_header_size;
1596 suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
1597 phs_rule->u8PHSM, phs_rule->u8PHSS,
1598 phs_rule->u8PHSV, new_header_size);
1600 if (suppress == STATUS_PHS_COMPRESSED) {
1601 *old_addr = (unsigned char)phs_rule->u8PHSI;
1602 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1603 "\nCOMP:In phs_compress phsi %d",
1606 *old_addr = ZERO_PHSI;
1607 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1608 "\nCOMP:In phs_compress PHSV Verification failed");
1615 * Procedure: verify_suppress_phsf
1617 * Description: This routine verifies the fields of the packet and if all the
1618 * static fields are equal it adds the phsi of that PHS rule.If any static
1619 * field differs it woun't suppress any field.
1622 * rules_set - ptr to classifier_rules.
1623 * in_buffer - ptr to incoming packet buffer.
1624 * out_buffer - ptr to output buffer where the suppressed header is copied.
1625 * phsf - ptr to phsf.
1626 * phsm - ptr to phsm.
1627 * phss - variable holding phss.
1630 * size - The number of bytes copied into the output buffer i.e dynamic
1632 * 0 - Packet has failed the verification.
1634 static int verify_suppress_phsf(unsigned char *in_buffer,
1635 unsigned char *out_buffer,
1636 unsigned char *phsf,
1637 unsigned char *phsm,
1640 UINT *new_header_size)
1642 unsigned int size = 0;
1644 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1646 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1647 "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
1649 if (phss > (*new_header_size))
1650 phss = *new_header_size;
1653 bit = ((*phsm << i) & SUPPRESS);
1654 if (bit == SUPPRESS) {
1655 if (*in_buffer != *phsf) {
1656 if (phsv == VERIFY) {
1657 BCM_DEBUG_PRINT(Adapter,
1661 "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",
1665 return STATUS_PHS_NOCOMPRESSION;
1668 BCM_DEBUG_PRINT(Adapter,
1672 "\nCOMP:In verify_phsf success for field %d buf %d phsf %d",
1677 *out_buffer = *in_buffer;
1678 BCM_DEBUG_PRINT(Adapter,
1682 "\nCOMP:In copying_header input %d out %d",
1694 if (i > MAX_NO_BIT) {
1699 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1700 "\nCOMP:In verify_phsf success");
1701 *new_header_size = size;
1702 return STATUS_PHS_COMPRESSED;