Staging: bcm: Qos.c: Line length / Whitespace cleanup in flush_all_queues()
[linux-2.6/btrfs-unstable.git] / drivers / staging / bcm / Qos.c
blob1608ba4fbb23d64030e5cfec23daed59f5242e00
1 /**
2 * @file Qos.C
3 * This file contains the routines related to Quality of Service.
4 */
5 #include "headers.h"
7 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,
8 PVOID pvEthPayload,
9 struct bcm_eth_packet_info *pstEthCsPktInfo);
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);
17 static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
18 struct bcm_classifier_rule *pstClassifierRule);
20 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex);
23 /*******************************************************************
24 * Function - MatchSrcIpAddress()
26 * Description - Checks whether the Source IP address from the packet
27 * matches with that of Queue.
29 * Parameters - pstClassifierRule: Pointer to the packet info structure.
30 * - ulSrcIP : Source IP address from the packet.
32 * Returns - TRUE(If address matches) else FAIL .
33 *********************************************************************/
34 static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,
35 ULONG ulSrcIP)
37 UCHAR ucLoopIndex = 0;
39 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
40 union u_ip_address *src_addr;
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]);
58 if ((src_addr->ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
59 (src_addr->ulIpv4Addr[ucLoopIndex] &
60 src_addr->ulIpv4Mask[ucLoopIndex]))
61 return TRUE;
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;
72 /*******************************************************************
73 * Function - MatchDestIpAddress()
75 * Description - Checks whether the Destination IP address from the packet
76 * matches with that of Queue.
78 * Parameters - pstClassifierRule: Pointer to the packet info structure.
79 * - ulDestIP : Destination IP address from the packet.
81 * Returns - TRUE(If address matches) else FAIL .
82 *********************************************************************/
83 static bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
85 UCHAR ucLoopIndex = 0;
86 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
87 union u_ip_address *dest_addr = &pstClassifierRule->stDestIpAddress;
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]);
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;
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;
118 /************************************************************************
119 * Function - MatchTos()
121 * Description - Checks the TOS from the packet matches with that of queue.
123 * Parameters - pstClassifierRule : Pointer to the packet info structure.
124 * - ucTypeOfService: TOS from the packet.
126 * Returns - TRUE(If address matches) else FAIL.
127 **************************************************************************/
128 static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule,
129 UCHAR ucTypeOfService)
131 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
133 if (3 != pstClassifierRule->ucIPTypeOfServiceLength)
134 return TRUE;
136 if (((pstClassifierRule->ucTosMask & ucTypeOfService) <=
137 pstClassifierRule->ucTosHigh) &&
138 ((pstClassifierRule->ucTosMask & ucTypeOfService) >=
139 pstClassifierRule->ucTosLow))
140 return TRUE;
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;
151 /***************************************************************************
152 * Function - MatchProtocol()
154 * Description - Checks the protocol from the packet matches with that of queue.
156 * Parameters - pstClassifierRule: Pointer to the packet info structure.
157 * - ucProtocol : Protocol from the packet.
159 * Returns - TRUE(If address matches) else FAIL.
160 ****************************************************************************/
161 bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,
162 UCHAR ucProtocol)
164 UCHAR ucLoopIndex = 0;
165 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
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;
182 BCM_DEBUG_PRINT(Adapter,
183 DBG_TYPE_TX,
184 IPV4_DBG,
185 DBG_LVL_ALL,
186 "Protocol Not Matched");
187 return false;
191 /***********************************************************************
192 * Function - MatchSrcPort()
194 * Description - Checks, Source port from the packet matches with that of queue.
196 * Parameters - pstClassifierRule: Pointer to the packet info structure.
197 * - ushSrcPort : Source port from the packet.
199 * Returns - TRUE(If address matches) else FAIL.
200 ***************************************************************************/
201 bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,
202 USHORT ushSrcPort)
204 UCHAR ucLoopIndex = 0;
206 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
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;
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;
228 /***********************************************************************
229 * Function - MatchDestPort()
231 * Description - Checks, Destination port from packet matches with that of queue.
233 * Parameters - pstClassifierRule: Pointer to the packet info structure.
234 * - ushDestPort : Destination port from the packet.
236 * Returns - TRUE(If address matches) else FAIL.
237 ***************************************************************************/
238 bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,
239 USHORT ushDestPort)
241 UCHAR ucLoopIndex = 0;
242 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
244 if (0 == pstClassifierRule->ucDestPortRangeLength)
245 return TRUE;
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]);
259 if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
260 ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
261 return TRUE;
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;
272 * @ingroup tx_functions
273 * Compares IPV4 Ip address and port number
274 * @return Queue Index.
276 static USHORT IpVersion4(struct bcm_mini_adapter *Adapter,
277 struct iphdr *iphd,
278 struct bcm_classifier_rule *pstClassifierRule)
280 struct bcm_transport_header *xprt_hdr = NULL;
281 bool bClassificationSucceed = false;
283 BCM_DEBUG_PRINT(Adapter,
284 DBG_TYPE_TX,
285 IPV4_DBG,
286 DBG_LVL_ALL,
287 "========>");
289 xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
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);
299 /* Checking classifier validity */
300 if (!pstClassifierRule->bUsed ||
301 pstClassifierRule->ucDirection == DOWNLINK_DIR)
302 goto out;
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;
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");
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");
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;
342 BCM_DEBUG_PRINT(Adapter,
343 DBG_TYPE_TX,
344 IPV4_DBG,
345 DBG_LVL_ALL,
346 "TOS Matched");
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");
357 * if protocol is not TCP or UDP then no
358 * need of comparing source port and destination port
360 if (iphd->protocol != TCP && iphd->protocol != UDP) {
361 bClassificationSucceed = TRUE;
362 goto out;
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);
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");
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);
390 if (!MatchDestPort(pstClassifierRule,
391 ntohs((iphd->protocol == UDP) ?
392 xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
393 goto out;
394 bClassificationSucceed = TRUE;
396 out:
397 if (TRUE == bClassificationSucceed) {
398 INT iMatchedSFQueueIndex = 0;
399 iMatchedSFQueueIndex =
400 SearchSfid(Adapter, pstClassifierRule->ulSFID);
401 if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
402 bClassificationSucceed = false;
403 else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
404 bClassificationSucceed = false;
407 BCM_DEBUG_PRINT(Adapter,
408 DBG_TYPE_TX,
409 IPV4_DBG,
410 DBG_LVL_ALL,
411 "IpVersion4 <==========");
413 return bClassificationSucceed;
416 VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter)
418 UINT iIndex = 0;
420 for (iIndex = 0; iIndex < HiPriority; iIndex++) {
421 if (!Adapter->PackInfo[iIndex].bValid)
422 continue;
424 PruneQueue(Adapter, iIndex);
430 * @ingroup tx_functions
431 * This function checks if the max queue size for a queue
432 * is less than number of bytes in the queue. If so -
433 * drops packets from the Head till the number of bytes is
434 * less than or equal to max queue size for the queue.
436 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
438 struct sk_buff *PacketToDrop = NULL;
439 struct net_device_stats *netstats;
440 struct bcm_packet_info *curr_pack_info = &Adapter->PackInfo[iIndex];
442 BCM_DEBUG_PRINT(Adapter,
443 DBG_TYPE_TX,
444 PRUNE_QUEUE,
445 DBG_LVL_ALL,
446 "=====> Index %d",
447 iIndex);
449 if (iIndex == HiPriority)
450 return;
452 if (!Adapter || (iIndex < 0) || (iIndex > HiPriority))
453 return;
455 /* To Store the netdevice statistic */
456 netstats = &Adapter->dev->stats;
458 spin_lock_bh(&curr_pack_info->SFQueueLock);
460 while (1) {
461 /* while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost > */
462 /* SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { */
464 BCM_DEBUG_PRINT(Adapter,
465 DBG_TYPE_TX,
466 PRUNE_QUEUE,
467 DBG_LVL_ALL,
468 "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
469 curr_pack_info->uiCurrentBytesOnHost,
470 curr_pack_info->uiMaxBucketSize);
472 PacketToDrop = curr_pack_info->FirstTxQueue;
474 if (PacketToDrop == NULL)
475 break;
476 if ((curr_pack_info->uiCurrentPacketsOnHost <
477 SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
478 ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb) +
479 SKB_CB_LATENCY_OFFSET))/HZ) <=
480 curr_pack_info->uiMaxLatency))
481 break;
483 if (PacketToDrop) {
484 if (netif_msg_tx_err(Adapter))
485 pr_info(PFX "%s: tx queue %d overlimit\n",
486 Adapter->dev->name, iIndex);
488 netstats->tx_dropped++;
490 DEQUEUEPACKET(curr_pack_info->FirstTxQueue,
491 curr_pack_info->LastTxQueue);
492 /* update current bytes and packets count */
493 curr_pack_info->uiCurrentBytesOnHost -=
494 PacketToDrop->len;
495 curr_pack_info->uiCurrentPacketsOnHost--;
496 /* update dropped bytes and packets counts */
497 curr_pack_info->uiDroppedCountBytes += PacketToDrop->len;
498 curr_pack_info->uiDroppedCountPackets++;
499 dev_kfree_skb(PacketToDrop);
503 BCM_DEBUG_PRINT(Adapter,
504 DBG_TYPE_TX,
505 PRUNE_QUEUE,
506 DBG_LVL_ALL,
507 "Dropped Bytes:%x Dropped Packets:%x",
508 curr_pack_info->uiDroppedCountBytes,
509 curr_pack_info->uiDroppedCountPackets);
511 atomic_dec(&Adapter->TotalPacketCount);
514 spin_unlock_bh(&curr_pack_info->SFQueueLock);
516 BCM_DEBUG_PRINT(Adapter,
517 DBG_TYPE_TX,
518 PRUNE_QUEUE,
519 DBG_LVL_ALL,
520 "TotalPacketCount:%x",
521 atomic_read(&Adapter->TotalPacketCount));
522 BCM_DEBUG_PRINT(Adapter,
523 DBG_TYPE_TX,
524 PRUNE_QUEUE,
525 DBG_LVL_ALL,
526 "<=====");
529 VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
531 INT iQIndex;
532 UINT uiTotalPacketLength;
533 struct sk_buff *PacketToDrop = NULL;
534 struct bcm_packet_info *curr_packet_info;
536 BCM_DEBUG_PRINT(Adapter,
537 DBG_TYPE_OTHERS,
538 DUMP_INFO,
539 DBG_LVL_ALL,
540 "=====>");
542 /* down(&Adapter->data_packet_queue_lock); */
543 for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) {
544 struct net_device_stats *netstats = &Adapter->dev->stats;
545 curr_packet_info = &Adapter->PackInfo[iQIndex];
547 spin_lock_bh(&curr_packet_info->SFQueueLock);
548 while (curr_packet_info->FirstTxQueue) {
549 PacketToDrop = curr_packet_info->FirstTxQueue;
550 if (PacketToDrop) {
551 uiTotalPacketLength = PacketToDrop->len;
552 netstats->tx_dropped++;
553 } else
554 uiTotalPacketLength = 0;
556 DEQUEUEPACKET(curr_packet_info->FirstTxQueue,
557 curr_packet_info->LastTxQueue);
559 /* Free the skb */
560 dev_kfree_skb(PacketToDrop);
562 /* update current bytes and packets count */
563 curr_packet_info->uiCurrentBytesOnHost -= uiTotalPacketLength;
564 curr_packet_info->uiCurrentPacketsOnHost--;
566 /* update dropped bytes and packets counts */
567 curr_packet_info->uiDroppedCountBytes += uiTotalPacketLength;
568 curr_packet_info->uiDroppedCountPackets++;
570 BCM_DEBUG_PRINT(Adapter,
571 DBG_TYPE_OTHERS,
572 DUMP_INFO,
573 DBG_LVL_ALL,
574 "Dropped Bytes:%x Dropped Packets:%x",
575 curr_packet_info->uiDroppedCountBytes,
576 curr_packet_info->uiDroppedCountPackets);
577 atomic_dec(&Adapter->TotalPacketCount);
579 spin_unlock_bh(&curr_packet_info->SFQueueLock);
581 /* up(&Adapter->data_packet_queue_lock); */
582 BCM_DEBUG_PRINT(Adapter,
583 DBG_TYPE_OTHERS,
584 DUMP_INFO,
585 DBG_LVL_ALL,
586 "<=====");
589 USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
591 INT uiLoopIndex = 0;
592 struct bcm_classifier_rule *pstClassifierRule = NULL;
593 struct bcm_eth_packet_info stEthCsPktInfo;
594 PVOID pvEThPayload = NULL;
595 struct iphdr *pIpHeader = NULL;
596 INT uiSfIndex = 0;
597 USHORT usIndex = Adapter->usBestEffortQueueIndex;
598 bool bFragmentedPkt = false, bClassificationSucceed = false;
599 USHORT usCurrFragment = 0;
601 struct bcm_tcp_header *pTcpHeader;
602 UCHAR IpHeaderLength;
603 UCHAR TcpHeaderLength;
605 pvEThPayload = skb->data;
606 *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = 0;
607 EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
609 switch (stEthCsPktInfo.eNwpktEthFrameType) {
610 case eEth802LLCFrame:
611 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n");
612 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
613 break;
614 case eEth802LLCSNAPFrame:
615 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n");
616 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_snap_frame);
617 break;
618 case eEth802QVLANFrame:
619 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n");
620 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
621 break;
622 case eEthOtherFrame:
623 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n");
624 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
625 break;
626 default:
627 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n");
628 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
629 break;
632 if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) {
633 usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
634 if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
635 bFragmentedPkt = TRUE;
637 if (bFragmentedPkt) {
638 /* Fragmented Packet. Get Frag Classifier Entry. */
639 pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
640 if (pstClassifierRule) {
641 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt");
642 bClassificationSucceed = TRUE;
644 if (!(ntohs(pIpHeader->frag_off) & IP_MF)) {
645 /* Fragmented Last packet . Remove Frag Classifier Entry */
646 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt");
647 DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
652 for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) {
653 if (bClassificationSucceed)
654 break;
656 * Iterate through all classifiers which are already in order of priority
657 * to classify the packet until match found
659 if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
660 bClassificationSucceed = false;
661 continue;
663 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
665 if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
666 bClassificationSucceed = false; /* cannot be processed for classification. */
667 continue; /* it is a down link connection */
670 pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
672 uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
673 if (uiSfIndex >= NO_OF_QUEUES) {
674 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Queue Not Valid. SearchSfid for this classifier Failed\n");
675 continue;
678 if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
680 if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
681 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
682 bClassificationSucceed = false;
683 continue;
688 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID);
689 bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
691 if (!bClassificationSucceed) {
692 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Ethernet CS Classification Failed\n");
693 continue;
695 } else { /* No ETH Supported on this SF */
696 if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
697 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
698 bClassificationSucceed = false;
699 continue;
703 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Proceeding to IP CS Clasification");
705 if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
707 if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
708 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
709 bClassificationSucceed = false;
710 continue;
712 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n");
713 DumpFullPacket((PUCHAR)pIpHeader, 20);
715 if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
716 bClassificationSucceed = IpVersion4(Adapter, pIpHeader, pstClassifierRule);
717 else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
718 bClassificationSucceed = IpVersion6(Adapter, pIpHeader, pstClassifierRule);
722 if (bClassificationSucceed == TRUE) {
723 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
725 /* Store The matched Classifier in SKB */
726 *((UINT32 *)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex;
727 if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len)) {
728 IpHeaderLength = pIpHeader->ihl;
729 pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
730 TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
732 if ((pTcpHeader->ucFlags & TCP_ACK) &&
733 (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
734 *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK;
737 usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
738 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex);
741 * If this is the first fragment of a Fragmented pkt,
742 * add this CF. Only This CF should be used for all other
743 * fragment of this Pkt.
745 if (bFragmentedPkt && (usCurrFragment == 0)) {
747 * First Fragment of Fragmented Packet.
748 * Create Frag CLS Entry
750 struct bcm_fragmented_packet_info stFragPktInfo;
752 stFragPktInfo.bUsed = TRUE;
753 stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr;
754 stFragPktInfo.usIpIdentification = pIpHeader->id;
755 stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule;
756 stFragPktInfo.bOutOfOrderFragment = false;
757 AddFragIPClsEntry(Adapter, &stFragPktInfo);
763 return (bClassificationSucceed ? usIndex : INVALID_QUEUE_INDEX);
766 static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
768 UINT i = 0;
769 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
771 if (pstClassifierRule->ucEthCSSrcMACLen == 0)
772 return TRUE;
773 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __func__);
774 for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
775 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
776 if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
777 (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
778 return false;
780 return TRUE;
783 static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
785 UINT i = 0;
786 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
788 if (pstClassifierRule->ucEthCSDestMACLen == 0)
789 return TRUE;
790 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __func__);
791 for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
792 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
793 if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
794 (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
795 return false;
797 return TRUE;
800 static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff *skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
802 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
804 if ((pstClassifierRule->ucEtherTypeLen == 0) ||
805 (pstClassifierRule->au8EthCSEtherType[0] == 0))
806 return TRUE;
808 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __func__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]);
809 if (pstClassifierRule->au8EthCSEtherType[0] == 1) {
810 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n", __func__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]);
812 if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
813 return TRUE;
814 else
815 return false;
818 if (pstClassifierRule->au8EthCSEtherType[0] == 2) {
819 if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
820 return false;
822 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n", __func__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]);
823 if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
824 return TRUE;
825 else
826 return false;
830 return false;
834 static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff *skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
836 bool bClassificationSucceed = false;
837 USHORT usVLANID;
838 B_UINT8 uPriority = 0;
839 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
841 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n", __func__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID);
844 * In case FW didn't receive the TLV,
845 * the priority field should be ignored
847 if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
848 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
849 return false;
851 uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13;
853 if ((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
854 bClassificationSucceed = TRUE;
856 if (!bClassificationSucceed)
857 return false;
860 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 D User Priority Rule Matched\n");
862 bClassificationSucceed = false;
864 if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID)) {
865 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
866 return false;
868 usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF;
870 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n", __func__, usVLANID, uPriority);
872 if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
873 bClassificationSucceed = TRUE;
875 if (!bClassificationSucceed)
876 return false;
879 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 Q VLAN ID Rule Matched\n");
881 return TRUE;
885 static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff *skb,
886 struct bcm_eth_packet_info *pstEthCsPktInfo,
887 struct bcm_classifier_rule *pstClassifierRule,
888 B_UINT8 EthCSCupport)
890 bool bClassificationSucceed = false;
892 bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
893 if (!bClassificationSucceed)
894 return false;
895 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n");
897 bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
898 if (!bClassificationSucceed)
899 return false;
900 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n");
902 /* classify on ETHType/802.2SAP TLV */
903 bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo);
904 if (!bClassificationSucceed)
905 return false;
907 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS EthType/802.2SAP Matched\n");
909 /* classify on 802.1VLAN Header Parameters */
910 bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo);
911 if (!bClassificationSucceed)
912 return false;
913 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 VLAN Rules Matched\n");
915 return bClassificationSucceed;
918 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload,
919 struct bcm_eth_packet_info *pstEthCsPktInfo)
921 USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype);
923 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype);
924 if (u16Etype > 0x5dc) {
925 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n");
926 /* ETH2 Frame */
927 if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) {
928 /* 802.1Q VLAN Header */
929 pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
930 u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType;
931 /* ((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority */
932 } else {
933 pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
934 u16Etype = ntohs(u16Etype);
936 } else {
937 /* 802.2 LLC */
938 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n");
939 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
940 pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
941 if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) {
942 /* SNAP Frame */
943 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
944 u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
947 if (u16Etype == ETHERNET_FRAMETYPE_IPV4)
948 pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet;
949 else if (u16Etype == ETHERNET_FRAMETYPE_IPV6)
950 pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet;
951 else
952 pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
954 pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype;
955 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo->eNwpktIPFrameType);
956 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo->eNwpktEthFrameType);
957 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo->usEtherType);