Linux 3.18-rc3
[cascardo/linux.git] / drivers / staging / bcm / Qos.c
1 /**
2  * @file Qos.C
3  * This file contains the routines related to Quality of Service.
4 */
5 #include "headers.h"
6
7 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,
8                             PVOID pvEthPayload,
9                             struct bcm_eth_packet_info *pstEthCsPktInfo);
10
11 static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,
12                              struct sk_buff *skb,
13                              struct bcm_eth_packet_info *pstEthCsPktInfo,
14                              struct bcm_classifier_rule *pstClassifierRule,
15                              B_UINT8 EthCSCupport);
16
17 static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
18                          struct bcm_classifier_rule *pstClassifierRule);
19
20 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex);
21
22
23 /*******************************************************************
24 * Function    - MatchSrcIpAddress()
25 *
26 * Description - Checks whether the Source IP address from the packet
27 *                               matches with that of Queue.
28 *
29 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
30 *               - ulSrcIP           : Source IP address from the packet.
31 *
32 * Returns     - TRUE(If address matches) else FAIL .
33 *********************************************************************/
34 static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,
35                               ULONG ulSrcIP)
36 {
37         UCHAR ucLoopIndex = 0;
38
39         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
40         union u_ip_address      *src_addr;
41
42         ulSrcIP = ntohl(ulSrcIP);
43         if (0 == pstClassifierRule->ucIPSourceAddressLength)
44                 return TRUE;
45         for (ucLoopIndex = 0;
46              ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);
47              ucLoopIndex++) {
48                 src_addr = &pstClassifierRule->stSrcIpAddress;
49                 BCM_DEBUG_PRINT(Adapter,
50                                 DBG_TYPE_TX,
51                                 IPV4_DBG,
52                                 DBG_LVL_ALL,
53                                 "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x",
54                                 (UINT)src_addr->ulIpv4Mask[ucLoopIndex],
55                                 (UINT)ulSrcIP,
56                                 (UINT)src_addr->ulIpv6Addr[ucLoopIndex]);
57
58                 if ((src_addr->ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
59                                 (src_addr->ulIpv4Addr[ucLoopIndex] &
60                                  src_addr->ulIpv4Mask[ucLoopIndex]))
61                         return TRUE;
62         }
63         BCM_DEBUG_PRINT(Adapter,
64                         DBG_TYPE_TX,
65                         IPV4_DBG,
66                         DBG_LVL_ALL,
67                         "Src Ip Address Not Matched");
68         return false;
69 }
70
71
72 /*******************************************************************
73 * Function    - MatchDestIpAddress()
74 *
75 * Description - Checks whether the Destination IP address from the packet
76 *                               matches with that of Queue.
77 *
78 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
79 *               - ulDestIP    : Destination IP address from the packet.
80 *
81 * Returns     - TRUE(If address matches) else FAIL .
82 *********************************************************************/
83 static bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
84 {
85         UCHAR ucLoopIndex = 0;
86         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
87         union u_ip_address      *dest_addr = &pstClassifierRule->stDestIpAddress;
88
89         ulDestIP = ntohl(ulDestIP);
90         if (0 == pstClassifierRule->ucIPDestinationAddressLength)
91                 return TRUE;
92         BCM_DEBUG_PRINT(Adapter,
93                         DBG_TYPE_TX,
94                         IPV4_DBG,
95                         DBG_LVL_ALL,
96                         "Destination Ip Address 0x%x 0x%x 0x%x  ",
97                         (UINT)ulDestIP,
98                         (UINT)dest_addr->ulIpv4Mask[ucLoopIndex],
99                         (UINT)dest_addr->ulIpv4Addr[ucLoopIndex]);
100
101         for (ucLoopIndex = 0;
102              ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength);
103              ucLoopIndex++) {
104                 if ((dest_addr->ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
105                                 (dest_addr->ulIpv4Addr[ucLoopIndex] &
106                                  dest_addr->ulIpv4Mask[ucLoopIndex]))
107                         return TRUE;
108         }
109         BCM_DEBUG_PRINT(Adapter,
110                         DBG_TYPE_TX,
111                         IPV4_DBG,
112                         DBG_LVL_ALL,
113                         "Destination Ip Address Not Matched");
114         return false;
115 }
116
117
118 /************************************************************************
119 * Function    - MatchTos()
120 *
121 * Description - Checks the TOS from the packet matches with that of queue.
122 *
123 * Parameters  - pstClassifierRule   : Pointer to the packet info structure.
124 *               - ucTypeOfService: TOS from the packet.
125 *
126 * Returns     - TRUE(If address matches) else FAIL.
127 **************************************************************************/
128 static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule,
129                      UCHAR ucTypeOfService)
130 {
131         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
132
133         if (3 != pstClassifierRule->ucIPTypeOfServiceLength)
134                 return TRUE;
135
136         if (((pstClassifierRule->ucTosMask & ucTypeOfService) <=
137                                 pstClassifierRule->ucTosHigh) &&
138                         ((pstClassifierRule->ucTosMask & ucTypeOfService) >=
139                                 pstClassifierRule->ucTosLow))
140                 return TRUE;
141
142         BCM_DEBUG_PRINT(Adapter,
143                         DBG_TYPE_TX,
144                         IPV4_DBG,
145                         DBG_LVL_ALL,
146                         "Type Of Service Not Matched");
147         return false;
148 }
149
150
151 /***************************************************************************
152 * Function    - MatchProtocol()
153 *
154 * Description - Checks the protocol from the packet matches with that of queue.
155 *
156 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
157 *               - ucProtocol    : Protocol from the packet.
158 *
159 * Returns     - TRUE(If address matches) else FAIL.
160 ****************************************************************************/
161 bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,
162                    UCHAR ucProtocol)
163 {
164         UCHAR ucLoopIndex = 0;
165         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
166
167         if (0 == pstClassifierRule->ucProtocolLength)
168                 return TRUE;
169         for (ucLoopIndex = 0;
170              ucLoopIndex < pstClassifierRule->ucProtocolLength;
171              ucLoopIndex++) {
172                 BCM_DEBUG_PRINT(Adapter,
173                                 DBG_TYPE_TX,
174                                 IPV4_DBG,
175                                 DBG_LVL_ALL,
176                                 "Protocol:0x%X Classification Protocol:0x%X",
177                                 ucProtocol,
178                                 pstClassifierRule->ucProtocol[ucLoopIndex]);
179                 if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol)
180                         return TRUE;
181         }
182         BCM_DEBUG_PRINT(Adapter,
183                         DBG_TYPE_TX,
184                         IPV4_DBG,
185                         DBG_LVL_ALL,
186                         "Protocol Not Matched");
187         return false;
188 }
189
190
191 /***********************************************************************
192 * Function    - MatchSrcPort()
193 *
194 * Description - Checks, Source port from the packet matches with that of queue.
195 *
196 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
197 *               - ushSrcPort    : Source port from the packet.
198 *
199 * Returns     - TRUE(If address matches) else FAIL.
200 ***************************************************************************/
201 bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,
202                   USHORT ushSrcPort)
203 {
204         UCHAR ucLoopIndex = 0;
205
206         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
207
208
209         if (0 == pstClassifierRule->ucSrcPortRangeLength)
210                 return TRUE;
211         for (ucLoopIndex = 0;
212              ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength;
213              ucLoopIndex++) {
214                 if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
215                         ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
216                         return TRUE;
217         }
218         BCM_DEBUG_PRINT(Adapter,
219                         DBG_TYPE_TX,
220                         IPV4_DBG,
221                         DBG_LVL_ALL,
222                         "Src Port: %x Not Matched ",
223                         ushSrcPort);
224         return false;
225 }
226
227
228 /***********************************************************************
229 * Function    - MatchDestPort()
230 *
231 * Description - Checks, Destination port from packet matches with that of queue.
232 *
233 * Parameters  - pstClassifierRule: Pointer to the packet info structure.
234 *               - ushDestPort   : Destination port from the packet.
235 *
236 * Returns     - TRUE(If address matches) else FAIL.
237 ***************************************************************************/
238 bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,
239                    USHORT ushDestPort)
240 {
241         UCHAR ucLoopIndex = 0;
242         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
243
244         if (0 == pstClassifierRule->ucDestPortRangeLength)
245                 return TRUE;
246
247         for (ucLoopIndex = 0;
248              ucLoopIndex < pstClassifierRule->ucDestPortRangeLength;
249              ucLoopIndex++) {
250                 BCM_DEBUG_PRINT(Adapter,
251                                 DBG_TYPE_TX,
252                                 IPV4_DBG,
253                                 DBG_LVL_ALL,
254                                 "Matching Port:0x%X   0x%X  0x%X",
255                                 ushDestPort,
256                                 pstClassifierRule->usDestPortRangeLo[ucLoopIndex],
257                                 pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
258
259                 if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
260                         ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
261                         return TRUE;
262         }
263         BCM_DEBUG_PRINT(Adapter,
264                         DBG_TYPE_TX,
265                         IPV4_DBG,
266                         DBG_LVL_ALL,
267                         "Dest Port: %x Not Matched",
268                         ushDestPort);
269         return false;
270 }
271 /**
272  * @ingroup tx_functions
273  * Compares IPV4 Ip address and port number
274  * @return Queue Index.
275 */
276 static USHORT   IpVersion4(struct bcm_mini_adapter *Adapter,
277                            struct iphdr *iphd,
278                            struct bcm_classifier_rule *pstClassifierRule)
279 {
280         struct bcm_transport_header *xprt_hdr = NULL;
281         bool    bClassificationSucceed = false;
282
283         BCM_DEBUG_PRINT(Adapter,
284                         DBG_TYPE_TX,
285                         IPV4_DBG,
286                         DBG_LVL_ALL,
287                         "========>");
288
289         xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
290
291         BCM_DEBUG_PRINT(Adapter,
292                         DBG_TYPE_TX,
293                         IPV4_DBG,
294                         DBG_LVL_ALL,
295                         "Trying to see Direction = %d %d",
296                         pstClassifierRule->ucDirection,
297                         pstClassifierRule->usVCID_Value);
298
299         /* Checking classifier validity */
300         if (!pstClassifierRule->bUsed ||
301                         pstClassifierRule->ucDirection == DOWNLINK_DIR)
302                 goto out;
303
304         BCM_DEBUG_PRINT(Adapter,
305                         DBG_TYPE_TX,
306                         IPV4_DBG,
307                         DBG_LVL_ALL,
308                         "is IPv6 check!");
309         if (pstClassifierRule->bIpv6Protocol)
310                 goto out;
311
312         /* Checking IP header parameter */
313         BCM_DEBUG_PRINT(Adapter,
314                         DBG_TYPE_TX,
315                         IPV4_DBG,
316                         DBG_LVL_ALL,
317                         "Trying to match Source IP Address");
318         if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
319                 goto out;
320         BCM_DEBUG_PRINT(Adapter,
321                         DBG_TYPE_TX,
322                         IPV4_DBG,
323                         DBG_LVL_ALL,
324                         "Source IP Address Matched");
325
326         if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
327                 goto out;
328         BCM_DEBUG_PRINT(Adapter,
329                         DBG_TYPE_TX,
330                         IPV4_DBG,
331                         DBG_LVL_ALL,
332                         "Destination IP Address Matched");
333
334         if (!MatchTos(pstClassifierRule, iphd->tos)) {
335                 BCM_DEBUG_PRINT(Adapter,
336                                 DBG_TYPE_TX,
337                                 IPV4_DBG,
338                                 DBG_LVL_ALL,
339                                 "TOS Match failed\n");
340                 goto out;
341         }
342         BCM_DEBUG_PRINT(Adapter,
343                         DBG_TYPE_TX,
344                         IPV4_DBG,
345                         DBG_LVL_ALL,
346                         "TOS Matched");
347
348         if (!MatchProtocol(pstClassifierRule, iphd->protocol))
349                 goto out;
350         BCM_DEBUG_PRINT(Adapter,
351                         DBG_TYPE_TX,
352                         IPV4_DBG,
353                         DBG_LVL_ALL,
354                         "Protocol Matched");
355
356         /*
357          * if protocol is not TCP or UDP then no
358          * need of comparing source port and destination port
359          */
360         if (iphd->protocol != TCP && iphd->protocol != UDP) {
361                 bClassificationSucceed = TRUE;
362                 goto out;
363         }
364         /* Checking Transport Layer Header field if present */
365         BCM_DEBUG_PRINT(Adapter,
366                         DBG_TYPE_TX,
367                         IPV4_DBG,
368                         DBG_LVL_ALL,
369                         "Source Port %04x",
370                         (iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
371
372         if (!MatchSrcPort(pstClassifierRule,
373                           ntohs((iphd->protocol == UDP) ?
374                           xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
375                 goto out;
376         BCM_DEBUG_PRINT(Adapter,
377                         DBG_TYPE_TX,
378                         IPV4_DBG,
379                         DBG_LVL_ALL,
380                         "Src Port Matched");
381
382         BCM_DEBUG_PRINT(Adapter,
383                         DBG_TYPE_TX,
384                         IPV4_DBG,
385                         DBG_LVL_ALL,
386                         "Destination Port %04x",
387                         (iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
388                                 xprt_hdr->thdr.dest);
389
390         if (!MatchDestPort(pstClassifierRule,
391                            ntohs((iphd->protocol == UDP) ?
392                            xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
393                 goto out;
394         bClassificationSucceed = TRUE;
395
396 out:
397         if (TRUE == bClassificationSucceed) {
398                 INT iMatchedSFQueueIndex = 0;
399
400                 iMatchedSFQueueIndex =
401                         SearchSfid(Adapter, pstClassifierRule->ulSFID);
402                 if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
403                         bClassificationSucceed = false;
404                 else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
405                         bClassificationSucceed = false;
406         }
407
408         BCM_DEBUG_PRINT(Adapter,
409                         DBG_TYPE_TX,
410                         IPV4_DBG,
411                         DBG_LVL_ALL,
412                         "IpVersion4 <==========");
413
414         return bClassificationSucceed;
415 }
416
417 VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter)
418 {
419         UINT iIndex = 0;
420
421         for (iIndex = 0; iIndex < HiPriority; iIndex++) {
422                 if (!Adapter->PackInfo[iIndex].bValid)
423                         continue;
424
425                 PruneQueue(Adapter, iIndex);
426         }
427 }
428
429
430 /**
431  * @ingroup tx_functions
432  * This function checks if the max queue size for a queue
433  * is less than number of bytes in the queue. If so -
434  * drops packets from the Head till the number of bytes is
435  * less than or equal to max queue size for the queue.
436  */
437 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
438 {
439         struct sk_buff *PacketToDrop = NULL;
440         struct net_device_stats *netstats;
441         struct bcm_packet_info  *curr_pack_info = &Adapter->PackInfo[iIndex];
442
443         BCM_DEBUG_PRINT(Adapter,
444                         DBG_TYPE_TX,
445                         PRUNE_QUEUE,
446                         DBG_LVL_ALL,
447                         "=====> Index %d",
448                         iIndex);
449
450         if (iIndex == HiPriority)
451                 return;
452
453         if (!Adapter || (iIndex < 0) || (iIndex > HiPriority))
454                 return;
455
456         /* To Store the netdevice statistic */
457         netstats = &Adapter->dev->stats;
458
459         spin_lock_bh(&curr_pack_info->SFQueueLock);
460
461         while (1) {
462 /*      while((UINT)curr_pack_info->uiCurrentPacketsOnHost >
463                 SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { */
464
465                 BCM_DEBUG_PRINT(Adapter,
466                                 DBG_TYPE_TX,
467                                 PRUNE_QUEUE,
468                                 DBG_LVL_ALL,
469                                 "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
470                                 curr_pack_info->uiCurrentBytesOnHost,
471                                 curr_pack_info->uiMaxBucketSize);
472
473                 PacketToDrop = curr_pack_info->FirstTxQueue;
474
475                 if (PacketToDrop == NULL)
476                         break;
477                 if ((curr_pack_info->uiCurrentPacketsOnHost <
478                                         SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
479                         ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb) +
480                                             SKB_CB_LATENCY_OFFSET))/HZ) <=
481                                 curr_pack_info->uiMaxLatency))
482                         break;
483
484                 if (PacketToDrop) {
485                         if (netif_msg_tx_err(Adapter))
486                                 pr_info(PFX "%s: tx queue %d overlimit\n",
487                                         Adapter->dev->name, iIndex);
488
489                         netstats->tx_dropped++;
490
491                         DEQUEUEPACKET(curr_pack_info->FirstTxQueue,
492                                       curr_pack_info->LastTxQueue);
493                         /* update current bytes and packets count */
494                         curr_pack_info->uiCurrentBytesOnHost -=
495                                 PacketToDrop->len;
496                         curr_pack_info->uiCurrentPacketsOnHost--;
497                         /* update dropped bytes and packets counts */
498                         curr_pack_info->uiDroppedCountBytes += PacketToDrop->len;
499                         curr_pack_info->uiDroppedCountPackets++;
500                         dev_kfree_skb(PacketToDrop);
501
502                 }
503
504                 BCM_DEBUG_PRINT(Adapter,
505                                 DBG_TYPE_TX,
506                                 PRUNE_QUEUE,
507                                 DBG_LVL_ALL,
508                                 "Dropped Bytes:%x Dropped Packets:%x",
509                                 curr_pack_info->uiDroppedCountBytes,
510                                 curr_pack_info->uiDroppedCountPackets);
511
512                 atomic_dec(&Adapter->TotalPacketCount);
513         }
514
515         spin_unlock_bh(&curr_pack_info->SFQueueLock);
516
517         BCM_DEBUG_PRINT(Adapter,
518                         DBG_TYPE_TX,
519                         PRUNE_QUEUE,
520                         DBG_LVL_ALL,
521                         "TotalPacketCount:%x",
522                         atomic_read(&Adapter->TotalPacketCount));
523         BCM_DEBUG_PRINT(Adapter,
524                         DBG_TYPE_TX,
525                         PRUNE_QUEUE,
526                         DBG_LVL_ALL,
527                         "<=====");
528 }
529
530 VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
531 {
532         INT     iQIndex;
533         UINT uiTotalPacketLength;
534         struct sk_buff *PacketToDrop = NULL;
535         struct bcm_packet_info *curr_packet_info;
536
537         BCM_DEBUG_PRINT(Adapter,
538                         DBG_TYPE_OTHERS,
539                         DUMP_INFO,
540                         DBG_LVL_ALL,
541                         "=====>");
542
543         /* down(&Adapter->data_packet_queue_lock); */
544         for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) {
545                 struct net_device_stats *netstats = &Adapter->dev->stats;
546
547                 curr_packet_info = &Adapter->PackInfo[iQIndex];
548
549                 spin_lock_bh(&curr_packet_info->SFQueueLock);
550                 while (curr_packet_info->FirstTxQueue) {
551                         PacketToDrop = curr_packet_info->FirstTxQueue;
552                         if (PacketToDrop) {
553                                 uiTotalPacketLength = PacketToDrop->len;
554                                 netstats->tx_dropped++;
555                         } else
556                                 uiTotalPacketLength = 0;
557
558                         DEQUEUEPACKET(curr_packet_info->FirstTxQueue,
559                                       curr_packet_info->LastTxQueue);
560
561                         /* Free the skb */
562                         dev_kfree_skb(PacketToDrop);
563
564                         /* update current bytes and packets count */
565                         curr_packet_info->uiCurrentBytesOnHost -= uiTotalPacketLength;
566                         curr_packet_info->uiCurrentPacketsOnHost--;
567
568                         /* update dropped bytes and packets counts */
569                         curr_packet_info->uiDroppedCountBytes += uiTotalPacketLength;
570                         curr_packet_info->uiDroppedCountPackets++;
571
572                         BCM_DEBUG_PRINT(Adapter,
573                                         DBG_TYPE_OTHERS,
574                                         DUMP_INFO,
575                                         DBG_LVL_ALL,
576                                         "Dropped Bytes:%x Dropped Packets:%x",
577                                         curr_packet_info->uiDroppedCountBytes,
578                                         curr_packet_info->uiDroppedCountPackets);
579                         atomic_dec(&Adapter->TotalPacketCount);
580                 }
581                 spin_unlock_bh(&curr_packet_info->SFQueueLock);
582         }
583         /* up(&Adapter->data_packet_queue_lock); */
584         BCM_DEBUG_PRINT(Adapter,
585                         DBG_TYPE_OTHERS,
586                         DUMP_INFO,
587                         DBG_LVL_ALL,
588                         "<=====");
589 }
590
591 USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
592 {
593         INT uiLoopIndex = 0;
594         struct bcm_classifier_rule *pstClassifierRule = NULL;
595         struct bcm_eth_packet_info stEthCsPktInfo;
596         PVOID pvEThPayload = NULL;
597         struct iphdr *pIpHeader = NULL;
598         INT uiSfIndex = 0;
599         USHORT usIndex = Adapter->usBestEffortQueueIndex;
600         bool bFragmentedPkt = false, bClassificationSucceed = false;
601         USHORT usCurrFragment = 0;
602
603         struct bcm_tcp_header *pTcpHeader;
604         UCHAR IpHeaderLength;
605         UCHAR TcpHeaderLength;
606
607         pvEThPayload = skb->data;
608         *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = 0;
609         EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
610
611         switch (stEthCsPktInfo.eNwpktEthFrameType) {
612         case eEth802LLCFrame:
613                 BCM_DEBUG_PRINT(Adapter,
614                                 DBG_TYPE_TX,
615                                 IPV4_DBG,
616                                 DBG_LVL_ALL,
617                                 "ClassifyPacket : 802LLCFrame\n");
618                 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
619                 break;
620         case eEth802LLCSNAPFrame:
621                 BCM_DEBUG_PRINT(Adapter,
622                                 DBG_TYPE_TX,
623                                 IPV4_DBG,
624                                 DBG_LVL_ALL,
625                                 "ClassifyPacket : 802LLC SNAP Frame\n");
626                 pIpHeader = pvEThPayload +
627                         sizeof(struct bcm_eth_llc_snap_frame);
628                 break;
629         case eEth802QVLANFrame:
630                 BCM_DEBUG_PRINT(Adapter,
631                                 DBG_TYPE_TX,
632                                 IPV4_DBG,
633                                 DBG_LVL_ALL,
634                                 "ClassifyPacket : 802.1Q VLANFrame\n");
635                 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
636                 break;
637         case eEthOtherFrame:
638                 BCM_DEBUG_PRINT(Adapter,
639                                 DBG_TYPE_TX,
640                                 IPV4_DBG,
641                                 DBG_LVL_ALL,
642                                 "ClassifyPacket : ETH Other Frame\n");
643                 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
644                 break;
645         default:
646                 BCM_DEBUG_PRINT(Adapter,
647                                 DBG_TYPE_TX,
648                                 IPV4_DBG,
649                                 DBG_LVL_ALL,
650                                 "ClassifyPacket : Unrecognized ETH Frame\n");
651                 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
652                 break;
653         }
654
655         if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) {
656                 usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
657                 if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
658                         bFragmentedPkt = TRUE;
659
660                 if (bFragmentedPkt) {
661                         /* Fragmented  Packet. Get Frag Classifier Entry. */
662                         pstClassifierRule = GetFragIPClsEntry(Adapter,
663                                                               pIpHeader->id,
664                                                               pIpHeader->saddr);
665                         if (pstClassifierRule) {
666                                         BCM_DEBUG_PRINT(Adapter,
667                                                         DBG_TYPE_TX,
668                                                         IPV4_DBG,
669                                                         DBG_LVL_ALL,
670                                                         "It is next Fragmented pkt");
671                                         bClassificationSucceed = TRUE;
672                         }
673                         if (!(ntohs(pIpHeader->frag_off) & IP_MF)) {
674                                 /* Fragmented Last packet . Remove Frag Classifier Entry */
675                                 BCM_DEBUG_PRINT(Adapter,
676                                                 DBG_TYPE_TX,
677                                                 IPV4_DBG,
678                                                 DBG_LVL_ALL,
679                                                 "This is the last fragmented Pkt");
680                                 DelFragIPClsEntry(Adapter,
681                                                   pIpHeader->id,
682                                                   pIpHeader->saddr);
683                         }
684                 }
685         }
686
687         for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) {
688                 if (bClassificationSucceed)
689                         break;
690                 /*
691                  * Iterate through all classifiers which are already in order of priority
692                  * to classify the packet until match found
693                  */
694                 if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
695                         bClassificationSucceed = false;
696                         continue;
697                 }
698                 BCM_DEBUG_PRINT(Adapter,
699                                 DBG_TYPE_TX,
700                                 IPV4_DBG,
701                                 DBG_LVL_ALL,
702                                 "Adapter->PackInfo[%d].bvalid=True\n",
703                                 uiLoopIndex);
704
705                 if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
706                         bClassificationSucceed = false; /* cannot be processed for classification. */
707                         continue;       /* it is a down link connection */
708                 }
709
710                 pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
711
712                 uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
713                 if (uiSfIndex >= NO_OF_QUEUES) {
714                         BCM_DEBUG_PRINT(Adapter,
715                                         DBG_TYPE_TX,
716                                         IPV4_DBG,
717                                         DBG_LVL_ALL,
718                                         "Queue Not Valid. SearchSfid for this classifier Failed\n");
719                         continue;
720                 }
721
722                 if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
723
724                         if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
725                                 BCM_DEBUG_PRINT(Adapter,
726                                                 DBG_TYPE_TX,
727                                                 IPV4_DBG,
728                                                 DBG_LVL_ALL,
729                                                 " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
730                                 bClassificationSucceed = false;
731                                 continue;
732                         }
733
734
735
736                         BCM_DEBUG_PRINT(Adapter,
737                                         DBG_TYPE_TX,
738                                         IPV4_DBG,
739                                         DBG_LVL_ALL,
740                                         "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",
741                                         pstClassifierRule->uiClassifierRuleIndex,
742                                         Adapter->PackInfo[uiSfIndex].ulSFID);
743                         bClassificationSucceed = EThCSClassifyPkt(Adapter,
744                                                                   skb,
745                                                                   &stEthCsPktInfo,
746                                                                   pstClassifierRule,
747                                                                   Adapter->PackInfo[uiSfIndex].bEthCSSupport);
748
749                         if (!bClassificationSucceed) {
750                                 BCM_DEBUG_PRINT(Adapter,
751                                                 DBG_TYPE_TX,
752                                                 IPV4_DBG,
753                                                 DBG_LVL_ALL,
754                                                 "ClassifyPacket : Ethernet CS Classification Failed\n");
755                                 continue;
756                         }
757                 } else { /* No ETH Supported on this SF */
758                         if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
759                                 BCM_DEBUG_PRINT(Adapter,
760                                                 DBG_TYPE_TX,
761                                                 IPV4_DBG,
762                                                 DBG_LVL_ALL,
763                                                 " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
764                                 bClassificationSucceed = false;
765                                 continue;
766                         }
767                 }
768
769                 BCM_DEBUG_PRINT(Adapter,
770                                 DBG_TYPE_TX,
771                                 IPV4_DBG,
772                                 DBG_LVL_ALL,
773                                 "Proceeding to IP CS Clasification");
774
775                 if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
776
777                         if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
778                                 BCM_DEBUG_PRINT(Adapter,
779                                                 DBG_TYPE_TX,
780                                                 IPV4_DBG,
781                                                 DBG_LVL_ALL,
782                                                 " ClassifyPacket : Packet is Not an IP Packet\n");
783                                 bClassificationSucceed = false;
784                                 continue;
785                         }
786                         BCM_DEBUG_PRINT(Adapter,
787                                         DBG_TYPE_TX,
788                                         IPV4_DBG,
789                                         DBG_LVL_ALL,
790                                         "Dump IP Header :\n");
791                         DumpFullPacket((PUCHAR)pIpHeader, 20);
792
793                         if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
794                                 bClassificationSucceed = IpVersion4(Adapter,
795                                                                     pIpHeader,
796                                                                     pstClassifierRule);
797                         else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
798                                 bClassificationSucceed = IpVersion6(Adapter,
799                                                                     pIpHeader,
800                                                                     pstClassifierRule);
801                 }
802         }
803
804         if (bClassificationSucceed == TRUE) {
805                 BCM_DEBUG_PRINT(Adapter,
806                                 DBG_TYPE_TX,
807                                 IPV4_DBG,
808                                 DBG_LVL_ALL,
809                                 "CF id : %d, SF ID is =%lu",
810                                 pstClassifierRule->uiClassifierRuleIndex,
811                                 pstClassifierRule->ulSFID);
812
813                 /* Store The matched Classifier in SKB */
814                 *((UINT32 *)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) =
815                         pstClassifierRule->uiClassifierRuleIndex;
816                 if ((TCP == pIpHeader->protocol) && !bFragmentedPkt &&
817                                 (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <=
818                                         skb->len)) {
819                         IpHeaderLength = pIpHeader->ihl;
820                         pTcpHeader =
821                                 (struct bcm_tcp_header *)(((PUCHAR)pIpHeader) +
822                                                 (IpHeaderLength*4));
823                         TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
824
825                         if ((pTcpHeader->ucFlags & TCP_ACK) &&
826                                    (ntohs(pIpHeader->tot_len) ==
827                                     (IpHeaderLength*4)+(TcpHeaderLength*4)))
828                                 *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) =
829                                         TCP_ACK;
830                 }
831
832                 usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
833                 BCM_DEBUG_PRINT(Adapter,
834                                 DBG_TYPE_TX,
835                                 IPV4_DBG,
836                                 DBG_LVL_ALL,
837                                 "index is =%d",
838                                 usIndex);
839
840                 /*
841                  * If this is the first fragment of a Fragmented pkt,
842                  * add this CF. Only This CF should be used for all other
843                  * fragment of this Pkt.
844                  */
845                 if (bFragmentedPkt && (usCurrFragment == 0)) {
846                         /*
847                          * First Fragment of Fragmented Packet.
848                          * Create Frag CLS Entry
849                          */
850                         struct bcm_fragmented_packet_info stFragPktInfo;
851
852                         stFragPktInfo.bUsed = TRUE;
853                         stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr;
854                         stFragPktInfo.usIpIdentification = pIpHeader->id;
855                         stFragPktInfo.pstMatchedClassifierEntry =
856                                 pstClassifierRule;
857                         stFragPktInfo.bOutOfOrderFragment = false;
858                         AddFragIPClsEntry(Adapter, &stFragPktInfo);
859                 }
860
861
862         }
863
864         return bClassificationSucceed ? usIndex : INVALID_QUEUE_INDEX;
865 }
866
867 static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,
868                                     PUCHAR Mac)
869 {
870         UINT i = 0;
871         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
872
873         if (pstClassifierRule->ucEthCSSrcMACLen == 0)
874                 return TRUE;
875         BCM_DEBUG_PRINT(Adapter,
876                         DBG_TYPE_TX,
877                         IPV4_DBG,
878                         DBG_LVL_ALL,
879                         "%s\n", __func__);
880         for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
881                 BCM_DEBUG_PRINT(Adapter,
882                                 DBG_TYPE_TX,
883                                 IPV4_DBG,
884                                 DBG_LVL_ALL,
885                                 "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",
886                                 i,
887                                 Mac[i],
888                                 pstClassifierRule->au8EThCSSrcMAC[i],
889                                 pstClassifierRule->au8EThCSSrcMACMask[i]);
890                 if ((pstClassifierRule->au8EThCSSrcMAC[i] &
891                                         pstClassifierRule->au8EThCSSrcMACMask[i]) !=
892                                 (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
893                         return false;
894         }
895         return TRUE;
896 }
897
898 static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,
899                                      PUCHAR Mac)
900 {
901         UINT i = 0;
902         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
903
904         if (pstClassifierRule->ucEthCSDestMACLen == 0)
905                 return TRUE;
906         BCM_DEBUG_PRINT(Adapter,
907                         DBG_TYPE_TX,
908                         IPV4_DBG,
909                         DBG_LVL_ALL,
910                         "%s\n",
911                         __func__);
912         for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
913                 BCM_DEBUG_PRINT(Adapter,
914                                 DBG_TYPE_TX,
915                                 IPV4_DBG,
916                                 DBG_LVL_ALL,
917                                 "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",
918                                 i,
919                                 Mac[i],
920                                 pstClassifierRule->au8EThCSDestMAC[i],
921                                 pstClassifierRule->au8EThCSDestMACMask[i]);
922                 if ((pstClassifierRule->au8EThCSDestMAC[i] &
923                                         pstClassifierRule->au8EThCSDestMACMask[i]) !=
924                                 (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
925                         return false;
926         }
927         return TRUE;
928 }
929
930 static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,
931                                  struct sk_buff *skb,
932                                  struct bcm_eth_packet_info *pstEthCsPktInfo)
933 {
934         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
935
936         if ((pstClassifierRule->ucEtherTypeLen == 0) ||
937                 (pstClassifierRule->au8EthCSEtherType[0] == 0))
938                 return TRUE;
939
940         BCM_DEBUG_PRINT(Adapter,
941                         DBG_TYPE_TX,
942                         IPV4_DBG,
943                         DBG_LVL_ALL,
944                         "%s SrcEtherType:%x CLS EtherType[0]:%x\n",
945                         __func__,
946                         pstEthCsPktInfo->usEtherType,
947                         pstClassifierRule->au8EthCSEtherType[0]);
948         if (pstClassifierRule->au8EthCSEtherType[0] == 1) {
949                 BCM_DEBUG_PRINT(Adapter,
950                                 DBG_TYPE_TX,
951                                 IPV4_DBG,
952                                 DBG_LVL_ALL,
953                                 "%s  CLS EtherType[1]:%x EtherType[2]:%x\n",
954                                 __func__,
955                                 pstClassifierRule->au8EthCSEtherType[1],
956                                 pstClassifierRule->au8EthCSEtherType[2]);
957
958                 if (memcmp(&pstEthCsPktInfo->usEtherType,
959                            &pstClassifierRule->au8EthCSEtherType[1],
960                            2) == 0)
961                         return TRUE;
962                 else
963                         return false;
964         }
965
966         if (pstClassifierRule->au8EthCSEtherType[0] == 2) {
967                 if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
968                         return false;
969
970                 BCM_DEBUG_PRINT(Adapter,
971                                 DBG_TYPE_TX,
972                                 IPV4_DBG,
973                                 DBG_LVL_ALL,
974                                 "%s  EthCS DSAP:%x EtherType[2]:%x\n",
975                                 __func__,
976                                 pstEthCsPktInfo->ucDSAP,
977                                 pstClassifierRule->au8EthCSEtherType[2]);
978                 if (pstEthCsPktInfo->ucDSAP ==
979                                 pstClassifierRule->au8EthCSEtherType[2])
980                         return TRUE;
981                 else
982                         return false;
983
984         }
985
986         return false;
987
988 }
989
990 static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,
991                                 struct sk_buff *skb,
992                                 struct bcm_eth_packet_info *pstEthCsPktInfo)
993 {
994         bool bClassificationSucceed = false;
995         USHORT usVLANID;
996         B_UINT8 uPriority = 0;
997         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
998
999         BCM_DEBUG_PRINT(Adapter,
1000                         DBG_TYPE_TX,
1001                         IPV4_DBG,
1002                         DBG_LVL_ALL,
1003                         "%s  CLS UserPrio:%x CLS VLANID:%x\n",
1004                         __func__,
1005                         ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),
1006                         pstClassifierRule->usVLANID);
1007
1008         /*
1009          * In case FW didn't receive the TLV,
1010          * the priority field should be ignored
1011          */
1012         if (pstClassifierRule->usValidityBitMap &
1013                         (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
1014                 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
1015                                 return false;
1016
1017                 uPriority = (ntohs(*(USHORT *)(skb->data +
1018                                    sizeof(struct bcm_eth_header))) &
1019                                    0xF000) >> 13;
1020
1021                 if ((uPriority >= pstClassifierRule->usUserPriority[0]) &&
1022                                 (uPriority <=
1023                                  pstClassifierRule->usUserPriority[1]))
1024                         bClassificationSucceed = TRUE;
1025
1026                 if (!bClassificationSucceed)
1027                         return false;
1028         }
1029
1030         BCM_DEBUG_PRINT(Adapter,
1031                         DBG_TYPE_TX,
1032                         IPV4_DBG,
1033                         DBG_LVL_ALL,
1034                         "ETH CS 802.1 D  User Priority Rule Matched\n");
1035
1036         bClassificationSucceed = false;
1037
1038         if (pstClassifierRule->usValidityBitMap &
1039                         (1<<PKT_CLASSIFICATION_VLANID_VALID)) {
1040                 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
1041                                 return false;
1042
1043                 usVLANID = ntohs(*(USHORT *)(skb->data +
1044                                         sizeof(struct bcm_eth_header))) & 0xFFF;
1045
1046                 BCM_DEBUG_PRINT(Adapter,
1047                                 DBG_TYPE_TX,
1048                                 IPV4_DBG,
1049                                 DBG_LVL_ALL,
1050                                 "%s  Pkt VLANID %x Priority: %d\n",
1051                                 __func__,
1052                                 usVLANID,
1053                                 uPriority);
1054
1055                 if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
1056                         bClassificationSucceed = TRUE;
1057
1058                 if (!bClassificationSucceed)
1059                         return false;
1060         }
1061
1062         BCM_DEBUG_PRINT(Adapter,
1063                         DBG_TYPE_TX,
1064                         IPV4_DBG,
1065                         DBG_LVL_ALL,
1066                         "ETH CS 802.1 Q VLAN ID Rule Matched\n");
1067
1068         return TRUE;
1069 }
1070
1071
1072 static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,
1073                              struct sk_buff *skb,
1074                              struct bcm_eth_packet_info *pstEthCsPktInfo,
1075                              struct bcm_classifier_rule *pstClassifierRule,
1076                              B_UINT8 EthCSCupport)
1077 {
1078         bool bClassificationSucceed = false;
1079
1080         bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,
1081                         ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
1082         if (!bClassificationSucceed)
1083                 return false;
1084         BCM_DEBUG_PRINT(Adapter,
1085                         DBG_TYPE_TX,
1086                         IPV4_DBG,
1087                         DBG_LVL_ALL,
1088                         "ETH CS SrcMAC Matched\n");
1089
1090         bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,
1091                         ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
1092         if (!bClassificationSucceed)
1093                 return false;
1094         BCM_DEBUG_PRINT(Adapter,
1095                         DBG_TYPE_TX,
1096                         IPV4_DBG,
1097                         DBG_LVL_ALL,
1098                         "ETH CS DestMAC Matched\n");
1099
1100         /* classify on ETHType/802.2SAP TLV */
1101         bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,
1102                                                       skb,
1103                                                       pstEthCsPktInfo);
1104         if (!bClassificationSucceed)
1105                 return false;
1106
1107         BCM_DEBUG_PRINT(Adapter,
1108                         DBG_TYPE_TX,
1109                         IPV4_DBG,
1110                         DBG_LVL_ALL,
1111                         "ETH CS EthType/802.2SAP Matched\n");
1112
1113         /* classify on 802.1VLAN Header Parameters */
1114         bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,
1115                                                      skb,
1116                                                      pstEthCsPktInfo);
1117         if (!bClassificationSucceed)
1118                 return false;
1119         BCM_DEBUG_PRINT(Adapter,
1120                         DBG_TYPE_TX,
1121                         IPV4_DBG,
1122                         DBG_LVL_ALL,
1123                         "ETH CS 802.1 VLAN Rules Matched\n");
1124
1125         return bClassificationSucceed;
1126 }
1127
1128 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,
1129                             PVOID pvEthPayload,
1130                             struct bcm_eth_packet_info *pstEthCsPktInfo)
1131 {
1132         USHORT u16Etype = ntohs(
1133                         ((struct bcm_eth_header *)pvEthPayload)->u16Etype);
1134
1135         BCM_DEBUG_PRINT(Adapter,
1136                         DBG_TYPE_TX,
1137                         IPV4_DBG,
1138                         DBG_LVL_ALL,
1139                         "EthCSGetPktInfo : Eth Hdr Type : %X\n",
1140                         u16Etype);
1141         if (u16Etype > 0x5dc) {
1142                 BCM_DEBUG_PRINT(Adapter,
1143                                 DBG_TYPE_TX,
1144                                 IPV4_DBG,
1145                                 DBG_LVL_ALL,
1146                                 "EthCSGetPktInfo : ETH2 Frame\n");
1147                 /* ETH2 Frame */
1148                 if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) {
1149                         /* 802.1Q VLAN Header */
1150                         pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
1151                         u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType;
1152                         /* ((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority */
1153                 } else {
1154                         pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
1155                         u16Etype = ntohs(u16Etype);
1156                 }
1157         } else {
1158                 /* 802.2 LLC */
1159                 BCM_DEBUG_PRINT(Adapter,
1160                                 DBG_TYPE_TX,
1161                                 IPV4_DBG,
1162                                 DBG_LVL_ALL,
1163                                 "802.2 LLC Frame\n");
1164                 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
1165                 pstEthCsPktInfo->ucDSAP =
1166                         ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
1167                 if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) {
1168                         /* SNAP Frame */
1169                         pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
1170                         u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
1171                 }
1172         }
1173         if (u16Etype == ETHERNET_FRAMETYPE_IPV4)
1174                 pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet;
1175         else if (u16Etype == ETHERNET_FRAMETYPE_IPV6)
1176                 pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet;
1177         else
1178                 pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
1179
1180         pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype;
1181         BCM_DEBUG_PRINT(Adapter,
1182                         DBG_TYPE_TX,
1183                         IPV4_DBG,
1184                         DBG_LVL_ALL,
1185                         "EthCsPktInfo->eNwpktIPFrameType : %x\n",
1186                         pstEthCsPktInfo->eNwpktIPFrameType);
1187         BCM_DEBUG_PRINT(Adapter,
1188                         DBG_TYPE_TX,
1189                         IPV4_DBG,
1190                         DBG_LVL_ALL,
1191                         "EthCsPktInfo->eNwpktEthFrameType : %x\n",
1192                         pstEthCsPktInfo->eNwpktEthFrameType);
1193         BCM_DEBUG_PRINT(Adapter,
1194                         DBG_TYPE_TX,
1195                         IPV4_DBG,
1196                         DBG_LVL_ALL,
1197                         "EthCsPktInfo->usEtherType : %x\n",
1198                         pstEthCsPktInfo->usEtherType);
1199 }
1200