3 * This file contains the routines related to Quality of Service.
7 static void EThCSGetPktInfo(struct bcm_mini_adapter
*Adapter
,
9 struct bcm_eth_packet_info
*pstEthCsPktInfo
);
11 static bool EThCSClassifyPkt(struct bcm_mini_adapter
*Adapter
,
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
,
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
)
46 ucLoopIndex
< (pstClassifierRule
->ucIPSourceAddressLength
);
48 src_addr
= &pstClassifierRule
->stSrcIpAddress
;
49 BCM_DEBUG_PRINT(Adapter
,
53 "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x",
54 (UINT
)src_addr
->ulIpv4Mask
[ucLoopIndex
],
56 (UINT
)src_addr
->ulIpv6Addr
[ucLoopIndex
]);
58 if ((src_addr
->ulIpv4Mask
[ucLoopIndex
] & ulSrcIP
) ==
59 (src_addr
->ulIpv4Addr
[ucLoopIndex
] &
60 src_addr
->ulIpv4Mask
[ucLoopIndex
]))
63 BCM_DEBUG_PRINT(Adapter
,
67 "Src Ip Address Not Matched");
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
)
92 BCM_DEBUG_PRINT(Adapter
,
96 "Destination Ip Address 0x%x 0x%x 0x%x ",
98 (UINT
)dest_addr
->ulIpv4Mask
[ucLoopIndex
],
99 (UINT
)dest_addr
->ulIpv4Addr
[ucLoopIndex
]);
101 for (ucLoopIndex
= 0;
102 ucLoopIndex
< (pstClassifierRule
->ucIPDestinationAddressLength
);
104 if ((dest_addr
->ulIpv4Mask
[ucLoopIndex
] & ulDestIP
) ==
105 (dest_addr
->ulIpv4Addr
[ucLoopIndex
] &
106 dest_addr
->ulIpv4Mask
[ucLoopIndex
]))
109 BCM_DEBUG_PRINT(Adapter
,
113 "Destination Ip Address Not Matched");
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
)
136 if (((pstClassifierRule
->ucTosMask
& ucTypeOfService
) <=
137 pstClassifierRule
->ucTosHigh
) &&
138 ((pstClassifierRule
->ucTosMask
& ucTypeOfService
) >=
139 pstClassifierRule
->ucTosLow
))
142 BCM_DEBUG_PRINT(Adapter
,
146 "Type Of Service Not Matched");
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
,
164 UCHAR ucLoopIndex
= 0;
165 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
167 if (0 == pstClassifierRule
->ucProtocolLength
)
169 for (ucLoopIndex
= 0;
170 ucLoopIndex
< pstClassifierRule
->ucProtocolLength
;
172 BCM_DEBUG_PRINT(Adapter
,
176 "Protocol:0x%X Classification Protocol:0x%X",
178 pstClassifierRule
->ucProtocol
[ucLoopIndex
]);
179 if (pstClassifierRule
->ucProtocol
[ucLoopIndex
] == ucProtocol
)
182 BCM_DEBUG_PRINT(Adapter
,
186 "Protocol Not Matched");
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
,
204 UCHAR ucLoopIndex
= 0;
206 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
209 if (0 == pstClassifierRule
->ucSrcPortRangeLength
)
211 for (ucLoopIndex
= 0;
212 ucLoopIndex
< pstClassifierRule
->ucSrcPortRangeLength
;
214 if (ushSrcPort
<= pstClassifierRule
->usSrcPortRangeHi
[ucLoopIndex
] &&
215 ushSrcPort
>= pstClassifierRule
->usSrcPortRangeLo
[ucLoopIndex
])
218 BCM_DEBUG_PRINT(Adapter
,
222 "Src Port: %x Not Matched ",
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
,
241 UCHAR ucLoopIndex
= 0;
242 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
244 if (0 == pstClassifierRule
->ucDestPortRangeLength
)
247 for (ucLoopIndex
= 0;
248 ucLoopIndex
< pstClassifierRule
->ucDestPortRangeLength
;
250 BCM_DEBUG_PRINT(Adapter
,
254 "Matching Port:0x%X 0x%X 0x%X",
256 pstClassifierRule
->usDestPortRangeLo
[ucLoopIndex
],
257 pstClassifierRule
->usDestPortRangeHi
[ucLoopIndex
]);
259 if (ushDestPort
<= pstClassifierRule
->usDestPortRangeHi
[ucLoopIndex
] &&
260 ushDestPort
>= pstClassifierRule
->usDestPortRangeLo
[ucLoopIndex
])
263 BCM_DEBUG_PRINT(Adapter
,
267 "Dest Port: %x Not Matched",
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
,
278 struct bcm_classifier_rule
*pstClassifierRule
)
280 struct bcm_transport_header
*xprt_hdr
= NULL
;
281 bool bClassificationSucceed
= false;
283 BCM_DEBUG_PRINT(Adapter
,
289 xprt_hdr
= (struct bcm_transport_header
*)((PUCHAR
)iphd
+ sizeof(struct iphdr
));
291 BCM_DEBUG_PRINT(Adapter
,
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
)
304 BCM_DEBUG_PRINT(Adapter
,
309 if (pstClassifierRule
->bIpv6Protocol
)
312 /* Checking IP header parameter */
313 BCM_DEBUG_PRINT(Adapter
,
317 "Trying to match Source IP Address");
318 if (!MatchSrcIpAddress(pstClassifierRule
, iphd
->saddr
))
320 BCM_DEBUG_PRINT(Adapter
,
324 "Source IP Address Matched");
326 if (!MatchDestIpAddress(pstClassifierRule
, iphd
->daddr
))
328 BCM_DEBUG_PRINT(Adapter
,
332 "Destination IP Address Matched");
334 if (!MatchTos(pstClassifierRule
, iphd
->tos
)) {
335 BCM_DEBUG_PRINT(Adapter
,
339 "TOS Match failed\n");
342 BCM_DEBUG_PRINT(Adapter
,
348 if (!MatchProtocol(pstClassifierRule
, iphd
->protocol
))
350 BCM_DEBUG_PRINT(Adapter
,
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
;
364 /* Checking Transport Layer Header field if present */
365 BCM_DEBUG_PRINT(Adapter
,
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
)))
376 BCM_DEBUG_PRINT(Adapter
,
382 BCM_DEBUG_PRINT(Adapter
,
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
)))
394 bClassificationSucceed
= TRUE
;
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
,
411 "IpVersion4 <==========");
413 return bClassificationSucceed
;
416 VOID
PruneQueueAllSF(struct bcm_mini_adapter
*Adapter
)
420 for (iIndex
= 0; iIndex
< HiPriority
; iIndex
++) {
421 if (!Adapter
->PackInfo
[iIndex
].bValid
)
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
,
449 if (iIndex
== HiPriority
)
452 if (!Adapter
|| (iIndex
< 0) || (iIndex
> HiPriority
))
455 /* To Store the netdevice statistic */
456 netstats
= &Adapter
->dev
->stats
;
458 spin_lock_bh(&curr_pack_info
->SFQueueLock
);
461 /* while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost > */
462 /* SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { */
464 BCM_DEBUG_PRINT(Adapter
,
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
)
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
))
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
-=
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
,
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
,
520 "TotalPacketCount:%x",
521 atomic_read(&Adapter
->TotalPacketCount
));
522 BCM_DEBUG_PRINT(Adapter
,
529 VOID
flush_all_queues(struct bcm_mini_adapter
*Adapter
)
532 UINT uiTotalPacketLength
;
533 struct sk_buff
*PacketToDrop
= NULL
;
534 struct bcm_packet_info
*curr_packet_info
;
536 BCM_DEBUG_PRINT(Adapter
,
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
;
551 uiTotalPacketLength
= PacketToDrop
->len
;
552 netstats
->tx_dropped
++;
554 uiTotalPacketLength
= 0;
556 DEQUEUEPACKET(curr_packet_info
->FirstTxQueue
,
557 curr_packet_info
->LastTxQueue
);
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
,
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
,
589 USHORT
ClassifyPacket(struct bcm_mini_adapter
*Adapter
, struct sk_buff
*skb
)
592 struct bcm_classifier_rule
*pstClassifierRule
= NULL
;
593 struct bcm_eth_packet_info stEthCsPktInfo
;
594 PVOID pvEThPayload
= NULL
;
595 struct iphdr
*pIpHeader
= NULL
;
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
);
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
);
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
);
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
);
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
);
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
)
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;
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");
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;
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");
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;
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;
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
)
769 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
771 if (pstClassifierRule
->ucEthCSSrcMACLen
== 0)
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
]))
783 static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule
*pstClassifierRule
, PUCHAR Mac
)
786 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
788 if (pstClassifierRule
->ucEthCSDestMACLen
== 0)
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
]))
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))
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)
818 if (pstClassifierRule
->au8EthCSEtherType
[0] == 2) {
819 if (eEth802LLCFrame
!= pstEthCsPktInfo
->eNwpktEthFrameType
)
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])
834 static bool EthCSMatchVLANRules(struct bcm_classifier_rule
*pstClassifierRule
, struct sk_buff
*skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
)
836 bool bClassificationSucceed
= false;
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
)
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
)
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
)
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
)
879 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 Q VLAN ID Rule Matched\n");
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
)
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
)
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
)
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
)
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");
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 */
933 pstEthCsPktInfo
->eNwpktEthFrameType
= eEthOtherFrame
;
934 u16Etype
= ntohs(u16Etype
);
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) {
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
;
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
);