3 static UINT
CreateSFToClassifierRuleMapping(B_UINT16 uiVcid
, B_UINT16 uiClsId
, struct bcm_phs_table
*psServiceFlowTable
, struct bcm_phs_rule
*psPhsRule
, B_UINT8 u8AssociatedPHSI
);
5 static UINT
CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid
, B_UINT16 uiClsId
, struct bcm_phs_entry
*pstServiceFlowEntry
, struct bcm_phs_rule
*psPhsRule
, B_UINT8 u8AssociatedPHSI
);
7 static UINT
CreateClassifierPHSRule(B_UINT16 uiClsId
, struct bcm_phs_classifier_table
*psaClassifiertable
, struct bcm_phs_rule
*psPhsRule
, enum bcm_phs_classifier_context eClsContext
, B_UINT8 u8AssociatedPHSI
);
9 static UINT
UpdateClassifierPHSRule(B_UINT16 uiClsId
, struct bcm_phs_classifier_entry
*pstClassifierEntry
, struct bcm_phs_classifier_table
*psaClassifiertable
, struct bcm_phs_rule
*psPhsRule
, B_UINT8 u8AssociatedPHSI
);
11 static bool ValidatePHSRuleComplete(struct bcm_phs_rule
*psPhsRule
);
13 static bool DerefPhsRule(B_UINT16 uiClsId
, struct bcm_phs_classifier_table
*psaClassifiertable
, struct bcm_phs_rule
*pstPhsRule
);
15 static UINT
GetClassifierEntry(struct bcm_phs_classifier_table
*pstClassifierTable
, B_UINT32 uiClsid
, enum bcm_phs_classifier_context eClsContext
, struct bcm_phs_classifier_entry
**ppstClassifierEntry
);
17 static UINT
GetPhsRuleEntry(struct bcm_phs_classifier_table
*pstClassifierTable
, B_UINT32 uiPHSI
, enum bcm_phs_classifier_context eClsContext
, struct bcm_phs_rule
**ppstPhsRule
);
19 static void free_phs_serviceflow_rules(struct bcm_phs_table
*psServiceFlowRulesTable
);
21 static int phs_compress(struct bcm_phs_rule
*phs_members
, unsigned char *in_buf
,
22 unsigned char *out_buf
, unsigned int *header_size
, UINT
*new_header_size
);
24 static int verify_suppress_phsf(unsigned char *in_buffer
, unsigned char *out_buffer
,
25 unsigned char *phsf
, unsigned char *phsm
, unsigned int phss
, unsigned int phsv
, UINT
*new_header_size
);
27 static int phs_decompress(unsigned char *in_buf
, unsigned char *out_buf
,
28 struct bcm_phs_rule
*phs_rules
, UINT
*header_size
);
30 static ULONG
PhsCompress(void *pvContext
,
36 UINT
*pNewHeaderSize
);
38 static ULONG
PhsDeCompress(void *pvContext
,
43 UINT
*pOutHeaderSize
);
49 * Function: PHSTransmit
50 * Description: This routine handle PHS(Payload Header Suppression for Tx path.
51 * It extracts a fragment of the NDIS_PACKET containing the header
52 * to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
53 * The header data after suppression is copied back to the NDIS_PACKET.
55 * Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
56 * IN Packet - NDIS packet containing data to be transmitted
57 * IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
58 * identify PHS rule to be applied.
59 * B_UINT16 uiClassifierRuleID - Classifier Rule ID
60 * BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
62 * Return: STATUS_SUCCESS - If the send was successful.
63 * Other - If an error occurred.
66 int PHSTransmit(struct bcm_mini_adapter
*Adapter
,
67 struct sk_buff
**pPacket
,
69 B_UINT16 uiClassifierRuleID
,
70 bool bHeaderSuppressionEnabled
,
75 UINT unPHSPktHdrBytesCopied
= 0;
76 UINT unPhsOldHdrSize
= 0;
77 UINT unPHSNewPktHeaderLen
= 0;
78 /* Pointer to PHS IN Hdr Buffer */
79 PUCHAR pucPHSPktHdrInBuf
= Adapter
->stPhsTxContextInfo
.ucaHdrSuppressionInBuf
;
80 /* Pointer to PHS OUT Hdr Buffer */
81 PUCHAR pucPHSPktHdrOutBuf
= Adapter
->stPhsTxContextInfo
.ucaHdrSuppressionOutBuf
;
83 UINT BytesToRemove
= 0;
86 UINT numBytesCompressed
= 0;
87 struct sk_buff
*newPacket
= NULL
;
88 struct sk_buff
*Packet
= *pPacket
;
90 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "In PHSTransmit");
93 BytesToRemove
= ETH_HLEN
;
95 * Accumulate the header upto the size we support suppression
99 usPacketType
= ((struct ethhdr
*)(Packet
->data
))->h_proto
;
101 pucPHSPktHdrInBuf
= Packet
->data
+ BytesToRemove
;
102 /* considering data after ethernet header */
103 if ((*PacketLen
- BytesToRemove
) < MAX_PHS_LENGTHS
)
104 unPHSPktHdrBytesCopied
= (*PacketLen
- BytesToRemove
);
106 unPHSPktHdrBytesCopied
= MAX_PHS_LENGTHS
;
108 if ((unPHSPktHdrBytesCopied
> 0) &&
109 (unPHSPktHdrBytesCopied
<= MAX_PHS_LENGTHS
)) {
112 * Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
113 * Suppress only if IP Header and PHS Enabled For the Service Flow
115 if (((usPacketType
== ETHERNET_FRAMETYPE_IPV4
) ||
116 (usPacketType
== ETHERNET_FRAMETYPE_IPV6
)) &&
117 (bHeaderSuppressionEnabled
)) {
119 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nTrying to PHS Compress Using Classifier rule 0x%X", uiClassifierRuleID
);
120 unPHSNewPktHeaderLen
= unPHSPktHdrBytesCopied
;
121 ulPhsStatus
= PhsCompress(&Adapter
->stBCMPhsContext
,
127 &unPHSNewPktHeaderLen
);
128 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nPHS Old header Size : %d New Header Size %d\n", unPhsOldHdrSize
, unPHSNewPktHeaderLen
);
130 if (unPHSNewPktHeaderLen
== unPhsOldHdrSize
) {
132 if (ulPhsStatus
== STATUS_PHS_COMPRESSED
)
133 bPHSI
= *pucPHSPktHdrOutBuf
;
135 ulPhsStatus
= STATUS_PHS_NOCOMPRESSION
;
138 if (ulPhsStatus
== STATUS_PHS_COMPRESSED
) {
140 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "PHS Sending packet Compressed");
142 if (skb_cloned(Packet
)) {
143 newPacket
= skb_copy(Packet
, GFP_ATOMIC
);
145 if (newPacket
== NULL
)
146 return STATUS_FAILURE
;
148 dev_kfree_skb(Packet
);
149 *pPacket
= Packet
= newPacket
;
150 pucPHSPktHdrInBuf
= Packet
->data
+ BytesToRemove
;
153 numBytesCompressed
= unPhsOldHdrSize
- (unPHSNewPktHeaderLen
+ PHSI_LEN
);
155 memcpy(pucPHSPktHdrInBuf
+ numBytesCompressed
, pucPHSPktHdrOutBuf
, unPHSNewPktHeaderLen
+ PHSI_LEN
);
156 memcpy(Packet
->data
+ numBytesCompressed
, Packet
->data
, BytesToRemove
);
157 skb_pull(Packet
, numBytesCompressed
);
159 return STATUS_SUCCESS
;
161 /* if one byte headroom is not available, increase it through skb_cow */
162 if (!(skb_headroom(Packet
) > 0)) {
164 if (skb_cow(Packet
, 1)) {
165 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_PRINTK
, 0, 0, "SKB Cow Failed\n");
166 return STATUS_FAILURE
;
172 * CAUTION: The MAC Header is getting corrupted
173 * here for IP CS - can be saved by copying 14
174 * Bytes. not needed .... hence corrupting it.
176 *(Packet
->data
+ BytesToRemove
) = bPHSI
;
177 return STATUS_SUCCESS
;
181 if (!bHeaderSuppressionEnabled
)
182 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nHeader Suppression Disabled For SF: No PHS\n");
184 return STATUS_SUCCESS
;
188 /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); */
189 return STATUS_SUCCESS
;
192 int PHSReceive(struct bcm_mini_adapter
*Adapter
,
194 struct sk_buff
*packet
,
196 UCHAR
*pucEthernetHdr
,
197 UINT bHeaderSuppressionEnabled
)
199 u32 nStandardPktHdrLen
= 0;
200 u32 nTotalsuppressedPktHdrBytes
= 0;
202 PUCHAR pucInBuff
= NULL
;
203 UINT TotalBytesAdded
= 0;
205 if (!bHeaderSuppressionEnabled
) {
206 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "\nPhs Disabled for incoming packet");
210 pucInBuff
= packet
->data
;
212 /* Restore PHS suppressed header */
213 nStandardPktHdrLen
= packet
->len
;
214 ulPhsStatus
= PhsDeCompress(&Adapter
->stBCMPhsContext
,
217 Adapter
->ucaPHSPktRestoreBuf
,
218 &nTotalsuppressedPktHdrBytes
,
219 &nStandardPktHdrLen
);
221 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
222 nTotalsuppressedPktHdrBytes
, nStandardPktHdrLen
);
224 if (ulPhsStatus
!= STATUS_PHS_COMPRESSED
) {
226 return STATUS_SUCCESS
;
228 TotalBytesAdded
= nStandardPktHdrLen
- nTotalsuppressedPktHdrBytes
- PHSI_LEN
;
230 if (TotalBytesAdded
) {
231 if (skb_headroom(packet
) >= (SKB_RESERVE_ETHERNET_HEADER
+ TotalBytesAdded
))
232 skb_push(packet
, TotalBytesAdded
);
234 if (skb_cow(packet
, skb_headroom(packet
) + TotalBytesAdded
)) {
235 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_PRINTK
, 0, 0, "cow failed in receive\n");
236 return STATUS_FAILURE
;
239 skb_push(packet
, TotalBytesAdded
);
243 memcpy(packet
->data
, Adapter
->ucaPHSPktRestoreBuf
, nStandardPktHdrLen
);
246 return STATUS_SUCCESS
;
249 void DumpFullPacket(UCHAR
*pBuf
, UINT nPktLen
)
251 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
253 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Dumping Data Packet");
254 BCM_DEBUG_PRINT_BUFFER(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, pBuf
, nPktLen
);
258 * Procedure: phs_init
260 * Description: This routine is responsible for allocating memory for classifier and
264 * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
267 * TRUE(1) -If allocation of memory was successful.
268 * FALSE -If allocation of memory fails.
270 int phs_init(struct bcm_phs_extension
*pPhsdeviceExtension
, struct bcm_mini_adapter
*Adapter
)
273 struct bcm_phs_table
*pstServiceFlowTable
;
275 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nPHS:phs_init function");
277 if (pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
)
280 pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
= kzalloc(sizeof(struct bcm_phs_table
), GFP_KERNEL
);
282 if (!pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
) {
283 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nAllocation ServiceFlowPhsRulesTable failed");
287 pstServiceFlowTable
= pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
;
288 for (i
= 0; i
< MAX_SERVICEFLOWS
; i
++) {
289 struct bcm_phs_entry sServiceFlow
= pstServiceFlowTable
->stSFList
[i
];
290 sServiceFlow
.pstClassifierTable
= kzalloc(sizeof(struct bcm_phs_classifier_table
), GFP_KERNEL
);
291 if (!sServiceFlow
.pstClassifierTable
) {
292 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nAllocation failed");
293 free_phs_serviceflow_rules(pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
);
294 pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
= NULL
;
299 pPhsdeviceExtension
->CompressedTxBuffer
= kmalloc(PHS_BUFFER_SIZE
, GFP_KERNEL
);
300 if (pPhsdeviceExtension
->CompressedTxBuffer
== NULL
) {
301 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nAllocation failed");
302 free_phs_serviceflow_rules(pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
);
303 pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
= NULL
;
307 pPhsdeviceExtension
->UnCompressedRxBuffer
= kmalloc(PHS_BUFFER_SIZE
, GFP_KERNEL
);
308 if (pPhsdeviceExtension
->UnCompressedRxBuffer
== NULL
) {
309 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nAllocation failed");
310 kfree(pPhsdeviceExtension
->CompressedTxBuffer
);
311 free_phs_serviceflow_rules(pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
);
312 pPhsdeviceExtension
->pstServiceFlowPhsRulesTable
= NULL
;
316 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\n phs_init Successful");
317 return STATUS_SUCCESS
;
320 int PhsCleanup(IN
struct bcm_phs_extension
*pPHSDeviceExt
)
322 if (pPHSDeviceExt
->pstServiceFlowPhsRulesTable
) {
323 free_phs_serviceflow_rules(pPHSDeviceExt
->pstServiceFlowPhsRulesTable
);
324 pPHSDeviceExt
->pstServiceFlowPhsRulesTable
= NULL
;
327 kfree(pPHSDeviceExt
->CompressedTxBuffer
);
328 pPHSDeviceExt
->CompressedTxBuffer
= NULL
;
330 kfree(pPHSDeviceExt
->UnCompressedRxBuffer
);
331 pPHSDeviceExt
->UnCompressedRxBuffer
= NULL
;
338 * PhsUpdateClassifierRule
340 * Routine Description:
341 * Exported function to add or modify a PHS Rule.
344 * IN void* pvContext - PHS Driver Specific Context
345 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
346 * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
347 * IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
354 ULONG
PhsUpdateClassifierRule(IN
void *pvContext
,
356 IN B_UINT16 uiClsId
,
357 IN
struct bcm_phs_rule
*psPhsRule
,
358 IN B_UINT8 u8AssociatedPHSI
)
362 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
363 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
364 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
366 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "PHS With Corr2 Changes\n");
368 if (pDeviceExtension
== NULL
) {
369 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "Invalid Device Extension\n");
370 return ERR_PHS_INVALID_DEVICE_EXETENSION
;
373 if (u8AssociatedPHSI
== 0)
374 return ERR_PHS_INVALID_PHS_RULE
;
376 /* Retrieve the SFID Entry Index for requested Service Flow */
377 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
,
378 uiVcid
, &pstServiceFlowEntry
);
380 if (nSFIndex
== PHS_INVALID_TABLE_INDEX
) {
381 /* This is a new SF. Create a mapping entry for this */
382 lStatus
= CreateSFToClassifierRuleMapping(uiVcid
, uiClsId
,
383 pDeviceExtension
->pstServiceFlowPhsRulesTable
, psPhsRule
, u8AssociatedPHSI
);
387 /* SF already Exists Add PHS Rule to existing SF */
388 lStatus
= CreateClassiferToPHSRuleMapping(uiVcid
, uiClsId
,
389 pstServiceFlowEntry
, psPhsRule
, u8AssociatedPHSI
);
397 * Routine Description:
398 * Deletes the specified phs Rule within Vcid
401 * IN void* pvContext - PHS Driver Specific Context
402 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
403 * IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
410 ULONG
PhsDeletePHSRule(IN
void *pvContext
, IN B_UINT16 uiVcid
, IN B_UINT8 u8PHSI
)
413 UINT nSFIndex
= 0, nClsidIndex
= 0;
414 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
415 struct bcm_phs_classifier_table
*pstClassifierRulesTable
= NULL
;
416 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
417 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
419 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "======>\n");
421 if (pDeviceExtension
) {
422 /* Retrieve the SFID Entry Index for requested Service Flow */
423 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
, uiVcid
, &pstServiceFlowEntry
);
425 if (nSFIndex
== PHS_INVALID_TABLE_INDEX
) {
426 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "SFID Match Failed\n");
427 return ERR_SF_MATCH_FAIL
;
430 pstClassifierRulesTable
= pstServiceFlowEntry
->pstClassifierTable
;
431 if (pstClassifierRulesTable
) {
432 for (nClsidIndex
= 0; nClsidIndex
< MAX_PHSRULE_PER_SF
; nClsidIndex
++) {
433 if (pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].bUsed
&& pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
) {
434 if (pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8PHSI
== u8PHSI
) {
436 if (pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
437 pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
--;
439 if (0 == pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
440 kfree(pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
);
442 memset(&pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
], 0,
443 sizeof(struct bcm_phs_classifier_entry
));
453 * PhsDeleteClassifierRule
455 * Routine Description:
456 * Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
459 * IN void* pvContext - PHS Driver Specific Context
460 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
461 * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
468 ULONG
PhsDeleteClassifierRule(IN
void *pvContext
, IN B_UINT16 uiVcid
, IN B_UINT16 uiClsId
)
471 UINT nSFIndex
= 0, nClsidIndex
= 0;
472 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
473 struct bcm_phs_classifier_entry
*pstClassifierEntry
= NULL
;
474 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
475 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
477 if (pDeviceExtension
) {
478 /* Retrieve the SFID Entry Index for requested Service Flow */
479 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
, uiVcid
, &pstServiceFlowEntry
);
480 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 nClsidIndex
= GetClassifierEntry(pstServiceFlowEntry
->pstClassifierTable
,
486 uiClsId
, eActiveClassifierRuleContext
, &pstClassifierEntry
);
488 if ((nClsidIndex
!= PHS_INVALID_TABLE_INDEX
) && (!pstClassifierEntry
->bUnclassifiedPHSRule
)) {
489 if (pstClassifierEntry
->pstPhsRule
) {
490 if (pstClassifierEntry
->pstPhsRule
->u8RefCnt
)
491 pstClassifierEntry
->pstPhsRule
->u8RefCnt
--;
493 if (0 == pstClassifierEntry
->pstPhsRule
->u8RefCnt
)
494 kfree(pstClassifierEntry
->pstPhsRule
);
496 memset(pstClassifierEntry
, 0, sizeof(struct bcm_phs_classifier_entry
));
499 nClsidIndex
= GetClassifierEntry(pstServiceFlowEntry
->pstClassifierTable
,
500 uiClsId
, eOldClassifierRuleContext
, &pstClassifierEntry
);
502 if ((nClsidIndex
!= PHS_INVALID_TABLE_INDEX
) && (!pstClassifierEntry
->bUnclassifiedPHSRule
)) {
503 kfree(pstClassifierEntry
->pstPhsRule
);
504 memset(pstClassifierEntry
, 0, sizeof(struct bcm_phs_classifier_entry
));
513 * Routine Description:
514 * Exported function to Delete a all PHS Rules for the SFID.
517 * IN void* pvContext - PHS Driver Specific Context
518 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
525 ULONG
PhsDeleteSFRules(IN
void *pvContext
, IN B_UINT16 uiVcid
)
528 UINT nSFIndex
= 0, nClsidIndex
= 0;
529 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
530 struct bcm_phs_classifier_table
*pstClassifierRulesTable
= NULL
;
531 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
532 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
534 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "====>\n");
536 if (pDeviceExtension
) {
537 /* Retrieve the SFID Entry Index for requested Service Flow */
538 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
,
539 uiVcid
, &pstServiceFlowEntry
);
540 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 pstClassifierRulesTable
= pstServiceFlowEntry
->pstClassifierTable
;
546 if (pstClassifierRulesTable
) {
547 for (nClsidIndex
= 0; nClsidIndex
< MAX_PHSRULE_PER_SF
; nClsidIndex
++) {
548 if (pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
) {
550 if (pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
551 pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
--;
553 if (0 == pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
554 kfree(pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
);
556 pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
].pstPhsRule
= NULL
;
558 memset(&pstClassifierRulesTable
->stActivePhsRulesList
[nClsidIndex
], 0, sizeof(struct bcm_phs_classifier_entry
));
559 if (pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
) {
561 if (pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
562 pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
--;
564 if (0 == pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
->u8RefCnt
)
565 kfree(pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
);
567 pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
].pstPhsRule
= NULL
;
569 memset(&pstClassifierRulesTable
->stOldPhsRulesList
[nClsidIndex
], 0, sizeof(struct bcm_phs_classifier_entry
));
572 pstServiceFlowEntry
->bUsed
= false;
573 pstServiceFlowEntry
->uiVcid
= 0;
582 * Routine Description:
583 * Exported function to compress the data using PHS.
586 * IN void* pvContext - PHS Driver Specific Context.
587 * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
588 * IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
589 * IN void *pvInputBuffer - The Input buffer containg packet header data
590 * IN void *pvOutputBuffer - The output buffer returned by this function after PHS
591 * IN UINT *pOldHeaderSize - The actual size of the header before PHS
592 * IN UINT *pNewHeaderSize - The new size of the header after applying PHS
599 static ULONG
PhsCompress(IN
void *pvContext
,
602 IN
void *pvInputBuffer
,
603 OUT
void *pvOutputBuffer
,
604 OUT UINT
*pOldHeaderSize
,
605 OUT UINT
*pNewHeaderSize
)
607 UINT nSFIndex
= 0, nClsidIndex
= 0;
608 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
609 struct bcm_phs_classifier_entry
*pstClassifierEntry
= NULL
;
610 struct bcm_phs_rule
*pstPhsRule
= NULL
;
612 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
613 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
615 if (pDeviceExtension
== NULL
) {
616 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "Invalid Device Extension\n");
617 lStatus
= STATUS_PHS_NOCOMPRESSION
;
621 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "Suppressing header\n");
623 /* Retrieve the SFID Entry Index for requested Service Flow */
624 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
,
625 uiVcid
, &pstServiceFlowEntry
);
626 if (nSFIndex
== PHS_INVALID_TABLE_INDEX
) {
627 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "SFID Match Failed\n");
628 lStatus
= STATUS_PHS_NOCOMPRESSION
;
632 nClsidIndex
= GetClassifierEntry(pstServiceFlowEntry
->pstClassifierTable
,
633 uiClsId
, eActiveClassifierRuleContext
, &pstClassifierEntry
);
635 if (nClsidIndex
== PHS_INVALID_TABLE_INDEX
) {
636 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "No PHS Rule Defined For Classifier\n");
637 lStatus
= STATUS_PHS_NOCOMPRESSION
;
641 /* get rule from SF id,Cls ID pair and proceed */
642 pstPhsRule
= pstClassifierEntry
->pstPhsRule
;
643 if (!ValidatePHSRuleComplete(pstPhsRule
)) {
644 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "PHS Rule Defined For Classifier But Not Complete\n");
645 lStatus
= STATUS_PHS_NOCOMPRESSION
;
649 /* Compress Packet */
650 lStatus
= phs_compress(pstPhsRule
, (PUCHAR
)pvInputBuffer
,
651 (PUCHAR
)pvOutputBuffer
, pOldHeaderSize
, pNewHeaderSize
);
653 if (lStatus
== STATUS_PHS_COMPRESSED
) {
654 pstPhsRule
->PHSModifiedBytes
+= *pOldHeaderSize
- *pNewHeaderSize
- 1;
655 pstPhsRule
->PHSModifiedNumPackets
++;
657 pstPhsRule
->PHSErrorNumPackets
++;
665 * Routine Description:
666 * Exported function to restore the packet header in Rx path.
669 * IN void* pvContext - PHS Driver Specific Context.
670 * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
671 * IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
672 * OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
673 * OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
680 static ULONG
PhsDeCompress(IN
void *pvContext
,
682 IN
void *pvInputBuffer
,
683 OUT
void *pvOutputBuffer
,
684 OUT UINT
*pInHeaderSize
,
685 OUT UINT
*pOutHeaderSize
)
687 UINT nSFIndex
= 0, nPhsRuleIndex
= 0;
688 struct bcm_phs_entry
*pstServiceFlowEntry
= NULL
;
689 struct bcm_phs_rule
*pstPhsRule
= NULL
;
691 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
692 struct bcm_phs_extension
*pDeviceExtension
= (struct bcm_phs_extension
*)pvContext
;
695 if (pDeviceExtension
== NULL
) {
696 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "Invalid Device Extension\n");
697 return ERR_PHS_INVALID_DEVICE_EXETENSION
;
700 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "Restoring header\n");
702 phsi
= *((unsigned char *)(pvInputBuffer
));
703 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "PHSI To Be Used For restore : %x\n", phsi
);
704 if (phsi
== UNCOMPRESSED_PACKET
)
705 return STATUS_PHS_NOCOMPRESSION
;
707 /* Retrieve the SFID Entry Index for requested Service Flow */
708 nSFIndex
= GetServiceFlowEntry(pDeviceExtension
->pstServiceFlowPhsRulesTable
,
709 uiVcid
, &pstServiceFlowEntry
);
710 if (nSFIndex
== PHS_INVALID_TABLE_INDEX
) {
711 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "SFID Match Failed During Lookup\n");
712 return ERR_SF_MATCH_FAIL
;
715 nPhsRuleIndex
= GetPhsRuleEntry(pstServiceFlowEntry
->pstClassifierTable
, phsi
,
716 eActiveClassifierRuleContext
, &pstPhsRule
);
717 if (nPhsRuleIndex
== PHS_INVALID_TABLE_INDEX
) {
718 /* Phs Rule does not exist in active rules table. Lets try in the old rules table. */
719 nPhsRuleIndex
= GetPhsRuleEntry(pstServiceFlowEntry
->pstClassifierTable
,
720 phsi
, eOldClassifierRuleContext
, &pstPhsRule
);
721 if (nPhsRuleIndex
== PHS_INVALID_TABLE_INDEX
)
722 return ERR_PHSRULE_MATCH_FAIL
;
725 *pInHeaderSize
= phs_decompress((PUCHAR
)pvInputBuffer
,
726 (PUCHAR
)pvOutputBuffer
, pstPhsRule
, pOutHeaderSize
);
728 pstPhsRule
->PHSModifiedBytes
+= *pOutHeaderSize
- *pInHeaderSize
- 1;
730 pstPhsRule
->PHSModifiedNumPackets
++;
731 return STATUS_PHS_COMPRESSED
;
735 * Procedure: free_phs_serviceflow_rules
737 * Description: This routine is responsible for freeing memory allocated for PHS rules.
740 * rules - ptr to S_SERVICEFLOW_TABLE structure.
743 * Does not return any value.
745 static void free_phs_serviceflow_rules(struct bcm_phs_table
*psServiceFlowRulesTable
)
748 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
750 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "=======>\n");
752 if (psServiceFlowRulesTable
) {
753 for (i
= 0; i
< MAX_SERVICEFLOWS
; i
++) {
754 struct bcm_phs_entry stServiceFlowEntry
= psServiceFlowRulesTable
->stSFList
[i
];
755 struct bcm_phs_classifier_table
*pstClassifierRulesTable
= stServiceFlowEntry
.pstClassifierTable
;
757 if (pstClassifierRulesTable
) {
758 for (j
= 0; j
< MAX_PHSRULE_PER_SF
; j
++) {
759 if (pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
) {
761 if (pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
->u8RefCnt
)
762 pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
->u8RefCnt
--;
764 if (0 == pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
->u8RefCnt
)
765 kfree(pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
);
767 pstClassifierRulesTable
->stActivePhsRulesList
[j
].pstPhsRule
= NULL
;
770 if (pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
) {
772 if (pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
->u8RefCnt
)
773 pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
->u8RefCnt
--;
775 if (0 == pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
->u8RefCnt
)
776 kfree(pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
);
778 pstClassifierRulesTable
->stOldPhsRulesList
[j
].pstPhsRule
= NULL
;
781 kfree(pstClassifierRulesTable
);
782 stServiceFlowEntry
.pstClassifierTable
= pstClassifierRulesTable
= NULL
;
787 kfree(psServiceFlowRulesTable
);
788 psServiceFlowRulesTable
= NULL
;
791 static bool ValidatePHSRuleComplete(IN
struct bcm_phs_rule
*psPhsRule
)
794 if (!psPhsRule
->u8PHSI
) {
795 /* PHSI is not valid */
799 if (!psPhsRule
->u8PHSS
) {
800 /* PHSS Is Undefined */
804 /* Check if PHSF is defines for the PHS Rule */
805 if (!psPhsRule
->u8PHSFLength
) /* If any part of PHSF is valid then Rule contains valid PHSF */
813 UINT
GetServiceFlowEntry(IN
struct bcm_phs_table
*psServiceFlowTable
,
815 struct bcm_phs_entry
**ppstServiceFlowEntry
)
819 for (i
= 0; i
< MAX_SERVICEFLOWS
; i
++) {
820 if (psServiceFlowTable
->stSFList
[i
].bUsed
) {
821 if (psServiceFlowTable
->stSFList
[i
].uiVcid
== uiVcid
) {
822 *ppstServiceFlowEntry
= &psServiceFlowTable
->stSFList
[i
];
828 *ppstServiceFlowEntry
= NULL
;
829 return PHS_INVALID_TABLE_INDEX
;
832 static UINT
GetClassifierEntry(IN
struct bcm_phs_classifier_table
*pstClassifierTable
,
833 IN B_UINT32 uiClsid
, enum bcm_phs_classifier_context eClsContext
,
834 OUT
struct bcm_phs_classifier_entry
**ppstClassifierEntry
)
837 struct bcm_phs_classifier_entry
*psClassifierRules
= NULL
;
839 for (i
= 0; i
< MAX_PHSRULE_PER_SF
; i
++) {
841 if (eClsContext
== eActiveClassifierRuleContext
)
842 psClassifierRules
= &pstClassifierTable
->stActivePhsRulesList
[i
];
844 psClassifierRules
= &pstClassifierTable
->stOldPhsRulesList
[i
];
846 if (psClassifierRules
->bUsed
) {
847 if (psClassifierRules
->uiClassifierRuleId
== uiClsid
) {
848 *ppstClassifierEntry
= psClassifierRules
;
854 *ppstClassifierEntry
= NULL
;
855 return PHS_INVALID_TABLE_INDEX
;
858 static UINT
GetPhsRuleEntry(IN
struct bcm_phs_classifier_table
*pstClassifierTable
,
859 IN B_UINT32 uiPHSI
, enum bcm_phs_classifier_context eClsContext
,
860 OUT
struct bcm_phs_rule
**ppstPhsRule
)
863 struct bcm_phs_classifier_entry
*pstClassifierRule
= NULL
;
865 for (i
= 0; i
< MAX_PHSRULE_PER_SF
; i
++) {
866 if (eClsContext
== eActiveClassifierRuleContext
)
867 pstClassifierRule
= &pstClassifierTable
->stActivePhsRulesList
[i
];
869 pstClassifierRule
= &pstClassifierTable
->stOldPhsRulesList
[i
];
871 if (pstClassifierRule
->bUsed
) {
872 if (pstClassifierRule
->u8PHSI
== uiPHSI
) {
873 *ppstPhsRule
= pstClassifierRule
->pstPhsRule
;
880 return PHS_INVALID_TABLE_INDEX
;
883 static UINT
CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid
, IN B_UINT16 uiClsId
,
884 IN
struct bcm_phs_table
*psServiceFlowTable
,
885 struct bcm_phs_rule
*psPhsRule
,
886 B_UINT8 u8AssociatedPHSI
)
888 struct bcm_phs_classifier_table
*psaClassifiertable
= NULL
;
891 bool bFreeEntryFound
= false;
893 /* Check for a free entry in SFID table */
894 for (iSfIndex
= 0; iSfIndex
< MAX_SERVICEFLOWS
; iSfIndex
++) {
895 if (!psServiceFlowTable
->stSFList
[iSfIndex
].bUsed
) {
896 bFreeEntryFound
= TRUE
;
901 if (!bFreeEntryFound
)
902 return ERR_SFTABLE_FULL
;
904 psaClassifiertable
= psServiceFlowTable
->stSFList
[iSfIndex
].pstClassifierTable
;
905 uiStatus
= CreateClassifierPHSRule(uiClsId
, psaClassifiertable
, psPhsRule
,
906 eActiveClassifierRuleContext
, u8AssociatedPHSI
);
907 if (uiStatus
== PHS_SUCCESS
) {
908 /* Add entry at free index to the SF */
909 psServiceFlowTable
->stSFList
[iSfIndex
].bUsed
= TRUE
;
910 psServiceFlowTable
->stSFList
[iSfIndex
].uiVcid
= uiVcid
;
916 static UINT
CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid
,
918 IN
struct bcm_phs_entry
*pstServiceFlowEntry
,
919 struct bcm_phs_rule
*psPhsRule
,
920 B_UINT8 u8AssociatedPHSI
)
922 struct bcm_phs_classifier_entry
*pstClassifierEntry
= NULL
;
923 UINT uiStatus
= PHS_SUCCESS
;
924 UINT nClassifierIndex
= 0;
925 struct bcm_phs_classifier_table
*psaClassifiertable
= NULL
;
926 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
928 psaClassifiertable
= pstServiceFlowEntry
->pstClassifierTable
;
930 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "==>");
932 /* Check if the supplied Classifier already exists */
933 nClassifierIndex
= GetClassifierEntry(
934 pstServiceFlowEntry
->pstClassifierTable
,
936 eActiveClassifierRuleContext
,
937 &pstClassifierEntry
);
939 if (nClassifierIndex
== PHS_INVALID_TABLE_INDEX
) {
941 * The Classifier doesn't exist. So its a new classifier being added.
942 * Add new entry to associate PHS Rule to the Classifier
945 uiStatus
= CreateClassifierPHSRule(uiClsId
, psaClassifiertable
,
947 eActiveClassifierRuleContext
,
953 * The Classifier exists.The PHS Rule for this classifier
957 if (pstClassifierEntry
->u8PHSI
== psPhsRule
->u8PHSI
) {
958 if (pstClassifierEntry
->pstPhsRule
== NULL
)
959 return ERR_PHS_INVALID_PHS_RULE
;
962 * This rule already exists if any fields are changed for this PHS
965 /* If any part of PHSF is valid then we update PHSF */
966 if (psPhsRule
->u8PHSFLength
) {
968 memcpy(pstClassifierEntry
->pstPhsRule
->u8PHSF
,
969 psPhsRule
->u8PHSF
, MAX_PHS_LENGTHS
);
972 if (psPhsRule
->u8PHSFLength
) {
974 pstClassifierEntry
->pstPhsRule
->u8PHSFLength
= psPhsRule
->u8PHSFLength
;
977 if (psPhsRule
->u8PHSMLength
) {
979 memcpy(pstClassifierEntry
->pstPhsRule
->u8PHSM
,
980 psPhsRule
->u8PHSM
, MAX_PHS_LENGTHS
);
983 if (psPhsRule
->u8PHSMLength
) {
984 /* update PHSM Len */
985 pstClassifierEntry
->pstPhsRule
->u8PHSMLength
=
986 psPhsRule
->u8PHSMLength
;
989 if (psPhsRule
->u8PHSS
) {
991 pstClassifierEntry
->pstPhsRule
->u8PHSS
= psPhsRule
->u8PHSS
;
995 pstClassifierEntry
->pstPhsRule
->u8PHSV
= psPhsRule
->u8PHSV
;
997 /* A new rule is being set for this classifier. */
998 uiStatus
= UpdateClassifierPHSRule(uiClsId
, pstClassifierEntry
,
999 psaClassifiertable
, psPhsRule
, u8AssociatedPHSI
);
1005 static UINT
CreateClassifierPHSRule(IN B_UINT16 uiClsId
,
1006 struct bcm_phs_classifier_table
*psaClassifiertable
,
1007 struct bcm_phs_rule
*psPhsRule
,
1008 enum bcm_phs_classifier_context eClsContext
,
1009 B_UINT8 u8AssociatedPHSI
)
1011 UINT iClassifierIndex
= 0;
1012 bool bFreeEntryFound
= false;
1013 struct bcm_phs_classifier_entry
*psClassifierRules
= NULL
;
1014 UINT nStatus
= PHS_SUCCESS
;
1015 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1017 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "Inside CreateClassifierPHSRule");
1019 if (psaClassifiertable
== NULL
)
1020 return ERR_INVALID_CLASSIFIERTABLE_FOR_SF
;
1022 if (eClsContext
== eOldClassifierRuleContext
) {
1024 * If An Old Entry for this classifier ID already exists in the
1025 * old rules table replace it.
1029 GetClassifierEntry(psaClassifiertable
, uiClsId
,
1030 eClsContext
, &psClassifierRules
);
1032 if (iClassifierIndex
!= PHS_INVALID_TABLE_INDEX
) {
1034 * The Classifier already exists in the old rules table
1035 * Lets replace the old classifier with the new one.
1037 bFreeEntryFound
= TRUE
;
1041 if (!bFreeEntryFound
) {
1042 /* Continue to search for a free location to add the rule */
1043 for (iClassifierIndex
= 0; iClassifierIndex
<
1044 MAX_PHSRULE_PER_SF
; iClassifierIndex
++) {
1045 if (eClsContext
== eActiveClassifierRuleContext
)
1046 psClassifierRules
= &psaClassifiertable
->stActivePhsRulesList
[iClassifierIndex
];
1048 psClassifierRules
= &psaClassifiertable
->stOldPhsRulesList
[iClassifierIndex
];
1050 if (!psClassifierRules
->bUsed
) {
1051 bFreeEntryFound
= TRUE
;
1057 if (!bFreeEntryFound
) {
1059 if (eClsContext
== eActiveClassifierRuleContext
)
1060 return ERR_CLSASSIFIER_TABLE_FULL
;
1062 /* Lets replace the oldest rule if we are looking in old Rule table */
1063 if (psaClassifiertable
->uiOldestPhsRuleIndex
>= MAX_PHSRULE_PER_SF
)
1064 psaClassifiertable
->uiOldestPhsRuleIndex
= 0;
1066 iClassifierIndex
= psaClassifiertable
->uiOldestPhsRuleIndex
;
1067 psClassifierRules
= &psaClassifiertable
->stOldPhsRulesList
[iClassifierIndex
];
1069 (psaClassifiertable
->uiOldestPhsRuleIndex
)++;
1073 if (eClsContext
== eOldClassifierRuleContext
) {
1075 if (psClassifierRules
->pstPhsRule
== NULL
) {
1077 psClassifierRules
->pstPhsRule
= kmalloc(sizeof(struct bcm_phs_rule
), GFP_KERNEL
);
1079 if (NULL
== psClassifierRules
->pstPhsRule
)
1080 return ERR_PHSRULE_MEMALLOC_FAIL
;
1083 psClassifierRules
->bUsed
= TRUE
;
1084 psClassifierRules
->uiClassifierRuleId
= uiClsId
;
1085 psClassifierRules
->u8PHSI
= psPhsRule
->u8PHSI
;
1086 psClassifierRules
->bUnclassifiedPHSRule
= psPhsRule
->bUnclassifiedPHSRule
;
1088 /* Update The PHS rule */
1089 memcpy(psClassifierRules
->pstPhsRule
, psPhsRule
, sizeof(struct bcm_phs_rule
));
1091 nStatus
= UpdateClassifierPHSRule(uiClsId
, psClassifierRules
,
1092 psaClassifiertable
, psPhsRule
, u8AssociatedPHSI
);
1097 static UINT
UpdateClassifierPHSRule(IN B_UINT16 uiClsId
,
1098 IN
struct bcm_phs_classifier_entry
*pstClassifierEntry
,
1099 struct bcm_phs_classifier_table
*psaClassifiertable
,
1100 struct bcm_phs_rule
*psPhsRule
,
1101 B_UINT8 u8AssociatedPHSI
)
1103 struct bcm_phs_rule
*pstAddPhsRule
= NULL
;
1104 UINT nPhsRuleIndex
= 0;
1105 bool bPHSRuleOrphaned
= false;
1106 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1108 psPhsRule
->u8RefCnt
= 0;
1110 /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
1111 bPHSRuleOrphaned
= DerefPhsRule(uiClsId
, psaClassifiertable
,
1112 pstClassifierEntry
->pstPhsRule
);
1114 /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */
1115 nPhsRuleIndex
= GetPhsRuleEntry(psaClassifiertable
, u8AssociatedPHSI
,
1116 eActiveClassifierRuleContext
, &pstAddPhsRule
);
1117 if (PHS_INVALID_TABLE_INDEX
== nPhsRuleIndex
) {
1119 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nAdding New PHSRuleEntry For Classifier");
1121 if (psPhsRule
->u8PHSI
== 0) {
1122 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nError PHSI is Zero\n");
1123 return ERR_PHS_INVALID_PHS_RULE
;
1126 /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
1127 if (false == bPHSRuleOrphaned
) {
1129 pstClassifierEntry
->pstPhsRule
= kmalloc(sizeof(struct bcm_phs_rule
), GFP_KERNEL
);
1130 if (NULL
== pstClassifierEntry
->pstPhsRule
)
1131 return ERR_PHSRULE_MEMALLOC_FAIL
;
1133 memcpy(pstClassifierEntry
->pstPhsRule
, psPhsRule
, sizeof(struct bcm_phs_rule
));
1135 /* Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule */
1136 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_DISPATCH
, DBG_LVL_ALL
, "\nTying Classifier to Existing PHS Rule");
1137 if (bPHSRuleOrphaned
) {
1138 kfree(pstClassifierEntry
->pstPhsRule
);
1139 pstClassifierEntry
->pstPhsRule
= NULL
;
1141 pstClassifierEntry
->pstPhsRule
= pstAddPhsRule
;
1144 pstClassifierEntry
->bUsed
= TRUE
;
1145 pstClassifierEntry
->u8PHSI
= pstClassifierEntry
->pstPhsRule
->u8PHSI
;
1146 pstClassifierEntry
->uiClassifierRuleId
= uiClsId
;
1147 pstClassifierEntry
->pstPhsRule
->u8RefCnt
++;
1148 pstClassifierEntry
->bUnclassifiedPHSRule
= pstClassifierEntry
->pstPhsRule
->bUnclassifiedPHSRule
;
1153 static bool DerefPhsRule(IN B_UINT16 uiClsId
, struct bcm_phs_classifier_table
*psaClassifiertable
, struct bcm_phs_rule
*pstPhsRule
)
1155 if (pstPhsRule
== NULL
)
1158 if (pstPhsRule
->u8RefCnt
)
1159 pstPhsRule
->u8RefCnt
--;
1161 if (0 == pstPhsRule
->u8RefCnt
) {
1163 * if(pstPhsRule->u8PHSI)
1164 * Store the currently active rule into the old rules list
1165 * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);
1172 void DumpPhsRules(struct bcm_phs_extension
*pDeviceExtension
)
1175 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1177 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "\n Dumping PHS Rules :\n");
1179 for (i
= 0; i
< MAX_SERVICEFLOWS
; i
++) {
1181 struct bcm_phs_entry stServFlowEntry
=
1182 pDeviceExtension
->pstServiceFlowPhsRulesTable
->stSFList
[i
];
1183 if (stServFlowEntry
.bUsed
) {
1185 for (j
= 0; j
< MAX_PHSRULE_PER_SF
; j
++) {
1187 for (l
= 0; l
< 2; l
++) {
1188 struct bcm_phs_classifier_entry stClsEntry
;
1191 stClsEntry
= stServFlowEntry
.pstClassifierTable
->stActivePhsRulesList
[j
];
1192 if (stClsEntry
.bUsed
)
1193 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n Active PHS Rule :\n");
1195 stClsEntry
= stServFlowEntry
.pstClassifierTable
->stOldPhsRulesList
[j
];
1196 if (stClsEntry
.bUsed
)
1197 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n Old PHS Rule :\n");
1200 if (stClsEntry
.bUsed
) {
1201 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "\n VCID : %#X", stServFlowEntry
.uiVcid
);
1202 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n ClassifierID : %#X", stClsEntry
.uiClassifierRuleId
);
1203 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSRuleID : %#X", stClsEntry
.u8PHSI
);
1204 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n****************PHS Rule********************\n");
1205 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSI : %#X", stClsEntry
.pstPhsRule
->u8PHSI
);
1206 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSFLength : %#X ", stClsEntry
.pstPhsRule
->u8PHSFLength
);
1207 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSF : ");
1209 for (k
= 0 ; k
< stClsEntry
.pstPhsRule
->u8PHSFLength
; k
++)
1210 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "%#X ", stClsEntry
.pstPhsRule
->u8PHSF
[k
]);
1211 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSMLength : %#X", stClsEntry
.pstPhsRule
->u8PHSMLength
);
1212 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSM :");
1214 for (k
= 0; k
< stClsEntry
.pstPhsRule
->u8PHSMLength
; k
++)
1215 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "%#X ", stClsEntry
.pstPhsRule
->u8PHSM
[k
]);
1216 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSS : %#X ", stClsEntry
.pstPhsRule
->u8PHSS
);
1217 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, (DBG_LVL_ALL
|DBG_NO_FUNC_PRINT
), "\n PHSV : %#X", stClsEntry
.pstPhsRule
->u8PHSV
);
1218 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "\n********************************************\n");
1227 * Procedure: phs_decompress
1229 * Description: This routine restores the static fields within the packet.
1232 * in_buf - ptr to incoming packet buffer.
1233 * out_buf - ptr to output buffer where the suppressed header is copied.
1234 * decomp_phs_rules - ptr to PHS rule.
1235 * header_size - ptr to field which holds the phss or phsf_length.
1238 * size -The number of bytes of dynamic fields present with in the incoming packet
1240 * 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
1242 static int phs_decompress(unsigned char *in_buf
,
1243 unsigned char *out_buf
,
1244 struct bcm_phs_rule
*decomp_phs_rules
,
1248 struct bcm_phs_rule
*tmp_memb
;
1250 unsigned char *phsf
, *phsm
;
1251 int in_buf_len
= *header_size
- 1;
1252 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1256 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "====>\n");
1259 if ((decomp_phs_rules
== NULL
))
1262 tmp_memb
= decomp_phs_rules
;
1264 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
1265 * header_size = tmp_memb->u8PHSFLength;
1267 phss
= tmp_memb
->u8PHSS
;
1268 phsf
= tmp_memb
->u8PHSF
;
1269 phsm
= tmp_memb
->u8PHSM
;
1271 if (phss
> MAX_PHS_LENGTHS
)
1272 phss
= MAX_PHS_LENGTHS
;
1275 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:
1276 * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
1278 while ((phss
> 0) && (size
< in_buf_len
)) {
1279 bit
= ((*phsm
<< i
) & SUPPRESS
);
1281 if (bit
== SUPPRESS
) {
1283 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "\nDECOMP:In phss %d phsf %d output %d",
1284 phss
, *phsf
, *out_buf
);
1287 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_RECEIVE
, DBG_LVL_ALL
, "\nDECOMP:In phss %d input %d output %d",
1288 phss
, *in_buf
, *out_buf
);
1296 *header_size
= *header_size
+ 1;
1298 if (i
> MAX_NO_BIT
) {
1308 * Procedure: phs_compress
1310 * Description: This routine suppresses the static fields within the packet.Before
1311 * that it will verify the fields to be suppressed with the corresponding fields in the
1312 * phsf. For verification it checks the phsv field of PHS rule. If set and verification
1313 * succeeds it suppresses the field.If any one static field is found different none of
1314 * the static fields are suppressed then the packet is sent as uncompressed packet with
1318 * phs_rule - ptr to PHS rule.
1319 * in_buf - ptr to incoming packet buffer.
1320 * out_buf - ptr to output buffer where the suppressed header is copied.
1321 * header_size - ptr to field which holds the phss.
1324 * size-The number of bytes copied into the output buffer i.e dynamic fields
1325 * 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails.
1327 static int phs_compress(struct bcm_phs_rule
*phs_rule
,
1328 unsigned char *in_buf
,
1329 unsigned char *out_buf
,
1331 UINT
*new_header_size
)
1333 unsigned char *old_addr
= out_buf
;
1335 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1337 if (phs_rule
== NULL
) {
1338 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nphs_compress(): phs_rule null!");
1339 *out_buf
= ZERO_PHSI
;
1340 return STATUS_PHS_NOCOMPRESSION
;
1343 if (phs_rule
->u8PHSS
<= *new_header_size
)
1344 *header_size
= phs_rule
->u8PHSS
;
1346 *header_size
= *new_header_size
;
1350 suppress
= verify_suppress_phsf(in_buf
, out_buf
, phs_rule
->u8PHSF
,
1351 phs_rule
->u8PHSM
, phs_rule
->u8PHSS
,
1352 phs_rule
->u8PHSV
, new_header_size
);
1354 if (suppress
== STATUS_PHS_COMPRESSED
) {
1355 *old_addr
= (unsigned char)phs_rule
->u8PHSI
;
1356 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nCOMP:In phs_compress phsi %d", phs_rule
->u8PHSI
);
1358 *old_addr
= ZERO_PHSI
;
1359 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nCOMP:In phs_compress PHSV Verification failed");
1366 * Procedure: verify_suppress_phsf
1368 * Description: This routine verifies the fields of the packet and if all the
1369 * static fields are equal it adds the phsi of that PHS rule.If any static
1370 * field differs it woun't suppress any field.
1373 * rules_set - ptr to classifier_rules.
1374 * in_buffer - ptr to incoming packet buffer.
1375 * out_buffer - ptr to output buffer where the suppressed header is copied.
1376 * phsf - ptr to phsf.
1377 * phsm - ptr to phsm.
1378 * phss - variable holding phss.
1381 * size-The number of bytes copied into the output buffer i.e dynamic fields.
1382 * 0 -Packet has failed the verification.
1384 static int verify_suppress_phsf(unsigned char *in_buffer
,
1385 unsigned char *out_buffer
,
1386 unsigned char *phsf
,
1387 unsigned char *phsm
,
1390 UINT
*new_header_size
)
1392 unsigned int size
= 0;
1394 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
1396 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm
);
1398 if (phss
> (*new_header_size
))
1399 phss
= *new_header_size
;
1402 bit
= ((*phsm
<< i
) & SUPPRESS
);
1403 if (bit
== SUPPRESS
) {
1404 if (*in_buffer
!= *phsf
) {
1405 if (phsv
== VERIFY
) {
1406 BCM_DEBUG_PRINT(Adapter
,
1410 "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",
1414 return STATUS_PHS_NOCOMPRESSION
;
1417 BCM_DEBUG_PRINT(Adapter
,
1421 "\nCOMP:In verify_phsf success for field %d buf %d phsf %d",
1426 *out_buffer
= *in_buffer
;
1427 BCM_DEBUG_PRINT(Adapter
,
1431 "\nCOMP:In copying_header input %d out %d",
1443 if (i
> MAX_NO_BIT
) {
1448 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, PHS_SEND
, DBG_LVL_ALL
, "\nCOMP:In verify_phsf success");
1449 *new_header_size
= size
;
1450 return STATUS_PHS_COMPRESSED
;