PHSModule.c revision 9dd47ee7dd535649a2c32d509631c7a3d793f2e1
1#include "headers.h"
2
3static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
4
5static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
6
7static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI);
8
9static UINT UpdateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
10
11static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule);
12
13static BOOLEAN DerefPhsRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule);
14
15static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry);
16
17static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule);
18
19static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable);
20
21static int phs_compress(S_PHS_RULE   *phs_members,unsigned char *in_buf,
22						unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
23
24
25static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
26								unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
27
28static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
29						  S_PHS_RULE   *phs_rules,UINT *header_size);
30
31
32static ULONG PhsCompress(void* pvContext,
33				  B_UINT16 uiVcid,
34				  B_UINT16 uiClsId,
35				  void *pvInputBuffer,
36				  void *pvOutputBuffer,
37				  UINT *pOldHeaderSize,
38				  UINT *pNewHeaderSize );
39
40static ULONG PhsDeCompress(void* pvContext,
41				  B_UINT16 uiVcid,
42				  void *pvInputBuffer,
43				  void *pvOutputBuffer,
44				  UINT *pInHeaderSize,
45				  UINT *pOutHeaderSize);
46
47
48
49#define IN
50#define OUT
51
52/*
53Function:				PHSTransmit
54
55Description:			This routine handle PHS(Payload Header Suppression for Tx path.
56					It extracts a fragment of the NDIS_PACKET containing the header
57					to be suppressed.It then supresses the header by invoking PHS exported compress routine.
58					The header data after supression is copied back to the NDIS_PACKET.
59
60
61Input parameters:		IN PMINI_ADAPTER Adapter         - Miniport Adapter Context
62						IN Packet 				- NDIS packet containing data to be transmitted
63						IN USHORT Vcid        - vcid pertaining to connection on which the packet is being sent.Used to
64										        identify PHS rule to be applied.
65						B_UINT16 uiClassifierRuleID - Classifier Rule ID
66						BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
67
68Return:					STATUS_SUCCESS - If the send was successful.
69						Other          - If an error occured.
70*/
71
72int PHSTransmit(PMINI_ADAPTER Adapter,
73					 struct sk_buff	**pPacket,
74					 USHORT Vcid,
75					 B_UINT16 uiClassifierRuleID,
76					 BOOLEAN bHeaderSuppressionEnabled,
77					 UINT *PacketLen,
78					 UCHAR bEthCSSupport)
79{
80
81	//PHS Sepcific
82	UINT    unPHSPktHdrBytesCopied = 0;
83	UINT	unPhsOldHdrSize = 0;
84	UINT	unPHSNewPktHeaderLen = 0;
85	/* Pointer to PHS IN Hdr Buffer */
86	PUCHAR pucPHSPktHdrInBuf =
87				Adapter->stPhsTxContextInfo.ucaHdrSupressionInBuf;
88	/* Pointer to PHS OUT Hdr Buffer */
89	PUCHAR  pucPHSPktHdrOutBuf =
90					Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf;
91	UINT       usPacketType;
92	UINT       BytesToRemove=0;
93	BOOLEAN  bPHSI = 0;
94	LONG ulPhsStatus = 0;
95	UINT 	numBytesCompressed = 0;
96	struct sk_buff *newPacket = NULL;
97	struct sk_buff *Packet = *pPacket;
98
99	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
100
101	if(!bEthCSSupport)
102		BytesToRemove=ETH_HLEN;
103	/*
104		Accumulate the header upto the size we support supression
105		from NDIS packet
106	*/
107
108	usPacketType=((struct ethhdr *)(Packet->data))->h_proto;
109
110
111	pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
112	//considering data after ethernet header
113	if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
114	{
115
116		unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
117	}
118	else
119	{
120		unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
121	}
122
123	if( (unPHSPktHdrBytesCopied > 0 ) &&
124		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))
125	{
126
127
128		// Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
129	// Suppress only if IP Header and PHS Enabled For the Service Flow
130		if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
131			(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
132			(bHeaderSuppressionEnabled))
133		{
134				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);
135
136
137				unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
138				ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
139					Vcid,
140					uiClassifierRuleID,
141					pucPHSPktHdrInBuf,
142					pucPHSPktHdrOutBuf,
143					&unPhsOldHdrSize,
144					&unPHSNewPktHeaderLen);
145				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size  %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen);
146
147				if(unPHSNewPktHeaderLen == unPhsOldHdrSize)
148				{
149					if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
150							bPHSI = *pucPHSPktHdrOutBuf;
151					ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
152				}
153
154				if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
155				{
156					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed");
157
158					if(skb_cloned(Packet))
159					{
160						newPacket = skb_copy(Packet, GFP_ATOMIC);
161
162						if(newPacket == NULL)
163							return STATUS_FAILURE;
164
165						dev_kfree_skb(Packet);
166						*pPacket = Packet = newPacket;
167						pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;
168					}
169
170					numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
171
172					memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
173					memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
174					skb_pull(Packet, numBytesCompressed);
175
176					return STATUS_SUCCESS;
177				}
178
179				else
180				{
181					//if one byte headroom is not available, increase it through skb_cow
182					if(!(skb_headroom(Packet) > 0))
183					{
184						if(skb_cow(Packet, 1))
185						{
186							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
187							return STATUS_FAILURE;
188						}
189					}
190					skb_push(Packet, 1);
191
192					// CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes.  not needed .... hence corrupting it.
193					*(Packet->data + BytesToRemove) = bPHSI;
194					return STATUS_SUCCESS;
195			}
196		}
197		else
198		{
199			if(!bHeaderSuppressionEnabled)
200			{
201				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");
202			}
203
204			return STATUS_SUCCESS;
205		}
206	}
207
208	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");
209	return STATUS_SUCCESS;
210}
211
212int PHSRecieve(PMINI_ADAPTER Adapter,
213					USHORT usVcid,
214					struct sk_buff *packet,
215					UINT *punPacketLen,
216					UCHAR *pucEthernetHdr,
217					UINT	bHeaderSuppressionEnabled)
218{
219	u32   nStandardPktHdrLen            		= 0;
220	u32   nTotalsupressedPktHdrBytes  = 0;
221	int     ulPhsStatus 		= 0;
222	PUCHAR pucInBuff = NULL ;
223	UINT TotalBytesAdded = 0;
224	if(!bHeaderSuppressionEnabled)
225	{
226		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
227		return ulPhsStatus;
228	}
229
230	pucInBuff = packet->data;
231
232	//Restore  PHS suppressed header
233	nStandardPktHdrLen = packet->len;
234	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
235		usVcid,
236		pucInBuff,
237		Adapter->ucaPHSPktRestoreBuf,
238		&nTotalsupressedPktHdrBytes,
239		&nStandardPktHdrLen);
240
241	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
242					nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
243
244	if(ulPhsStatus != STATUS_PHS_COMPRESSED)
245	{
246		skb_pull(packet, 1);
247		return STATUS_SUCCESS;
248	}
249	else
250	{
251		TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - PHSI_LEN;
252		if(TotalBytesAdded)
253		{
254			if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
255				skb_push(packet, TotalBytesAdded);
256			else
257			{
258				if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))
259				{
260					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
261					return STATUS_FAILURE;
262				}
263
264				skb_push(packet, TotalBytesAdded);
265			}
266		}
267
268		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
269	}
270
271	return STATUS_SUCCESS;
272}
273
274void DumpFullPacket(UCHAR *pBuf,UINT nPktLen)
275{
276	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
277    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");
278    BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);
279}
280
281//-----------------------------------------------------------------------------
282// Procedure:   phs_init
283//
284// Description: This routine is responsible for allocating memory for classifier and
285// PHS rules.
286//
287// Arguments:
288// pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
289//
290// Returns:
291// TRUE(1)	-If allocation of memory was success full.
292// FALSE	-If allocation of memory fails.
293//-----------------------------------------------------------------------------
294int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter)
295{
296	int i;
297	S_SERVICEFLOW_TABLE *pstServiceFlowTable;
298    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function ");
299
300	if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
301		return -EINVAL;
302
303	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
304		kzalloc(sizeof(S_SERVICEFLOW_TABLE), GFP_KERNEL);
305
306    if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
307	{
308		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
309		return -ENOMEM;
310	}
311
312	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
313	for(i=0;i<MAX_SERVICEFLOWS;i++)
314	{
315		S_SERVICEFLOW_ENTRY sServiceFlow = pstServiceFlowTable->stSFList[i];
316		sServiceFlow.pstClassifierTable = kzalloc(sizeof(S_CLASSIFIER_TABLE), GFP_KERNEL);
317		if(!sServiceFlow.pstClassifierTable)
318		{
319			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
320			free_phs_serviceflow_rules(pPhsdeviceExtension->
321                pstServiceFlowPhsRulesTable);
322			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
323			return -ENOMEM;
324		}
325	}
326
327	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
328
329    if(pPhsdeviceExtension->CompressedTxBuffer == NULL)
330	{
331		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
332		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
333		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
334		return -ENOMEM;
335	}
336
337    pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
338	if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
339	{
340		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
341		kfree(pPhsdeviceExtension->CompressedTxBuffer);
342		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
343		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
344		return -ENOMEM;
345	}
346
347
348
349	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull");
350	return STATUS_SUCCESS;
351}
352
353
354int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt)
355{
356	if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)
357	{
358		free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
359		pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
360	}
361
362	kfree(pPHSDeviceExt->CompressedTxBuffer);
363	pPHSDeviceExt->CompressedTxBuffer = NULL;
364
365	kfree(pPHSDeviceExt->UnCompressedRxBuffer);
366	pPHSDeviceExt->UnCompressedRxBuffer = NULL;
367
368	return 0;
369}
370
371
372
373//PHS functions
374/*++
375PhsUpdateClassifierRule
376
377Routine Description:
378    Exported function to add or modify a PHS Rule.
379
380Arguments:
381	IN void* pvContext - PHS Driver Specific Context
382	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies
383	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
384	IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
385
386Return Value:
387
388    0 if successful,
389    >0 Error.
390
391--*/
392ULONG PhsUpdateClassifierRule(IN void* pvContext,
393								IN B_UINT16  uiVcid ,
394								IN B_UINT16  uiClsId   ,
395								IN S_PHS_RULE *psPhsRule,
396								IN B_UINT8  u8AssociatedPHSI)
397{
398	ULONG lStatus =0;
399	UINT nSFIndex =0 ;
400	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
401    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
402
403
404
405	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
406
407	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n");
408
409	if(pDeviceExtension == NULL)
410	{
411		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");
412		return ERR_PHS_INVALID_DEVICE_EXETENSION;
413	}
414
415
416	if(u8AssociatedPHSI == 0)
417	{
418		return ERR_PHS_INVALID_PHS_RULE;
419	}
420
421	/* Retrieve the SFID Entry Index for requested Service Flow */
422
423	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
424	                uiVcid,&pstServiceFlowEntry);
425
426    if(nSFIndex == PHS_INVALID_TABLE_INDEX)
427	{
428		/* This is a new SF. Create a mapping entry for this */
429		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
430		      pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
431		return lStatus;
432	}
433
434	/* SF already Exists Add PHS Rule to existing SF */
435  	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
436  	          pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
437
438    return lStatus;
439}
440
441/*++
442PhsDeletePHSRule
443
444Routine Description:
445   Deletes the specified phs Rule within Vcid
446
447Arguments:
448	IN void* pvContext - PHS Driver Specific Context
449	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
450	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted.
451
452Return Value:
453
454    0 if successful,
455    >0 Error.
456
457--*/
458
459ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)
460{
461	ULONG lStatus =0;
462	UINT nSFIndex =0, nClsidIndex =0 ;
463	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
464	S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
465    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
466
467
468	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
469
470	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
471
472	if(pDeviceExtension)
473	{
474
475		//Retrieve the SFID Entry Index for requested Service Flow
476		nSFIndex = GetServiceFlowEntry(pDeviceExtension
477		      ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);
478
479       if(nSFIndex == PHS_INVALID_TABLE_INDEX)
480		{
481			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
482			return ERR_SF_MATCH_FAIL;
483		}
484
485		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
486		if(pstClassifierRulesTable)
487		{
488			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
489			{
490				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
491				{
492					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI)					{
493						if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
494							pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
495						if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
496							kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
497						memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
498							sizeof(S_CLASSIFIER_ENTRY));
499					}
500				}
501			}
502		}
503
504	}
505	return lStatus;
506}
507
508/*++
509PhsDeleteClassifierRule
510
511Routine Description:
512    Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
513
514Arguments:
515	IN void* pvContext - PHS Driver Specific Context
516	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
517	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
518
519Return Value:
520
521    0 if successful,
522    >0 Error.
523
524--*/
525ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16  uiClsId)
526{
527	ULONG lStatus =0;
528	UINT nSFIndex =0, nClsidIndex =0 ;
529	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
530	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
531    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
532	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
533
534	if(pDeviceExtension)
535	{
536		//Retrieve the SFID Entry Index for requested Service Flow
537		nSFIndex = GetServiceFlowEntry(pDeviceExtension
538		      ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
539		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
540		{
541			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n");
542			return ERR_SF_MATCH_FAIL;
543		}
544
545		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
546                  uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
547		if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
548		{
549			if(pstClassifierEntry->pstPhsRule)
550			{
551				if(pstClassifierEntry->pstPhsRule->u8RefCnt)
552				pstClassifierEntry->pstPhsRule->u8RefCnt--;
553				if(0==pstClassifierEntry->pstPhsRule->u8RefCnt)
554					kfree(pstClassifierEntry->pstPhsRule);
555
556			}
557			memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
558		}
559
560		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
561                    uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
562
563	   if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
564		{
565			kfree(pstClassifierEntry->pstPhsRule);
566			memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
567		}
568	}
569	return lStatus;
570}
571
572/*++
573PhsDeleteSFRules
574
575Routine Description:
576    Exported function to Delete a all PHS Rules for the SFID.
577
578Arguments:
579	IN void* pvContext - PHS Driver Specific Context
580	IN B_UINT16 uiVcid   - The Service Flow ID for which the PHS rules need to be deleted
581
582Return Value:
583
584    0 if successful,
585    >0 Error.
586
587--*/
588ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid)
589{
590
591	ULONG lStatus =0;
592	UINT nSFIndex =0, nClsidIndex =0  ;
593	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
594	S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
595    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
596	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
597    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n");
598
599	if(pDeviceExtension)
600	{
601		//Retrieve the SFID Entry Index for requested Service Flow
602		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
603		                  uiVcid,&pstServiceFlowEntry);
604		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
605		{
606			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
607			return ERR_SF_MATCH_FAIL;
608		}
609
610		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
611		if(pstClassifierRulesTable)
612		{
613			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
614			{
615				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
616				{
617					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
618                                                        .pstPhsRule->u8RefCnt)
619						pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
620						                                    .pstPhsRule->u8RefCnt--;
621					if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
622                                                          .pstPhsRule->u8RefCnt)
623						kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
624					    pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
625                                        .pstPhsRule = NULL;
626				}
627				memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
628				if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule)
629				{
630					if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
631                                        .pstPhsRule->u8RefCnt)
632						pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
633						                  .pstPhsRule->u8RefCnt--;
634					if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
635                                        .pstPhsRule->u8RefCnt)
636						kfree(pstClassifierRulesTable
637						      ->stOldPhsRulesList[nClsidIndex].pstPhsRule);
638					pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
639                              .pstPhsRule = NULL;
640				}
641				memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
642			}
643		}
644		pstServiceFlowEntry->bUsed = FALSE;
645		pstServiceFlowEntry->uiVcid = 0;
646
647	}
648
649	return lStatus;
650}
651
652
653/*++
654PhsCompress
655
656Routine Description:
657    Exported function to compress the data using PHS.
658
659Arguments:
660	IN void* pvContext - PHS Driver Specific Context.
661	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header compression applies.
662	IN UINT  uiClsId   - The Classifier ID to which current packet header compression applies.
663	IN void *pvInputBuffer - The Input buffer containg packet header data
664	IN void *pvOutputBuffer - The output buffer returned by this function after PHS
665	IN UINT *pOldHeaderSize  - The actual size of the header before PHS
666	IN UINT *pNewHeaderSize - The new size of the header after applying PHS
667
668Return Value:
669
670    0 if successful,
671    >0 Error.
672
673--*/
674ULONG PhsCompress(IN void* pvContext,
675				  IN B_UINT16 uiVcid,
676				  IN B_UINT16 uiClsId,
677				  IN void *pvInputBuffer,
678				  OUT void *pvOutputBuffer,
679				  OUT UINT *pOldHeaderSize,
680				  OUT UINT *pNewHeaderSize )
681{
682	UINT nSFIndex =0, nClsidIndex =0  ;
683	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
684	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
685	S_PHS_RULE *pstPhsRule = NULL;
686	ULONG lStatus =0;
687    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
688
689
690
691	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
692
693
694	if(pDeviceExtension == NULL)
695	{
696		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n");
697		lStatus =  STATUS_PHS_NOCOMPRESSION ;
698		return lStatus;
699
700	}
701
702	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n");
703
704
705	//Retrieve the SFID Entry Index for requested Service Flow
706	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
707	                  uiVcid,&pstServiceFlowEntry);
708	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
709	{
710		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n");
711		lStatus =  STATUS_PHS_NOCOMPRESSION ;
712		return lStatus;
713	}
714
715	nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
716                uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry);
717
718    if(nClsidIndex == PHS_INVALID_TABLE_INDEX)
719	{
720		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n");
721		lStatus =  STATUS_PHS_NOCOMPRESSION ;
722		return lStatus;
723	}
724
725
726	//get rule from SF id,Cls ID pair and proceed
727	pstPhsRule =  pstClassifierEntry->pstPhsRule;
728
729	if(!ValidatePHSRuleComplete(pstPhsRule))
730	{
731		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n");
732		lStatus =  STATUS_PHS_NOCOMPRESSION ;
733		return lStatus;
734	}
735
736	//Compress Packet
737	lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer,
738	      (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize);
739
740	if(lStatus == STATUS_PHS_COMPRESSED)
741	{
742		pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
743		pstPhsRule->PHSModifiedNumPackets++;
744	}
745	else
746		pstPhsRule->PHSErrorNumPackets++;
747
748	return lStatus;
749}
750
751/*++
752PhsDeCompress
753
754Routine Description:
755    Exported function to restore the packet header in Rx path.
756
757Arguments:
758	IN void* pvContext - PHS Driver Specific Context.
759	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header restoration applies.
760	IN  void *pvInputBuffer - The Input buffer containg suppressed packet header data
761	OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
762	OUT UINT *pHeaderSize   - The packet header size after restoration is returned in this parameter.
763
764Return Value:
765
766    0 if successful,
767    >0 Error.
768
769--*/
770ULONG PhsDeCompress(IN void* pvContext,
771				  IN B_UINT16 uiVcid,
772				  IN void *pvInputBuffer,
773				  OUT void *pvOutputBuffer,
774				  OUT UINT *pInHeaderSize,
775				  OUT UINT *pOutHeaderSize )
776{
777	UINT nSFIndex =0, nPhsRuleIndex =0 ;
778	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
779	S_PHS_RULE *pstPhsRule = NULL;
780	UINT phsi;
781    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
782	PPHS_DEVICE_EXTENSION pDeviceExtension=
783        (PPHS_DEVICE_EXTENSION)pvContext;
784
785	*pInHeaderSize = 0;
786
787	if(pDeviceExtension == NULL)
788	{
789		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n");
790		return ERR_PHS_INVALID_DEVICE_EXETENSION;
791	}
792
793	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n");
794
795	phsi = *((unsigned char *)(pvInputBuffer));
796    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi);
797    if(phsi == UNCOMPRESSED_PACKET )
798	{
799		return STATUS_PHS_NOCOMPRESSION;
800	}
801
802	//Retrieve the SFID Entry Index for requested Service Flow
803	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
804	      uiVcid,&pstServiceFlowEntry);
805	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
806	{
807		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
808		return ERR_SF_MATCH_FAIL;
809	}
810
811	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi,
812          eActiveClassifierRuleContext,&pstPhsRule);
813	if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
814	{
815		//Phs Rule does not exist in  active rules table. Lets try in the old rules table.
816		nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
817		      phsi,eOldClassifierRuleContext,&pstPhsRule);
818		if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
819		{
820			return ERR_PHSRULE_MATCH_FAIL;
821		}
822
823	}
824
825	*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
826            (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize);
827
828	pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
829
830	pstPhsRule->PHSModifiedNumPackets++;
831	return STATUS_PHS_COMPRESSED;
832}
833
834
835//-----------------------------------------------------------------------------
836// Procedure:   free_phs_serviceflow_rules
837//
838// Description: This routine is responsible for freeing memory allocated for PHS rules.
839//
840// Arguments:
841// rules	- ptr to S_SERVICEFLOW_TABLE structure.
842//
843// Returns:
844// Does not return any value.
845//-----------------------------------------------------------------------------
846
847static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable)
848{
849	int i,j;
850    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
851
852	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
853    if(psServiceFlowRulesTable)
854	{
855		for(i=0;i<MAX_SERVICEFLOWS;i++)
856		{
857			S_SERVICEFLOW_ENTRY stServiceFlowEntry =
858                psServiceFlowRulesTable->stSFList[i];
859			S_CLASSIFIER_TABLE *pstClassifierRulesTable =
860                stServiceFlowEntry.pstClassifierTable;
861
862			if(pstClassifierRulesTable)
863			{
864				for(j=0;j<MAX_PHSRULE_PER_SF;j++)
865				{
866					if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule)
867					{
868						if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
869                                                                                        ->u8RefCnt)
870							pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
871  							                                                ->u8RefCnt--;
872						if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
873                                                                ->u8RefCnt)
874							kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
875						pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
876					}
877					if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule)
878					{
879						if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
880                                                                ->u8RefCnt)
881							pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
882							                                          ->u8RefCnt--;
883						if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
884                                                                      ->u8RefCnt)
885							kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
886						pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
887					}
888				}
889				kfree(pstClassifierRulesTable);
890			    stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
891			}
892		}
893	}
894
895    kfree(psServiceFlowRulesTable);
896    psServiceFlowRulesTable = NULL;
897}
898
899
900
901static BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule)
902{
903	if(psPhsRule)
904	{
905		if(!psPhsRule->u8PHSI)
906		{
907			// PHSI is not valid
908			return FALSE;
909		}
910
911		if(!psPhsRule->u8PHSS)
912		{
913			//PHSS Is Undefined
914			return FALSE;
915		}
916
917		//Check if PHSF is defines for the PHS Rule
918		if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF
919		{
920			return FALSE;
921		}
922		return TRUE;
923	}
924	else
925	{
926		return FALSE;
927	}
928}
929
930UINT GetServiceFlowEntry(IN S_SERVICEFLOW_TABLE *psServiceFlowTable,
931    IN B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry)
932{
933	int  i;
934	for(i=0;i<MAX_SERVICEFLOWS;i++)
935	{
936		if(psServiceFlowTable->stSFList[i].bUsed)
937		{
938			if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid)
939			{
940				*ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
941				return i;
942			}
943		}
944	}
945
946	*ppstServiceFlowEntry = NULL;
947	return PHS_INVALID_TABLE_INDEX;
948}
949
950
951UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
952        IN B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
953        OUT S_CLASSIFIER_ENTRY **ppstClassifierEntry)
954{
955	int  i;
956	S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
957	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
958	{
959
960		if(eClsContext == eActiveClassifierRuleContext)
961		{
962			psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
963		}
964		else
965		{
966			psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
967		}
968
969		if(psClassifierRules->bUsed)
970		{
971			if(psClassifierRules->uiClassifierRuleId == uiClsid)
972			{
973				*ppstClassifierEntry = psClassifierRules;
974				return i;
975			}
976		}
977
978	}
979
980	*ppstClassifierEntry = NULL;
981	return PHS_INVALID_TABLE_INDEX;
982}
983
984static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
985			    IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
986			    OUT S_PHS_RULE **ppstPhsRule)
987{
988	int  i;
989	S_CLASSIFIER_ENTRY *pstClassifierRule = NULL;
990	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
991	{
992		if(eClsContext == eActiveClassifierRuleContext)
993		{
994			pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
995		}
996		else
997		{
998			pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
999		}
1000		if(pstClassifierRule->bUsed)
1001		{
1002			if(pstClassifierRule->u8PHSI == uiPHSI)
1003			{
1004				*ppstPhsRule = pstClassifierRule->pstPhsRule;
1005				return i;
1006			}
1007		}
1008
1009	}
1010
1011	*ppstPhsRule = NULL;
1012	return PHS_INVALID_TABLE_INDEX;
1013}
1014
1015UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16  uiClsId,
1016                      IN S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,
1017                      B_UINT8 u8AssociatedPHSI)
1018{
1019
1020    S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
1021	UINT uiStatus = 0;
1022	int iSfIndex;
1023	BOOLEAN bFreeEntryFound =FALSE;
1024	//Check for a free entry in SFID table
1025	for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++)
1026	{
1027		if(!psServiceFlowTable->stSFList[iSfIndex].bUsed)
1028		{
1029			bFreeEntryFound = TRUE;
1030			break;
1031		}
1032	}
1033
1034	if(!bFreeEntryFound)
1035		return ERR_SFTABLE_FULL;
1036
1037
1038	psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
1039	uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule,
1040	                      eActiveClassifierRuleContext,u8AssociatedPHSI);
1041	if(uiStatus == PHS_SUCCESS)
1042	{
1043		//Add entry at free index to the SF
1044		psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
1045		psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
1046	}
1047
1048	return uiStatus;
1049
1050}
1051
1052UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
1053            IN B_UINT16  uiClsId,IN S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,
1054              S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI)
1055{
1056	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
1057	UINT uiStatus =PHS_SUCCESS;
1058	UINT nClassifierIndex = 0;
1059	S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
1060    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1061    psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
1062
1063	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
1064
1065	/* Check if the supplied Classifier already exists */
1066	nClassifierIndex =GetClassifierEntry(
1067	            pstServiceFlowEntry->pstClassifierTable,uiClsId,
1068	            eActiveClassifierRuleContext,&pstClassifierEntry);
1069	if(nClassifierIndex == PHS_INVALID_TABLE_INDEX)
1070	{
1071		/*
1072		    The Classifier doesn't exist. So its a new classifier being added.
1073		     Add new entry to associate PHS Rule to the Classifier
1074		*/
1075
1076		uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,
1077		    psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI);
1078		return uiStatus;
1079	}
1080
1081	/*
1082	  The Classifier exists.The PHS Rule for this classifier
1083	  is being modified
1084	  */
1085	if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI)
1086	{
1087		if(pstClassifierEntry->pstPhsRule == NULL)
1088			return ERR_PHS_INVALID_PHS_RULE;
1089
1090		/*
1091		    This rule already exists if any fields are changed for this PHS
1092		    rule update them.
1093		 */
1094		 /* If any part of PHSF is valid then we update PHSF */
1095		if(psPhsRule->u8PHSFLength)
1096		{
1097			//update PHSF
1098			memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
1099			    psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
1100		}
1101		if(psPhsRule->u8PHSFLength)
1102		{
1103			//update PHSFLen
1104			pstClassifierEntry->pstPhsRule->u8PHSFLength =
1105			    psPhsRule->u8PHSFLength;
1106		}
1107		if(psPhsRule->u8PHSMLength)
1108		{
1109			//update PHSM
1110			memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
1111			    psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
1112		}
1113		if(psPhsRule->u8PHSMLength)
1114		{
1115			//update PHSM Len
1116			pstClassifierEntry->pstPhsRule->u8PHSMLength =
1117			    psPhsRule->u8PHSMLength;
1118		}
1119		if(psPhsRule->u8PHSS)
1120		{
1121			//update PHSS
1122			pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
1123		}
1124
1125		//update PHSV
1126		pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
1127
1128	}
1129	else
1130	{
1131		/*
1132		  A new rule is being set for this classifier.
1133		*/
1134		uiStatus=UpdateClassifierPHSRule( uiClsId,  pstClassifierEntry,
1135		      psaClassifiertable,  psPhsRule, u8AssociatedPHSI);
1136	}
1137
1138
1139
1140	return uiStatus;
1141}
1142
1143static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
1144    S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1145    E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI)
1146{
1147	UINT iClassifierIndex = 0;
1148	BOOLEAN bFreeEntryFound = FALSE;
1149	S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
1150	UINT nStatus = PHS_SUCCESS;
1151    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1152	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule");
1153    if(psaClassifiertable == NULL)
1154	{
1155		return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
1156	}
1157
1158	if(eClsContext == eOldClassifierRuleContext)
1159	{
1160		/* If An Old Entry for this classifier ID already exists in the
1161		    old rules table replace it. */
1162
1163		iClassifierIndex =
1164		GetClassifierEntry(psaClassifiertable, uiClsId,
1165		            eClsContext,&psClassifierRules);
1166		if(iClassifierIndex != PHS_INVALID_TABLE_INDEX)
1167		{
1168			/*
1169			    The Classifier already exists in the old rules table
1170		        Lets replace the old classifier with the new one.
1171			*/
1172			bFreeEntryFound = TRUE;
1173		}
1174	}
1175
1176	if(!bFreeEntryFound)
1177	{
1178		/*
1179		  Continue to search for a free location to add the rule
1180		*/
1181		for(iClassifierIndex = 0; iClassifierIndex <
1182            MAX_PHSRULE_PER_SF; iClassifierIndex++)
1183		{
1184			if(eClsContext == eActiveClassifierRuleContext)
1185			{
1186				psClassifierRules =
1187              &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
1188			}
1189			else
1190			{
1191				psClassifierRules =
1192                &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1193			}
1194
1195			if(!psClassifierRules->bUsed)
1196			{
1197				bFreeEntryFound = TRUE;
1198				break;
1199			}
1200		}
1201	}
1202
1203	if(!bFreeEntryFound)
1204	{
1205		if(eClsContext == eActiveClassifierRuleContext)
1206		{
1207			return ERR_CLSASSIFIER_TABLE_FULL;
1208		}
1209		else
1210		{
1211			//Lets replace the oldest rule if we are looking in old Rule table
1212			if(psaClassifiertable->uiOldestPhsRuleIndex >=
1213                MAX_PHSRULE_PER_SF)
1214			{
1215				psaClassifiertable->uiOldestPhsRuleIndex =0;
1216			}
1217
1218			iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
1219			psClassifierRules =
1220              &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1221
1222          (psaClassifiertable->uiOldestPhsRuleIndex)++;
1223		}
1224	}
1225
1226	if(eClsContext == eOldClassifierRuleContext)
1227	{
1228		if(psClassifierRules->pstPhsRule == NULL)
1229		{
1230			psClassifierRules->pstPhsRule = kmalloc(sizeof(S_PHS_RULE),GFP_KERNEL);
1231
1232          if(NULL == psClassifierRules->pstPhsRule)
1233				return ERR_PHSRULE_MEMALLOC_FAIL;
1234		}
1235
1236		psClassifierRules->bUsed = TRUE;
1237		psClassifierRules->uiClassifierRuleId = uiClsId;
1238		psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
1239		psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
1240
1241        /* Update The PHS rule */
1242		memcpy(psClassifierRules->pstPhsRule,
1243		    psPhsRule, sizeof(S_PHS_RULE));
1244	}
1245	else
1246	{
1247		nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
1248            psaClassifiertable,psPhsRule,u8AssociatedPHSI);
1249	}
1250	return nStatus;
1251}
1252
1253
1254static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
1255      IN S_CLASSIFIER_ENTRY *pstClassifierEntry,
1256      S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1257      B_UINT8 u8AssociatedPHSI)
1258{
1259	S_PHS_RULE *pstAddPhsRule = NULL;
1260	UINT              nPhsRuleIndex = 0;
1261	BOOLEAN       bPHSRuleOrphaned = FALSE;
1262    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1263	psPhsRule->u8RefCnt =0;
1264
1265	/* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/
1266	bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable,
1267	    pstClassifierEntry->pstPhsRule);
1268
1269	//Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF
1270	nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI,
1271	    eActiveClassifierRuleContext, &pstAddPhsRule);
1272	if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex)
1273	{
1274		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
1275
1276		if(psPhsRule->u8PHSI == 0)
1277		{
1278			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
1279			return ERR_PHS_INVALID_PHS_RULE;
1280		}
1281		//Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId
1282		if(FALSE == bPHSRuleOrphaned)
1283		{
1284			pstClassifierEntry->pstPhsRule = kmalloc(sizeof(S_PHS_RULE), GFP_KERNEL);
1285			if(NULL == pstClassifierEntry->pstPhsRule)
1286			{
1287				return ERR_PHSRULE_MEMALLOC_FAIL;
1288			}
1289		}
1290		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE));
1291
1292	}
1293	else
1294	{
1295		//Step 2.b PHS Rule  Exists Tie uiClsId with the existing PHS Rule
1296		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
1297		if(bPHSRuleOrphaned)
1298		{
1299			kfree(pstClassifierEntry->pstPhsRule);
1300			pstClassifierEntry->pstPhsRule = NULL;
1301		}
1302		pstClassifierEntry->pstPhsRule = pstAddPhsRule;
1303
1304	}
1305	pstClassifierEntry->bUsed = TRUE;
1306	pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
1307	pstClassifierEntry->uiClassifierRuleId = uiClsId;
1308	pstClassifierEntry->pstPhsRule->u8RefCnt++;
1309	pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
1310
1311	return PHS_SUCCESS;
1312
1313}
1314
1315static BOOLEAN DerefPhsRule(IN B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule)
1316{
1317	if(pstPhsRule==NULL)
1318		return FALSE;
1319	if(pstPhsRule->u8RefCnt)
1320		pstPhsRule->u8RefCnt--;
1321	if(0==pstPhsRule->u8RefCnt)
1322	{
1323		/*if(pstPhsRule->u8PHSI)
1324		//Store the currently active rule into the old rules list
1325		CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/
1326		return TRUE;
1327	}
1328	else
1329	{
1330		return FALSE;
1331	}
1332}
1333
1334void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension)
1335{
1336	int i,j,k,l;
1337    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1338    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n");
1339	for(i=0;i<MAX_SERVICEFLOWS;i++)
1340	{
1341		S_SERVICEFLOW_ENTRY stServFlowEntry =
1342				pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
1343		if(stServFlowEntry.bUsed)
1344		{
1345			for(j=0;j<MAX_PHSRULE_PER_SF;j++)
1346			{
1347				for(l=0;l<2;l++)
1348				{
1349					S_CLASSIFIER_ENTRY stClsEntry;
1350					if(l==0)
1351					{
1352						stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
1353						if(stClsEntry.bUsed)
1354							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n");
1355					}
1356					else
1357					{
1358						stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
1359						if(stClsEntry.bUsed)
1360							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n");
1361					}
1362					if(stClsEntry.bUsed)
1363					{
1364
1365						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X",stServFlowEntry.uiVcid);
1366						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X",stClsEntry.uiClassifierRuleId);
1367						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X",stClsEntry.u8PHSI);
1368						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
1369						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X",stClsEntry.pstPhsRule->u8PHSI);
1370						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength);
1371						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
1372						for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
1373						{
1374							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSF[k]);
1375						}
1376						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
1377						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
1378						for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
1379						{
1380							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSM[k]);
1381						}
1382						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS);
1383						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X",stClsEntry.pstPhsRule->u8PHSV);
1384						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
1385					}
1386				}
1387			}
1388		}
1389	}
1390}
1391
1392
1393//-----------------------------------------------------------------------------
1394// Procedure:   phs_decompress
1395//
1396// Description: This routine restores the static fields within the packet.
1397//
1398// Arguments:
1399//	in_buf			- ptr to incoming packet buffer.
1400//	out_buf			- ptr to output buffer where the suppressed header is copied.
1401//	decomp_phs_rules - ptr to PHS rule.
1402//	header_size		- ptr to field which holds the phss or phsf_length.
1403//
1404// Returns:
1405//	size -The number of bytes of dynamic fields present with in the incoming packet
1406//			header.
1407//	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
1408//-----------------------------------------------------------------------------
1409
1410int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
1411 S_PHS_RULE   *decomp_phs_rules,UINT *header_size)
1412{
1413	int phss,size=0;
1414	 S_PHS_RULE   *tmp_memb;
1415	int bit,i=0;
1416	unsigned char *phsf,*phsm;
1417	int in_buf_len = *header_size-1;
1418    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1419	in_buf++;
1420    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n");
1421	*header_size = 0;
1422
1423	if((decomp_phs_rules == NULL ))
1424		return 0;
1425
1426
1427	tmp_memb = decomp_phs_rules;
1428	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
1429	//*header_size = tmp_memb->u8PHSFLength;
1430	phss         = tmp_memb->u8PHSS;
1431	phsf         = tmp_memb->u8PHSF;
1432	phsm         = tmp_memb->u8PHSM;
1433
1434	if(phss > MAX_PHS_LENGTHS)
1435		phss = MAX_PHS_LENGTHS;
1436	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
1437	while((phss > 0) && (size < in_buf_len))
1438	{
1439		bit =  ((*phsm << i)& SUPPRESS);
1440
1441		if(bit == SUPPRESS)
1442		{
1443			*out_buf = *phsf;
1444			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d phsf %d ouput %d",
1445              phss,*phsf,*out_buf);
1446		}
1447		else
1448		{
1449			*out_buf = *in_buf;
1450			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d input %d ouput %d",
1451            phss,*in_buf,*out_buf);
1452			in_buf++;
1453			size++;
1454		}
1455		out_buf++;
1456		phsf++;
1457		phss--;
1458		i++;
1459		*header_size=*header_size + 1;
1460
1461		if(i > MAX_NO_BIT)
1462		{
1463			i=0;
1464			phsm++;
1465		}
1466	}
1467	return size;
1468}
1469
1470
1471
1472
1473//-----------------------------------------------------------------------------
1474// Procedure:   phs_compress
1475//
1476// Description: This routine suppresses the static fields within the packet.Before
1477// that it will verify the fields to be suppressed with the corresponding fields in the
1478// phsf. For verification it checks the phsv field of PHS rule. If set and verification
1479// succeeds it suppresses the field.If any one static field is found different none of
1480// the static fields are suppressed then the packet is sent as uncompressed packet with
1481// phsi=0.
1482//
1483// Arguments:
1484//	phs_rule - ptr to PHS rule.
1485//	in_buf		- ptr to incoming packet buffer.
1486//	out_buf		- ptr to output buffer where the suppressed header is copied.
1487//	header_size	- ptr to field which holds the phss.
1488//
1489// Returns:
1490//	size-The number of bytes copied into the output buffer i.e dynamic fields
1491//	0	-If PHS rule is NULL.If PHSV field is not set.If the verification fails.
1492//-----------------------------------------------------------------------------
1493static int phs_compress(S_PHS_RULE  *phs_rule,unsigned char *in_buf
1494			,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
1495{
1496	unsigned char *old_addr = out_buf;
1497	int supress = 0;
1498    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1499    if(phs_rule == NULL)
1500	{
1501		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!");
1502		*out_buf = ZERO_PHSI;
1503		return STATUS_PHS_NOCOMPRESSION;
1504	}
1505
1506
1507	if(phs_rule->u8PHSS <= *new_header_size)
1508	{
1509		*header_size = phs_rule->u8PHSS;
1510	}
1511	else
1512	{
1513		*header_size = *new_header_size;
1514	}
1515	//To copy PHSI
1516	out_buf++;
1517	supress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF,
1518        phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size);
1519
1520	if(supress == STATUS_PHS_COMPRESSED)
1521	{
1522		*old_addr = (unsigned char)phs_rule->u8PHSI;
1523		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI);
1524	}
1525	else
1526	{
1527		*old_addr = ZERO_PHSI;
1528		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed");
1529	}
1530	return supress;
1531}
1532
1533
1534//-----------------------------------------------------------------------------
1535// Procedure:	verify_suppress_phsf
1536//
1537// Description: This routine verifies the fields of the packet and if all the
1538// static fields are equal it adds the phsi of that PHS rule.If any static
1539// field differs it woun't suppress any field.
1540//
1541// Arguments:
1542// rules_set	- ptr to classifier_rules.
1543// in_buffer	- ptr to incoming packet buffer.
1544// out_buffer	- ptr to output buffer where the suppressed header is copied.
1545// phsf			- ptr to phsf.
1546// phsm			- ptr to phsm.
1547// phss			- variable holding phss.
1548//
1549// Returns:
1550//	size-The number of bytes copied into the output buffer i.e dynamic fields.
1551//	0	-Packet has failed the verification.
1552//-----------------------------------------------------------------------------
1553
1554static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
1555				unsigned char *phsf,unsigned char *phsm,unsigned int phss,
1556				unsigned int phsv,UINT* new_header_size)
1557{
1558	unsigned int size=0;
1559	int bit,i=0;
1560    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
1561    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm);
1562
1563
1564	if(phss>(*new_header_size))
1565	{
1566		phss=*new_header_size;
1567	}
1568	while(phss > 0)
1569	{
1570		bit = ((*phsm << i)& SUPPRESS);
1571		if(bit == SUPPRESS)
1572		{
1573
1574			if(*in_buffer != *phsf)
1575			{
1576				if(phsv == VERIFY)
1577				{
1578					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
1579					return STATUS_PHS_NOCOMPRESSION;
1580				}
1581			}
1582			else
1583				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
1584		}
1585		else
1586		{
1587			*out_buffer = *in_buffer;
1588			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d  out %d",*in_buffer,*out_buffer);
1589			out_buffer++;
1590			size++;
1591		}
1592		in_buffer++;
1593		phsf++;
1594		phss--;
1595		i++;
1596		if(i > MAX_NO_BIT)
1597		{
1598			i=0;
1599			phsm++;
1600		}
1601	}
1602	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success");
1603	*new_header_size = size;
1604	return STATUS_PHS_COMPRESSED;
1605}
1606
1607
1608
1609
1610
1611
1612