3 This file contains the routines related to Quality of Service.
7 static void EThCSGetPktInfo(struct bcm_mini_adapter
*Adapter
, PVOID pvEthPayload
, struct bcm_eth_packet_info
*pstEthCsPktInfo
);
8 static bool EThCSClassifyPkt(struct bcm_mini_adapter
*Adapter
, struct sk_buff
* skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
, struct bcm_classifier_rule
*pstClassifierRule
, B_UINT8 EthCSCupport
);
10 static USHORT
IpVersion4(struct bcm_mini_adapter
*Adapter
, struct iphdr
*iphd
,
11 struct bcm_classifier_rule
*pstClassifierRule
);
13 static VOID
PruneQueue(struct bcm_mini_adapter
*Adapter
, INT iIndex
);
16 /*******************************************************************
17 * Function - MatchSrcIpAddress()
19 * Description - Checks whether the Source IP address from the packet
20 * matches with that of Queue.
22 * Parameters - pstClassifierRule: Pointer to the packet info structure.
23 * - ulSrcIP : Source IP address from the packet.
25 * Returns - TRUE(If address matches) else FAIL .
26 *********************************************************************/
27 static bool MatchSrcIpAddress(struct bcm_classifier_rule
*pstClassifierRule
, ULONG ulSrcIP
)
29 UCHAR ucLoopIndex
= 0;
31 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
33 ulSrcIP
= ntohl(ulSrcIP
);
34 if (0 == pstClassifierRule
->ucIPSourceAddressLength
)
36 for (ucLoopIndex
= 0; ucLoopIndex
< (pstClassifierRule
->ucIPSourceAddressLength
); ucLoopIndex
++)
38 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT
)pstClassifierRule
->stSrcIpAddress
.ulIpv4Mask
[ucLoopIndex
], (UINT
)ulSrcIP
, (UINT
)pstClassifierRule
->stSrcIpAddress
.ulIpv6Addr
[ucLoopIndex
]);
39 if ((pstClassifierRule
->stSrcIpAddress
.ulIpv4Mask
[ucLoopIndex
] & ulSrcIP
) ==
40 (pstClassifierRule
->stSrcIpAddress
.ulIpv4Addr
[ucLoopIndex
] & pstClassifierRule
->stSrcIpAddress
.ulIpv4Mask
[ucLoopIndex
]))
45 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Src Ip Address Not Matched");
50 /*******************************************************************
51 * Function - MatchDestIpAddress()
53 * Description - Checks whether the Destination IP address from the packet
54 * matches with that of Queue.
56 * Parameters - pstClassifierRule: Pointer to the packet info structure.
57 * - ulDestIP : Destination IP address from the packet.
59 * Returns - TRUE(If address matches) else FAIL .
60 *********************************************************************/
61 static bool MatchDestIpAddress(struct bcm_classifier_rule
*pstClassifierRule
, ULONG ulDestIP
)
63 UCHAR ucLoopIndex
= 0;
64 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
66 ulDestIP
= ntohl(ulDestIP
);
67 if (0 == pstClassifierRule
->ucIPDestinationAddressLength
)
69 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT
)ulDestIP
, (UINT
)pstClassifierRule
->stDestIpAddress
.ulIpv4Mask
[ucLoopIndex
], (UINT
)pstClassifierRule
->stDestIpAddress
.ulIpv4Addr
[ucLoopIndex
]);
71 for (ucLoopIndex
= 0; ucLoopIndex
< (pstClassifierRule
->ucIPDestinationAddressLength
); ucLoopIndex
++)
73 if ((pstClassifierRule
->stDestIpAddress
.ulIpv4Mask
[ucLoopIndex
] & ulDestIP
) ==
74 (pstClassifierRule
->stDestIpAddress
.ulIpv4Addr
[ucLoopIndex
] & pstClassifierRule
->stDestIpAddress
.ulIpv4Mask
[ucLoopIndex
]))
79 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination Ip Address Not Matched");
84 /************************************************************************
85 * Function - MatchTos()
87 * Description - Checks the TOS from the packet matches with that of queue.
89 * Parameters - pstClassifierRule : Pointer to the packet info structure.
90 * - ucTypeOfService: TOS from the packet.
92 * Returns - TRUE(If address matches) else FAIL.
93 **************************************************************************/
94 static bool MatchTos(struct bcm_classifier_rule
*pstClassifierRule
, UCHAR ucTypeOfService
)
97 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
98 if (3 != pstClassifierRule
->ucIPTypeOfServiceLength
)
101 if (((pstClassifierRule
->ucTosMask
& ucTypeOfService
) <= pstClassifierRule
->ucTosHigh
) && ((pstClassifierRule
->ucTosMask
& ucTypeOfService
) >= pstClassifierRule
->ucTosLow
))
105 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Type Of Service Not Matched");
110 /***************************************************************************
111 * Function - MatchProtocol()
113 * Description - Checks the protocol from the packet matches with that of queue.
115 * Parameters - pstClassifierRule: Pointer to the packet info structure.
116 * - ucProtocol : Protocol from the packet.
118 * Returns - TRUE(If address matches) else FAIL.
119 ****************************************************************************/
120 bool MatchProtocol(struct bcm_classifier_rule
*pstClassifierRule
, UCHAR ucProtocol
)
122 UCHAR ucLoopIndex
= 0;
123 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
124 if (0 == pstClassifierRule
->ucProtocolLength
)
126 for (ucLoopIndex
= 0; ucLoopIndex
< pstClassifierRule
->ucProtocolLength
; ucLoopIndex
++)
128 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol
, pstClassifierRule
->ucProtocol
[ucLoopIndex
]);
129 if (pstClassifierRule
->ucProtocol
[ucLoopIndex
] == ucProtocol
)
134 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Protocol Not Matched");
139 /***********************************************************************
140 * Function - MatchSrcPort()
142 * Description - Checks, Source port from the packet matches with that of queue.
144 * Parameters - pstClassifierRule: Pointer to the packet info structure.
145 * - ushSrcPort : Source port from the packet.
147 * Returns - TRUE(If address matches) else FAIL.
148 ***************************************************************************/
149 bool MatchSrcPort(struct bcm_classifier_rule
*pstClassifierRule
, USHORT ushSrcPort
)
151 UCHAR ucLoopIndex
= 0;
153 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
156 if (0 == pstClassifierRule
->ucSrcPortRangeLength
)
158 for (ucLoopIndex
= 0; ucLoopIndex
< pstClassifierRule
->ucSrcPortRangeLength
; ucLoopIndex
++)
160 if (ushSrcPort
<= pstClassifierRule
->usSrcPortRangeHi
[ucLoopIndex
] &&
161 ushSrcPort
>= pstClassifierRule
->usSrcPortRangeLo
[ucLoopIndex
])
166 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Src Port: %x Not Matched ", ushSrcPort
);
171 /***********************************************************************
172 * Function - MatchDestPort()
174 * Description - Checks, Destination port from packet matches with that of queue.
176 * Parameters - pstClassifierRule: Pointer to the packet info structure.
177 * - ushDestPort : Destination port from the packet.
179 * Returns - TRUE(If address matches) else FAIL.
180 ***************************************************************************/
181 bool MatchDestPort(struct bcm_classifier_rule
*pstClassifierRule
, USHORT ushDestPort
)
183 UCHAR ucLoopIndex
= 0;
184 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
186 if (0 == pstClassifierRule
->ucDestPortRangeLength
)
189 for (ucLoopIndex
= 0; ucLoopIndex
< pstClassifierRule
->ucDestPortRangeLength
; ucLoopIndex
++)
191 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Matching Port:0x%X 0x%X 0x%X", ushDestPort
, pstClassifierRule
->usDestPortRangeLo
[ucLoopIndex
], pstClassifierRule
->usDestPortRangeHi
[ucLoopIndex
]);
193 if (ushDestPort
<= pstClassifierRule
->usDestPortRangeHi
[ucLoopIndex
] &&
194 ushDestPort
>= pstClassifierRule
->usDestPortRangeLo
[ucLoopIndex
])
199 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Dest Port: %x Not Matched", ushDestPort
);
203 @ingroup tx_functions
204 Compares IPV4 Ip address and port number
207 static USHORT
IpVersion4(struct bcm_mini_adapter
*Adapter
,
209 struct bcm_classifier_rule
*pstClassifierRule
)
211 struct bcm_transport_header
*xprt_hdr
= NULL
;
212 bool bClassificationSucceed
= false;
214 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "========>");
216 xprt_hdr
= (struct bcm_transport_header
*)((PUCHAR
)iphd
+ sizeof(struct iphdr
));
219 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Trying to see Direction = %d %d",
220 pstClassifierRule
->ucDirection
,
221 pstClassifierRule
->usVCID_Value
);
223 //Checking classifier validity
224 if (!pstClassifierRule
->bUsed
|| pstClassifierRule
->ucDirection
== DOWNLINK_DIR
)
227 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "is IPv6 check!");
228 if (pstClassifierRule
->bIpv6Protocol
)
231 //**************Checking IP header parameter**************************//
232 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Trying to match Source IP Address");
233 if (!MatchSrcIpAddress(pstClassifierRule
, iphd
->saddr
))
235 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Source IP Address Matched");
237 if (!MatchDestIpAddress(pstClassifierRule
, iphd
->daddr
))
239 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination IP Address Matched");
241 if (!MatchTos(pstClassifierRule
, iphd
->tos
)) {
242 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "TOS Match failed\n");
245 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "TOS Matched");
247 if (!MatchProtocol(pstClassifierRule
, iphd
->protocol
))
249 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Protocol Matched");
251 //if protocol is not TCP or UDP then no need of comparing source port and destination port
252 if (iphd
->protocol
!= TCP
&& iphd
->protocol
!= UDP
) {
253 bClassificationSucceed
= TRUE
;
256 //******************Checking Transport Layer Header field if present *****************//
257 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Source Port %04x",
258 (iphd
->protocol
== UDP
) ? xprt_hdr
->uhdr
.source
: xprt_hdr
->thdr
.source
);
260 if (!MatchSrcPort(pstClassifierRule
,
261 ntohs((iphd
->protocol
== UDP
) ?
262 xprt_hdr
->uhdr
.source
: xprt_hdr
->thdr
.source
)))
264 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Src Port Matched");
266 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination Port %04x",
267 (iphd
->protocol
== UDP
) ? xprt_hdr
->uhdr
.dest
:
268 xprt_hdr
->thdr
.dest
);
269 if (!MatchDestPort(pstClassifierRule
,
270 ntohs((iphd
->protocol
== UDP
) ?
271 xprt_hdr
->uhdr
.dest
: xprt_hdr
->thdr
.dest
)))
273 bClassificationSucceed
= TRUE
;
276 if (TRUE
== bClassificationSucceed
)
278 INT iMatchedSFQueueIndex
= 0;
279 iMatchedSFQueueIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
280 if (iMatchedSFQueueIndex
>= NO_OF_QUEUES
)
282 bClassificationSucceed
= false;
286 if (false == Adapter
->PackInfo
[iMatchedSFQueueIndex
].bActive
)
288 bClassificationSucceed
= false;
293 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "IpVersion4 <==========");
295 return bClassificationSucceed
;
298 VOID
PruneQueueAllSF(struct bcm_mini_adapter
*Adapter
)
302 for (iIndex
= 0; iIndex
< HiPriority
; iIndex
++)
304 if (!Adapter
->PackInfo
[iIndex
].bValid
)
307 PruneQueue(Adapter
, iIndex
);
313 @ingroup tx_functions
314 This function checks if the max queue size for a queue
315 is less than number of bytes in the queue. If so -
316 drops packets from the Head till the number of bytes is
317 less than or equal to max queue size for the queue.
319 static VOID
PruneQueue(struct bcm_mini_adapter
*Adapter
, INT iIndex
)
321 struct sk_buff
* PacketToDrop
= NULL
;
322 struct net_device_stats
*netstats
;
324 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "=====> Index %d", iIndex
);
326 if (iIndex
== HiPriority
)
329 if (!Adapter
|| (iIndex
< 0) || (iIndex
> HiPriority
))
332 /* To Store the netdevice statistic */
333 netstats
= &Adapter
->dev
->stats
;
335 spin_lock_bh(&Adapter
->PackInfo
[iIndex
].SFQueueLock
);
338 // while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
339 // SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
341 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
342 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
,
343 Adapter
->PackInfo
[iIndex
].uiMaxBucketSize
);
345 PacketToDrop
= Adapter
->PackInfo
[iIndex
].FirstTxQueue
;
347 if (PacketToDrop
== NULL
)
349 if ((Adapter
->PackInfo
[iIndex
].uiCurrentPacketsOnHost
< SF_MAX_ALLOWED_PACKETS_TO_BACKUP
) &&
350 ((1000*(jiffies
- *((B_UINT32
*)(PacketToDrop
->cb
)+SKB_CB_LATENCY_OFFSET
))/HZ
) <= Adapter
->PackInfo
[iIndex
].uiMaxLatency
))
355 if (netif_msg_tx_err(Adapter
))
356 pr_info(PFX
"%s: tx queue %d overlimit\n",
357 Adapter
->dev
->name
, iIndex
);
359 netstats
->tx_dropped
++;
361 DEQUEUEPACKET(Adapter
->PackInfo
[iIndex
].FirstTxQueue
,
362 Adapter
->PackInfo
[iIndex
].LastTxQueue
);
363 /// update current bytes and packets count
364 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
-=
366 Adapter
->PackInfo
[iIndex
].uiCurrentPacketsOnHost
--;
367 /// update dropped bytes and packets counts
368 Adapter
->PackInfo
[iIndex
].uiDroppedCountBytes
+= PacketToDrop
->len
;
369 Adapter
->PackInfo
[iIndex
].uiDroppedCountPackets
++;
370 dev_kfree_skb(PacketToDrop
);
374 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "Dropped Bytes:%x Dropped Packets:%x",
375 Adapter
->PackInfo
[iIndex
].uiDroppedCountBytes
,
376 Adapter
->PackInfo
[iIndex
].uiDroppedCountPackets
);
378 atomic_dec(&Adapter
->TotalPacketCount
);
381 spin_unlock_bh(&Adapter
->PackInfo
[iIndex
].SFQueueLock
);
383 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "TotalPacketCount:%x",
384 atomic_read(&Adapter
->TotalPacketCount
));
385 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "<=====");
388 VOID
flush_all_queues(struct bcm_mini_adapter
*Adapter
)
391 UINT uiTotalPacketLength
;
392 struct sk_buff
* PacketToDrop
= NULL
;
394 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "=====>");
396 // down(&Adapter->data_packet_queue_lock);
397 for (iQIndex
= LowPriority
; iQIndex
< HiPriority
; iQIndex
++)
399 struct net_device_stats
*netstats
= &Adapter
->dev
->stats
;
401 spin_lock_bh(&Adapter
->PackInfo
[iQIndex
].SFQueueLock
);
402 while (Adapter
->PackInfo
[iQIndex
].FirstTxQueue
)
404 PacketToDrop
= Adapter
->PackInfo
[iQIndex
].FirstTxQueue
;
407 uiTotalPacketLength
= PacketToDrop
->len
;
408 netstats
->tx_dropped
++;
411 uiTotalPacketLength
= 0;
413 DEQUEUEPACKET(Adapter
->PackInfo
[iQIndex
].FirstTxQueue
,
414 Adapter
->PackInfo
[iQIndex
].LastTxQueue
);
417 dev_kfree_skb(PacketToDrop
);
419 /// update current bytes and packets count
420 Adapter
->PackInfo
[iQIndex
].uiCurrentBytesOnHost
-= uiTotalPacketLength
;
421 Adapter
->PackInfo
[iQIndex
].uiCurrentPacketsOnHost
--;
423 /// update dropped bytes and packets counts
424 Adapter
->PackInfo
[iQIndex
].uiDroppedCountBytes
+= uiTotalPacketLength
;
425 Adapter
->PackInfo
[iQIndex
].uiDroppedCountPackets
++;
427 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "Dropped Bytes:%x Dropped Packets:%x",
428 Adapter
->PackInfo
[iQIndex
].uiDroppedCountBytes
,
429 Adapter
->PackInfo
[iQIndex
].uiDroppedCountPackets
);
430 atomic_dec(&Adapter
->TotalPacketCount
);
432 spin_unlock_bh(&Adapter
->PackInfo
[iQIndex
].SFQueueLock
);
434 // up(&Adapter->data_packet_queue_lock);
435 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "<=====");
438 USHORT
ClassifyPacket(struct bcm_mini_adapter
*Adapter
, struct sk_buff
* skb
)
441 struct bcm_classifier_rule
*pstClassifierRule
= NULL
;
442 struct bcm_eth_packet_info stEthCsPktInfo
;
443 PVOID pvEThPayload
= NULL
;
444 struct iphdr
*pIpHeader
= NULL
;
446 USHORT usIndex
= Adapter
->usBestEffortQueueIndex
;
447 bool bFragmentedPkt
= false, bClassificationSucceed
= false;
448 USHORT usCurrFragment
= 0;
450 struct bcm_tcp_header
*pTcpHeader
;
451 UCHAR IpHeaderLength
;
452 UCHAR TcpHeaderLength
;
454 pvEThPayload
= skb
->data
;
455 *((UINT32
*) (skb
->cb
) +SKB_CB_TCPACK_OFFSET
) = 0;
456 EThCSGetPktInfo(Adapter
, pvEThPayload
, &stEthCsPktInfo
);
458 switch (stEthCsPktInfo
.eNwpktEthFrameType
)
460 case eEth802LLCFrame
:
462 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802LLCFrame\n");
463 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_llc_frame
);
467 case eEth802LLCSNAPFrame
:
469 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802LLC SNAP Frame\n");
470 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_llc_snap_frame
);
473 case eEth802QVLANFrame
:
475 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802.1Q VLANFrame\n");
476 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_q_frame
);
481 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : ETH Other Frame\n");
482 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_ethernet2_frame
);
487 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : Unrecognized ETH Frame\n");
488 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_ethernet2_frame
);
493 if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv4Packet
)
495 usCurrFragment
= (ntohs(pIpHeader
->frag_off
) & IP_OFFSET
);
496 if ((ntohs(pIpHeader
->frag_off
) & IP_MF
) || usCurrFragment
)
497 bFragmentedPkt
= TRUE
;
501 //Fragmented Packet. Get Frag Classifier Entry.
502 pstClassifierRule
= GetFragIPClsEntry(Adapter
, pIpHeader
->id
, pIpHeader
->saddr
);
503 if (pstClassifierRule
)
505 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "It is next Fragmented pkt");
506 bClassificationSucceed
= TRUE
;
508 if (!(ntohs(pIpHeader
->frag_off
) & IP_MF
))
510 //Fragmented Last packet . Remove Frag Classifier Entry
511 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "This is the last fragmented Pkt");
512 DelFragIPClsEntry(Adapter
, pIpHeader
->id
, pIpHeader
->saddr
);
517 for (uiLoopIndex
= MAX_CLASSIFIERS
- 1; uiLoopIndex
>= 0; uiLoopIndex
--)
519 if (bClassificationSucceed
)
521 //Iterate through all classifiers which are already in order of priority
522 //to classify the packet until match found
525 if (false == Adapter
->astClassifierTable
[uiLoopIndex
].bUsed
)
527 bClassificationSucceed
= false;
530 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex
);
532 if (0 == Adapter
->astClassifierTable
[uiLoopIndex
].ucDirection
)
534 bClassificationSucceed
= false;//cannot be processed for classification.
535 break; // it is a down link connection
538 pstClassifierRule
= &Adapter
->astClassifierTable
[uiLoopIndex
];
540 uiSfIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
541 if (uiSfIndex
>= NO_OF_QUEUES
) {
542 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Queue Not Valid. SearchSfid for this classifier Failed\n");
546 if (Adapter
->PackInfo
[uiSfIndex
].bEthCSSupport
)
549 if (eEthUnsupportedFrame
== stEthCsPktInfo
.eNwpktEthFrameType
)
551 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
552 bClassificationSucceed
= false;
558 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
);
559 bClassificationSucceed
= EThCSClassifyPkt(Adapter
, skb
, &stEthCsPktInfo
, pstClassifierRule
, Adapter
->PackInfo
[uiSfIndex
].bEthCSSupport
);
561 if (!bClassificationSucceed
)
563 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : Ethernet CS Classification Failed\n");
568 else // No ETH Supported on this SF
570 if (eEthOtherFrame
!= stEthCsPktInfo
.eNwpktEthFrameType
)
572 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");
573 bClassificationSucceed
= false;
578 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Proceeding to IP CS Clasification");
580 if (Adapter
->PackInfo
[uiSfIndex
].bIPCSSupport
)
583 if (stEthCsPktInfo
.eNwpktIPFrameType
== eNonIPPacket
)
585 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, " ClassifyPacket : Packet is Not an IP Packet\n");
586 bClassificationSucceed
= false;
589 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Dump IP Header :\n");
590 DumpFullPacket((PUCHAR
)pIpHeader
, 20);
592 if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv4Packet
)
593 bClassificationSucceed
= IpVersion4(Adapter
, pIpHeader
, pstClassifierRule
);
594 else if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv6Packet
)
595 bClassificationSucceed
= IpVersion6(Adapter
, pIpHeader
, pstClassifierRule
);
601 if (bClassificationSucceed
== TRUE
)
603 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "CF id : %d, SF ID is =%lu", pstClassifierRule
->uiClassifierRuleIndex
, pstClassifierRule
->ulSFID
);
605 //Store The matched Classifier in SKB
606 *((UINT32
*)(skb
->cb
)+SKB_CB_CLASSIFICATION_OFFSET
) = pstClassifierRule
->uiClassifierRuleIndex
;
607 if ((TCP
== pIpHeader
->protocol
) && !bFragmentedPkt
&& (ETH_AND_IP_HEADER_LEN
+ TCP_HEADER_LEN
<= skb
->len
))
609 IpHeaderLength
= pIpHeader
->ihl
;
610 pTcpHeader
= (struct bcm_tcp_header
*)(((PUCHAR
)pIpHeader
)+(IpHeaderLength
*4));
611 TcpHeaderLength
= GET_TCP_HEADER_LEN(pTcpHeader
->HeaderLength
);
613 if ((pTcpHeader
->ucFlags
& TCP_ACK
) &&
614 (ntohs(pIpHeader
->tot_len
) == (IpHeaderLength
*4)+(TcpHeaderLength
*4)))
616 *((UINT32
*) (skb
->cb
) + SKB_CB_TCPACK_OFFSET
) = TCP_ACK
;
620 usIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
621 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "index is =%d", usIndex
);
623 //If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt.
624 if (bFragmentedPkt
&& (usCurrFragment
== 0))
626 //First Fragment of Fragmented Packet. Create Frag CLS Entry
627 struct bcm_fragmented_packet_info stFragPktInfo
;
628 stFragPktInfo
.bUsed
= TRUE
;
629 stFragPktInfo
.ulSrcIpAddress
= pIpHeader
->saddr
;
630 stFragPktInfo
.usIpIdentification
= pIpHeader
->id
;
631 stFragPktInfo
.pstMatchedClassifierEntry
= pstClassifierRule
;
632 stFragPktInfo
.bOutOfOrderFragment
= false;
633 AddFragIPClsEntry(Adapter
, &stFragPktInfo
);
639 if (bClassificationSucceed
)
642 return INVALID_QUEUE_INDEX
;
645 static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule
*pstClassifierRule
, PUCHAR Mac
)
648 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
649 if (pstClassifierRule
->ucEthCSSrcMACLen
== 0)
651 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s\n", __FUNCTION__
);
652 for (i
= 0; i
< MAC_ADDRESS_SIZE
; i
++)
654 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
]);
655 if ((pstClassifierRule
->au8EThCSSrcMAC
[i
] & pstClassifierRule
->au8EThCSSrcMACMask
[i
]) !=
656 (Mac
[i
] & pstClassifierRule
->au8EThCSSrcMACMask
[i
]))
662 static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule
*pstClassifierRule
, PUCHAR Mac
)
665 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
666 if (pstClassifierRule
->ucEthCSDestMACLen
== 0)
668 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s\n", __FUNCTION__
);
669 for (i
= 0; i
< MAC_ADDRESS_SIZE
; i
++)
671 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
]);
672 if ((pstClassifierRule
->au8EThCSDestMAC
[i
] & pstClassifierRule
->au8EThCSDestMACMask
[i
]) !=
673 (Mac
[i
] & pstClassifierRule
->au8EThCSDestMACMask
[i
]))
679 static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule
*pstClassifierRule
, struct sk_buff
* skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
)
681 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
682 if ((pstClassifierRule
->ucEtherTypeLen
== 0) ||
683 (pstClassifierRule
->au8EthCSEtherType
[0] == 0))
686 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __FUNCTION__
, pstEthCsPktInfo
->usEtherType
, pstClassifierRule
->au8EthCSEtherType
[0]);
687 if (pstClassifierRule
->au8EthCSEtherType
[0] == 1)
689 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s CLS EtherType[1]:%x EtherType[2]:%x\n", __FUNCTION__
, pstClassifierRule
->au8EthCSEtherType
[1], pstClassifierRule
->au8EthCSEtherType
[2]);
691 if (memcmp(&pstEthCsPktInfo
->usEtherType
, &pstClassifierRule
->au8EthCSEtherType
[1], 2) == 0)
697 if (pstClassifierRule
->au8EthCSEtherType
[0] == 2)
699 if (eEth802LLCFrame
!= pstEthCsPktInfo
->eNwpktEthFrameType
)
702 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s EthCS DSAP:%x EtherType[2]:%x\n", __FUNCTION__
, pstEthCsPktInfo
->ucDSAP
, pstClassifierRule
->au8EthCSEtherType
[2]);
703 if (pstEthCsPktInfo
->ucDSAP
== pstClassifierRule
->au8EthCSEtherType
[2])
714 static bool EthCSMatchVLANRules(struct bcm_classifier_rule
*pstClassifierRule
, struct sk_buff
* skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
)
716 bool bClassificationSucceed
= false;
718 B_UINT8 uPriority
= 0;
719 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
721 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s CLS UserPrio:%x CLS VLANID:%x\n", __FUNCTION__
, ntohs(*((USHORT
*)pstClassifierRule
->usUserPriority
)), pstClassifierRule
->usVLANID
);
723 /* In case FW didn't receive the TLV, the priority field should be ignored */
724 if (pstClassifierRule
->usValidityBitMap
& (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID
))
726 if (pstEthCsPktInfo
->eNwpktEthFrameType
!= eEth802QVLANFrame
)
729 uPriority
= (ntohs(*(USHORT
*)(skb
->data
+ sizeof(struct bcm_eth_header
))) & 0xF000) >> 13;
731 if ((uPriority
>= pstClassifierRule
->usUserPriority
[0]) && (uPriority
<= pstClassifierRule
->usUserPriority
[1]))
732 bClassificationSucceed
= TRUE
;
734 if (!bClassificationSucceed
)
738 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 D User Priority Rule Matched\n");
740 bClassificationSucceed
= false;
742 if (pstClassifierRule
->usValidityBitMap
& (1<<PKT_CLASSIFICATION_VLANID_VALID
))
744 if (pstEthCsPktInfo
->eNwpktEthFrameType
!= eEth802QVLANFrame
)
747 usVLANID
= ntohs(*(USHORT
*)(skb
->data
+ sizeof(struct bcm_eth_header
))) & 0xFFF;
749 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s Pkt VLANID %x Priority: %d\n", __FUNCTION__
, usVLANID
, uPriority
);
751 if (usVLANID
== ((pstClassifierRule
->usVLANID
& 0xFFF0) >> 4))
752 bClassificationSucceed
= TRUE
;
754 if (!bClassificationSucceed
)
758 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 Q VLAN ID Rule Matched\n");
764 static bool EThCSClassifyPkt(struct bcm_mini_adapter
*Adapter
, struct sk_buff
* skb
,
765 struct bcm_eth_packet_info
*pstEthCsPktInfo
,
766 struct bcm_classifier_rule
*pstClassifierRule
,
767 B_UINT8 EthCSCupport
)
769 bool bClassificationSucceed
= false;
770 bClassificationSucceed
= EthCSMatchSrcMACAddress(pstClassifierRule
, ((struct bcm_eth_header
*)(skb
->data
))->au8SourceAddress
);
771 if (!bClassificationSucceed
)
773 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS SrcMAC Matched\n");
775 bClassificationSucceed
= EthCSMatchDestMACAddress(pstClassifierRule
, ((struct bcm_eth_header
*)(skb
->data
))->au8DestinationAddress
);
776 if (!bClassificationSucceed
)
778 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS DestMAC Matched\n");
780 //classify on ETHType/802.2SAP TLV
781 bClassificationSucceed
= EthCSMatchEThTypeSAP(pstClassifierRule
, skb
, pstEthCsPktInfo
);
782 if (!bClassificationSucceed
)
785 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS EthType/802.2SAP Matched\n");
787 //classify on 802.1VLAN Header Parameters
789 bClassificationSucceed
= EthCSMatchVLANRules(pstClassifierRule
, skb
, pstEthCsPktInfo
);
790 if (!bClassificationSucceed
)
792 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 VLAN Rules Matched\n");
794 return bClassificationSucceed
;
797 static void EThCSGetPktInfo(struct bcm_mini_adapter
*Adapter
, PVOID pvEthPayload
,
798 struct bcm_eth_packet_info
*pstEthCsPktInfo
)
800 USHORT u16Etype
= ntohs(((struct bcm_eth_header
*)pvEthPayload
)->u16Etype
);
802 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype
);
803 if (u16Etype
> 0x5dc)
805 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCSGetPktInfo : ETH2 Frame\n");
807 if (u16Etype
== ETHERNET_FRAMETYPE_802QVLAN
)
810 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802QVLANFrame
;
811 u16Etype
= ((struct bcm_eth_q_frame
*)pvEthPayload
)->EthType
;
812 //((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
816 pstEthCsPktInfo
->eNwpktEthFrameType
= eEthOtherFrame
;
817 u16Etype
= ntohs(u16Etype
);
824 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "802.2 LLC Frame\n");
825 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802LLCFrame
;
826 pstEthCsPktInfo
->ucDSAP
= ((struct bcm_eth_llc_frame
*)pvEthPayload
)->DSAP
;
827 if (pstEthCsPktInfo
->ucDSAP
== 0xAA && ((struct bcm_eth_llc_frame
*)pvEthPayload
)->SSAP
== 0xAA)
830 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802LLCSNAPFrame
;
831 u16Etype
= ((struct bcm_eth_llc_snap_frame
*)pvEthPayload
)->usEtherType
;
834 if (u16Etype
== ETHERNET_FRAMETYPE_IPV4
)
835 pstEthCsPktInfo
->eNwpktIPFrameType
= eIPv4Packet
;
836 else if (u16Etype
== ETHERNET_FRAMETYPE_IPV6
)
837 pstEthCsPktInfo
->eNwpktIPFrameType
= eIPv6Packet
;
839 pstEthCsPktInfo
->eNwpktIPFrameType
= eNonIPPacket
;
841 pstEthCsPktInfo
->usEtherType
= ((struct bcm_eth_header
*)pvEthPayload
)->u16Etype
;
842 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo
->eNwpktIPFrameType
);
843 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo
->eNwpktEthFrameType
);
844 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo
->usEtherType
);