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