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