Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
PHSModule.c
Go to the documentation of this file.
1 #include "headers.h"
2 
3 static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
4 
5 static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
6 
7 static UINT CreateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI);
8 
9 static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
10 
11 static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule);
12 
13 static BOOLEAN DerefPhsRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule);
14 
15 static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry);
16 
17 static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule);
18 
19 static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable);
20 
21 static int phs_compress(S_PHS_RULE *phs_members,unsigned char *in_buf,
22  unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
23 
24 
25 static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
26  unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
27 
28 static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
29  S_PHS_RULE *phs_rules,UINT *header_size);
30 
31 
32 static ULONG PhsCompress(void* pvContext,
33  B_UINT16 uiVcid,
34  B_UINT16 uiClsId,
35  void *pvInputBuffer,
36  void *pvOutputBuffer,
37  UINT *pOldHeaderSize,
38  UINT *pNewHeaderSize );
39 
40 static 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 /*
53 Function: PHSTransmit
54 
55 Description: This routine handle PHS(Payload Header Suppression for Tx path.
56  It extracts a fragment of the NDIS_PACKET containing the header
57  to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
58  The header data after suppression is copied back to the NDIS_PACKET.
59 
60 
61 Input parameters: IN struct bcm_mini_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 
68 Return: STATUS_SUCCESS - If the send was successful.
69  Other - If an error occurred.
70 */
71 
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.ucaHdrSuppressionInBuf;
88  /* Pointer to PHS OUT Hdr Buffer */
89  PUCHAR pucPHSPktHdrOutBuf =
90  Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
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 suppression
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 Suppress 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 
213  USHORT usVcid,
214  struct sk_buff *packet,
215  UINT *punPacketLen,
216  UCHAR *pucEthernetHdr,
217  UINT bHeaderSuppressionEnabled)
218 {
219  u32 nStandardPktHdrLen = 0;
220  u32 nTotalsuppressedPktHdrBytes = 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_RECEIVE,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  &nTotalsuppressedPktHdrBytes,
239  &nStandardPktHdrLen);
240 
241  BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
242  nTotalsuppressedPktHdrBytes,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 - nTotalsuppressedPktHdrBytes - 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 
275 {
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 //-----------------------------------------------------------------------------
294 int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension, struct bcm_mini_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 Successful");
350  return STATUS_SUCCESS;
351 }
352 
353 
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 /*++
375 PhsUpdateClassifierRule
376 
377 Routine Description:
378  Exported function to add or modify a PHS Rule.
379 
380 Arguments:
381  IN void* pvContext - PHS Driver Specific Context
382  IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
383  IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
384  IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
385 
386 Return Value:
387 
388  0 if successful,
389  >0 Error.
390 
391 --*/
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;
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");
413  }
414 
415 
416  if(u8AssociatedPHSI == 0)
417  {
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 /*++
442 PhsDeletePHSRule
443 
444 Routine Description:
445  Deletes the specified phs Rule within Vcid
446 
447 Arguments:
448  IN void* pvContext - PHS Driver Specific Context
449  IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
450  IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
451 
452 Return Value:
453 
454  0 if successful,
455  >0 Error.
456 
457 --*/
458 
459 ULONG 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;
466 
467 
468  PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
469 
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 /*++
509 PhsDeleteClassifierRule
510 
511 Routine Description:
512  Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
513 
514 Arguments:
515  IN void* pvContext - PHS Driver Specific Context
516  IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
517  IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
518 
519 Return Value:
520 
521  0 if successful,
522  >0 Error.
523 
524 --*/
525 ULONG 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;
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 /*++
573 PhsDeleteSFRules
574 
575 Routine Description:
576  Exported function to Delete a all PHS Rules for the SFID.
577 
578 Arguments:
579  IN void* pvContext - PHS Driver Specific Context
580  IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
581 
582 Return Value:
583 
584  0 if successful,
585  >0 Error.
586 
587 --*/
588 ULONG 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;
596  PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
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]
619  pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
620  .pstPhsRule->u8RefCnt--;
621  if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
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]
632  pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
633  .pstPhsRule->u8RefCnt--;
634  if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
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 /*++
654 PhsCompress
655 
656 Routine Description:
657  Exported function to compress the data using PHS.
658 
659 Arguments:
660  IN void* pvContext - PHS Driver Specific Context.
661  IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
662  IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
663  IN void *pvInputBuffer - The Input buffer containg packet header data
664  IN void *pvOutputBuffer - The output buffer returned by this function after PHS
665  IN UINT *pOldHeaderSize - The actual size of the header before PHS
666  IN UINT *pNewHeaderSize - The new size of the header after applying PHS
667 
668 Return Value:
669 
670  0 if successful,
671  >0 Error.
672 
673 --*/
674 ULONG PhsCompress(IN void* pvContext,
675  IN B_UINT16 uiVcid,
676  IN B_UINT16 uiClsId,
677  IN void *pvInputBuffer,
678  OUT void *pvOutputBuffer,
679  OUT UINT *pOldHeaderSize,
680  OUT UINT *pNewHeaderSize )
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;
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 /*++
752 PhsDeCompress
753 
754 Routine Description:
755  Exported function to restore the packet header in Rx path.
756 
757 Arguments:
758  IN void* pvContext - PHS Driver Specific Context.
759  IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
760  IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
761  OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
762  OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
763 
764 Return Value:
765 
766  0 if successful,
767  >0 Error.
768 
769 --*/
770 ULONG PhsDeCompress(IN void* pvContext,
771  IN B_UINT16 uiVcid,
772  IN void *pvInputBuffer,
773  OUT void *pvOutputBuffer,
774  OUT UINT *pInHeaderSize,
775  OUT UINT *pOutHeaderSize )
776 {
777  UINT nSFIndex =0, nPhsRuleIndex =0 ;
778  S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
779  S_PHS_RULE *pstPhsRule = NULL;
780  UINT phsi;
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_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
791  }
792 
793  BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
794 
795  phsi = *((unsigned char *)(pvInputBuffer));
796  BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
797  if(phsi == UNCOMPRESSED_PACKET )
798  {
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_RECEIVE,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 
847 static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable)
848 {
849  int i,j;
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 
901 static 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 
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;
948 }
949 
950 
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;
982 }
983 
984 static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
985  IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
986  OUT S_PHS_RULE **ppstPhsRule)
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 
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 
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  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1061  psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
1062 
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 
1143 static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
1144  S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1145  E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI)
1146 {
1147  UINT iClassifierIndex = 0;
1148  BOOLEAN bFreeEntryFound = FALSE;
1149  S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
1150  UINT nStatus = PHS_SUCCESS;
1151  struct bcm_mini_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  {
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  {
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)
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 
1254 static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
1255  IN S_CLASSIFIER_ENTRY *pstClassifierEntry,
1256  S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
1257  B_UINT8 u8AssociatedPHSI)
1258 {
1259  S_PHS_RULE *pstAddPhsRule = NULL;
1260  UINT nPhsRuleIndex = 0;
1261  BOOLEAN bPHSRuleOrphaned = FALSE;
1262  struct bcm_mini_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  {
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 
1315 static 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 
1334 void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension)
1335 {
1336  int i,j,k,l;
1337  struct bcm_mini_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);
1372  for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
1373  {
1375  }
1376  BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
1378  for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
1379  {
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 
1410 int 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  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1419  in_buf++;
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_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
1429  //*header_size = tmp_memb->u8PHSFLength;
1430  phss = tmp_memb->u8PHSS;
1431  phsf = tmp_memb->u8PHSF;
1432  phsm = tmp_memb->u8PHSM;
1433 
1434  if(phss > MAX_PHS_LENGTHS)
1435  phss = MAX_PHS_LENGTHS;
1436  //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
1437  while((phss > 0) && (size < in_buf_len))
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_RECEIVE,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_RECEIVE,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 //-----------------------------------------------------------------------------
1493 static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf
1494  ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
1495 {
1496  unsigned char *old_addr = out_buf;
1497  int suppress = 0;
1498  struct bcm_mini_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  suppress = 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(suppress == 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 suppress;
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 
1554 static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
1555  unsigned char *phsf,unsigned char *phsm,unsigned int phss,
1556  unsigned int phsv,UINT* new_header_size)
1557 {
1558  unsigned int size=0;
1559  int bit,i=0;
1560  struct bcm_mini_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