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 BOOLEAN
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 BOOLEAN
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 BOOLEAN
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 BOOLEAN
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 BOOLEAN 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
)
226 bClassificationSucceed
= FALSE
;
230 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "is IPv6 check!");
231 if (pstClassifierRule
->bIpv6Protocol
)
234 //**************Checking IP header parameter**************************//
235 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Trying to match Source IP Address");
236 if (FALSE
== (bClassificationSucceed
=
237 MatchSrcIpAddress(pstClassifierRule
, iphd
->saddr
)))
239 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Source IP Address Matched");
241 if (FALSE
== (bClassificationSucceed
=
242 MatchDestIpAddress(pstClassifierRule
, iphd
->daddr
)))
244 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination IP Address Matched");
246 if (FALSE
== (bClassificationSucceed
=
247 MatchTos(pstClassifierRule
, iphd
->tos
)))
249 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "TOS Match failed\n");
252 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "TOS Matched");
254 if (FALSE
== (bClassificationSucceed
=
255 MatchProtocol(pstClassifierRule
, iphd
->protocol
)))
257 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Protocol Matched");
259 //if protocol is not TCP or UDP then no need of comparing source port and destination port
260 if (iphd
->protocol
!= TCP
&& iphd
->protocol
!= UDP
)
262 //******************Checking Transport Layer Header field if present *****************//
263 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Source Port %04x",
264 (iphd
->protocol
== UDP
) ? xprt_hdr
->uhdr
.source
: xprt_hdr
->thdr
.source
);
266 if (FALSE
== (bClassificationSucceed
=
267 MatchSrcPort(pstClassifierRule
,
268 ntohs((iphd
->protocol
== UDP
) ?
269 xprt_hdr
->uhdr
.source
: xprt_hdr
->thdr
.source
))))
271 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Src Port Matched");
273 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Destination Port %04x",
274 (iphd
->protocol
== UDP
) ? xprt_hdr
->uhdr
.dest
:
275 xprt_hdr
->thdr
.dest
);
276 if (FALSE
== (bClassificationSucceed
=
277 MatchDestPort(pstClassifierRule
,
278 ntohs((iphd
->protocol
== UDP
) ?
279 xprt_hdr
->uhdr
.dest
: xprt_hdr
->thdr
.dest
))))
283 if (TRUE
== bClassificationSucceed
)
285 INT iMatchedSFQueueIndex
= 0;
286 iMatchedSFQueueIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
287 if (iMatchedSFQueueIndex
>= NO_OF_QUEUES
)
289 bClassificationSucceed
= FALSE
;
293 if (FALSE
== Adapter
->PackInfo
[iMatchedSFQueueIndex
].bActive
)
295 bClassificationSucceed
= FALSE
;
300 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "IpVersion4 <==========");
302 return bClassificationSucceed
;
305 VOID
PruneQueueAllSF(struct bcm_mini_adapter
*Adapter
)
309 for (iIndex
= 0; iIndex
< HiPriority
; iIndex
++)
311 if (!Adapter
->PackInfo
[iIndex
].bValid
)
314 PruneQueue(Adapter
, iIndex
);
320 @ingroup tx_functions
321 This function checks if the max queue size for a queue
322 is less than number of bytes in the queue. If so -
323 drops packets from the Head till the number of bytes is
324 less than or equal to max queue size for the queue.
326 static VOID
PruneQueue(struct bcm_mini_adapter
*Adapter
, INT iIndex
)
328 struct sk_buff
* PacketToDrop
= NULL
;
329 struct net_device_stats
*netstats
;
331 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "=====> Index %d", iIndex
);
333 if (iIndex
== HiPriority
)
336 if (!Adapter
|| (iIndex
< 0) || (iIndex
> HiPriority
))
339 /* To Store the netdevice statistic */
340 netstats
= &Adapter
->dev
->stats
;
342 spin_lock_bh(&Adapter
->PackInfo
[iIndex
].SFQueueLock
);
345 // while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
346 // SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
348 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
349 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
,
350 Adapter
->PackInfo
[iIndex
].uiMaxBucketSize
);
352 PacketToDrop
= Adapter
->PackInfo
[iIndex
].FirstTxQueue
;
354 if (PacketToDrop
== NULL
)
356 if ((Adapter
->PackInfo
[iIndex
].uiCurrentPacketsOnHost
< SF_MAX_ALLOWED_PACKETS_TO_BACKUP
) &&
357 ((1000*(jiffies
- *((B_UINT32
*)(PacketToDrop
->cb
)+SKB_CB_LATENCY_OFFSET
))/HZ
) <= Adapter
->PackInfo
[iIndex
].uiMaxLatency
))
362 if (netif_msg_tx_err(Adapter
))
363 pr_info(PFX
"%s: tx queue %d overlimit\n",
364 Adapter
->dev
->name
, iIndex
);
366 netstats
->tx_dropped
++;
368 DEQUEUEPACKET(Adapter
->PackInfo
[iIndex
].FirstTxQueue
,
369 Adapter
->PackInfo
[iIndex
].LastTxQueue
);
370 /// update current bytes and packets count
371 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
-=
373 Adapter
->PackInfo
[iIndex
].uiCurrentPacketsOnHost
--;
374 /// update dropped bytes and packets counts
375 Adapter
->PackInfo
[iIndex
].uiDroppedCountBytes
+= PacketToDrop
->len
;
376 Adapter
->PackInfo
[iIndex
].uiDroppedCountPackets
++;
377 dev_kfree_skb(PacketToDrop
);
381 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "Dropped Bytes:%x Dropped Packets:%x",
382 Adapter
->PackInfo
[iIndex
].uiDroppedCountBytes
,
383 Adapter
->PackInfo
[iIndex
].uiDroppedCountPackets
);
385 atomic_dec(&Adapter
->TotalPacketCount
);
388 spin_unlock_bh(&Adapter
->PackInfo
[iIndex
].SFQueueLock
);
390 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "TotalPacketCount:%x",
391 atomic_read(&Adapter
->TotalPacketCount
));
392 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, PRUNE_QUEUE
, DBG_LVL_ALL
, "<=====");
395 VOID
flush_all_queues(struct bcm_mini_adapter
*Adapter
)
398 UINT uiTotalPacketLength
;
399 struct sk_buff
* PacketToDrop
= NULL
;
401 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "=====>");
403 // down(&Adapter->data_packet_queue_lock);
404 for (iQIndex
= LowPriority
; iQIndex
< HiPriority
; iQIndex
++)
406 struct net_device_stats
*netstats
= &Adapter
->dev
->stats
;
408 spin_lock_bh(&Adapter
->PackInfo
[iQIndex
].SFQueueLock
);
409 while (Adapter
->PackInfo
[iQIndex
].FirstTxQueue
)
411 PacketToDrop
= Adapter
->PackInfo
[iQIndex
].FirstTxQueue
;
414 uiTotalPacketLength
= PacketToDrop
->len
;
415 netstats
->tx_dropped
++;
418 uiTotalPacketLength
= 0;
420 DEQUEUEPACKET(Adapter
->PackInfo
[iQIndex
].FirstTxQueue
,
421 Adapter
->PackInfo
[iQIndex
].LastTxQueue
);
424 dev_kfree_skb(PacketToDrop
);
426 /// update current bytes and packets count
427 Adapter
->PackInfo
[iQIndex
].uiCurrentBytesOnHost
-= uiTotalPacketLength
;
428 Adapter
->PackInfo
[iQIndex
].uiCurrentPacketsOnHost
--;
430 /// update dropped bytes and packets counts
431 Adapter
->PackInfo
[iQIndex
].uiDroppedCountBytes
+= uiTotalPacketLength
;
432 Adapter
->PackInfo
[iQIndex
].uiDroppedCountPackets
++;
434 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "Dropped Bytes:%x Dropped Packets:%x",
435 Adapter
->PackInfo
[iQIndex
].uiDroppedCountBytes
,
436 Adapter
->PackInfo
[iQIndex
].uiDroppedCountPackets
);
437 atomic_dec(&Adapter
->TotalPacketCount
);
439 spin_unlock_bh(&Adapter
->PackInfo
[iQIndex
].SFQueueLock
);
441 // up(&Adapter->data_packet_queue_lock);
442 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_OTHERS
, DUMP_INFO
, DBG_LVL_ALL
, "<=====");
445 USHORT
ClassifyPacket(struct bcm_mini_adapter
*Adapter
, struct sk_buff
* skb
)
448 struct bcm_classifier_rule
*pstClassifierRule
= NULL
;
449 struct bcm_eth_packet_info stEthCsPktInfo
;
450 PVOID pvEThPayload
= NULL
;
451 struct iphdr
*pIpHeader
= NULL
;
453 USHORT usIndex
= Adapter
->usBestEffortQueueIndex
;
454 BOOLEAN bFragmentedPkt
= FALSE
, bClassificationSucceed
= FALSE
;
455 USHORT usCurrFragment
= 0;
457 struct bcm_tcp_header
*pTcpHeader
;
458 UCHAR IpHeaderLength
;
459 UCHAR TcpHeaderLength
;
461 pvEThPayload
= skb
->data
;
462 *((UINT32
*) (skb
->cb
) +SKB_CB_TCPACK_OFFSET
) = 0;
463 EThCSGetPktInfo(Adapter
, pvEThPayload
, &stEthCsPktInfo
);
465 switch (stEthCsPktInfo
.eNwpktEthFrameType
)
467 case eEth802LLCFrame
:
469 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802LLCFrame\n");
470 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_llc_frame
);
474 case eEth802LLCSNAPFrame
:
476 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802LLC SNAP Frame\n");
477 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_llc_snap_frame
);
480 case eEth802QVLANFrame
:
482 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : 802.1Q VLANFrame\n");
483 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_eth_q_frame
);
488 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : ETH Other Frame\n");
489 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_ethernet2_frame
);
494 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : Unrecognized ETH Frame\n");
495 pIpHeader
= pvEThPayload
+ sizeof(struct bcm_ethernet2_frame
);
500 if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv4Packet
)
502 usCurrFragment
= (ntohs(pIpHeader
->frag_off
) & IP_OFFSET
);
503 if ((ntohs(pIpHeader
->frag_off
) & IP_MF
) || usCurrFragment
)
504 bFragmentedPkt
= TRUE
;
508 //Fragmented Packet. Get Frag Classifier Entry.
509 pstClassifierRule
= GetFragIPClsEntry(Adapter
, pIpHeader
->id
, pIpHeader
->saddr
);
510 if (pstClassifierRule
)
512 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "It is next Fragmented pkt");
513 bClassificationSucceed
= TRUE
;
515 if (!(ntohs(pIpHeader
->frag_off
) & IP_MF
))
517 //Fragmented Last packet . Remove Frag Classifier Entry
518 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "This is the last fragmented Pkt");
519 DelFragIPClsEntry(Adapter
, pIpHeader
->id
, pIpHeader
->saddr
);
524 for (uiLoopIndex
= MAX_CLASSIFIERS
- 1; uiLoopIndex
>= 0; uiLoopIndex
--)
526 if (bClassificationSucceed
)
528 //Iterate through all classifiers which are already in order of priority
529 //to classify the packet until match found
532 if (FALSE
== Adapter
->astClassifierTable
[uiLoopIndex
].bUsed
)
534 bClassificationSucceed
= FALSE
;
537 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex
);
539 if (0 == Adapter
->astClassifierTable
[uiLoopIndex
].ucDirection
)
541 bClassificationSucceed
= FALSE
;//cannot be processed for classification.
542 break; // it is a down link connection
545 pstClassifierRule
= &Adapter
->astClassifierTable
[uiLoopIndex
];
547 uiSfIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
548 if (uiSfIndex
>= NO_OF_QUEUES
) {
549 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Queue Not Valid. SearchSfid for this classifier Failed\n");
553 if (Adapter
->PackInfo
[uiSfIndex
].bEthCSSupport
)
556 if (eEthUnsupportedFrame
== stEthCsPktInfo
.eNwpktEthFrameType
)
558 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
559 bClassificationSucceed
= FALSE
;
565 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
);
566 bClassificationSucceed
= EThCSClassifyPkt(Adapter
, skb
, &stEthCsPktInfo
, pstClassifierRule
, Adapter
->PackInfo
[uiSfIndex
].bEthCSSupport
);
568 if (!bClassificationSucceed
)
570 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ClassifyPacket : Ethernet CS Classification Failed\n");
575 else // No ETH Supported on this SF
577 if (eEthOtherFrame
!= stEthCsPktInfo
.eNwpktEthFrameType
)
579 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");
580 bClassificationSucceed
= FALSE
;
585 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Proceeding to IP CS Clasification");
587 if (Adapter
->PackInfo
[uiSfIndex
].bIPCSSupport
)
590 if (stEthCsPktInfo
.eNwpktIPFrameType
== eNonIPPacket
)
592 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, " ClassifyPacket : Packet is Not an IP Packet\n");
593 bClassificationSucceed
= FALSE
;
596 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "Dump IP Header :\n");
597 DumpFullPacket((PUCHAR
)pIpHeader
, 20);
599 if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv4Packet
)
600 bClassificationSucceed
= IpVersion4(Adapter
, pIpHeader
, pstClassifierRule
);
601 else if (stEthCsPktInfo
.eNwpktIPFrameType
== eIPv6Packet
)
602 bClassificationSucceed
= IpVersion6(Adapter
, pIpHeader
, pstClassifierRule
);
608 if (bClassificationSucceed
== TRUE
)
610 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "CF id : %d, SF ID is =%lu", pstClassifierRule
->uiClassifierRuleIndex
, pstClassifierRule
->ulSFID
);
612 //Store The matched Classifier in SKB
613 *((UINT32
*)(skb
->cb
)+SKB_CB_CLASSIFICATION_OFFSET
) = pstClassifierRule
->uiClassifierRuleIndex
;
614 if ((TCP
== pIpHeader
->protocol
) && !bFragmentedPkt
&& (ETH_AND_IP_HEADER_LEN
+ TCP_HEADER_LEN
<= skb
->len
))
616 IpHeaderLength
= pIpHeader
->ihl
;
617 pTcpHeader
= (struct bcm_tcp_header
*)(((PUCHAR
)pIpHeader
)+(IpHeaderLength
*4));
618 TcpHeaderLength
= GET_TCP_HEADER_LEN(pTcpHeader
->HeaderLength
);
620 if ((pTcpHeader
->ucFlags
& TCP_ACK
) &&
621 (ntohs(pIpHeader
->tot_len
) == (IpHeaderLength
*4)+(TcpHeaderLength
*4)))
623 *((UINT32
*) (skb
->cb
) + SKB_CB_TCPACK_OFFSET
) = TCP_ACK
;
627 usIndex
= SearchSfid(Adapter
, pstClassifierRule
->ulSFID
);
628 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "index is =%d", usIndex
);
630 //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.
631 if (bFragmentedPkt
&& (usCurrFragment
== 0))
633 //First Fragment of Fragmented Packet. Create Frag CLS Entry
634 struct bcm_fragmented_packet_info stFragPktInfo
;
635 stFragPktInfo
.bUsed
= TRUE
;
636 stFragPktInfo
.ulSrcIpAddress
= pIpHeader
->saddr
;
637 stFragPktInfo
.usIpIdentification
= pIpHeader
->id
;
638 stFragPktInfo
.pstMatchedClassifierEntry
= pstClassifierRule
;
639 stFragPktInfo
.bOutOfOrderFragment
= FALSE
;
640 AddFragIPClsEntry(Adapter
, &stFragPktInfo
);
646 if (bClassificationSucceed
)
649 return INVALID_QUEUE_INDEX
;
652 static BOOLEAN
EthCSMatchSrcMACAddress(struct bcm_classifier_rule
*pstClassifierRule
, PUCHAR Mac
)
655 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
656 if (pstClassifierRule
->ucEthCSSrcMACLen
== 0)
658 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s\n", __FUNCTION__
);
659 for (i
= 0; i
< MAC_ADDRESS_SIZE
; i
++)
661 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
]);
662 if ((pstClassifierRule
->au8EThCSSrcMAC
[i
] & pstClassifierRule
->au8EThCSSrcMACMask
[i
]) !=
663 (Mac
[i
] & pstClassifierRule
->au8EThCSSrcMACMask
[i
]))
669 static BOOLEAN
EthCSMatchDestMACAddress(struct bcm_classifier_rule
*pstClassifierRule
, PUCHAR Mac
)
672 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
673 if (pstClassifierRule
->ucEthCSDestMACLen
== 0)
675 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s\n", __FUNCTION__
);
676 for (i
= 0; i
< MAC_ADDRESS_SIZE
; i
++)
678 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
]);
679 if ((pstClassifierRule
->au8EThCSDestMAC
[i
] & pstClassifierRule
->au8EThCSDestMACMask
[i
]) !=
680 (Mac
[i
] & pstClassifierRule
->au8EThCSDestMACMask
[i
]))
686 static BOOLEAN
EthCSMatchEThTypeSAP(struct bcm_classifier_rule
*pstClassifierRule
, struct sk_buff
* skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
)
688 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
689 if ((pstClassifierRule
->ucEtherTypeLen
== 0) ||
690 (pstClassifierRule
->au8EthCSEtherType
[0] == 0))
693 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]);
694 if (pstClassifierRule
->au8EthCSEtherType
[0] == 1)
696 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]);
698 if (memcmp(&pstEthCsPktInfo
->usEtherType
, &pstClassifierRule
->au8EthCSEtherType
[1], 2) == 0)
704 if (pstClassifierRule
->au8EthCSEtherType
[0] == 2)
706 if (eEth802LLCFrame
!= pstEthCsPktInfo
->eNwpktEthFrameType
)
709 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]);
710 if (pstEthCsPktInfo
->ucDSAP
== pstClassifierRule
->au8EthCSEtherType
[2])
721 static BOOLEAN
EthCSMatchVLANRules(struct bcm_classifier_rule
*pstClassifierRule
, struct sk_buff
* skb
, struct bcm_eth_packet_info
*pstEthCsPktInfo
)
723 BOOLEAN bClassificationSucceed
= FALSE
;
725 B_UINT8 uPriority
= 0;
726 struct bcm_mini_adapter
*Adapter
= GET_BCM_ADAPTER(gblpnetdev
);
728 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
);
730 /* In case FW didn't receive the TLV, the priority field should be ignored */
731 if (pstClassifierRule
->usValidityBitMap
& (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID
))
733 if (pstEthCsPktInfo
->eNwpktEthFrameType
!= eEth802QVLANFrame
)
736 uPriority
= (ntohs(*(USHORT
*)(skb
->data
+ sizeof(struct bcm_eth_header
))) & 0xF000) >> 13;
738 if ((uPriority
>= pstClassifierRule
->usUserPriority
[0]) && (uPriority
<= pstClassifierRule
->usUserPriority
[1]))
739 bClassificationSucceed
= TRUE
;
741 if (!bClassificationSucceed
)
745 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 D User Priority Rule Matched\n");
747 bClassificationSucceed
= FALSE
;
749 if (pstClassifierRule
->usValidityBitMap
& (1<<PKT_CLASSIFICATION_VLANID_VALID
))
751 if (pstEthCsPktInfo
->eNwpktEthFrameType
!= eEth802QVLANFrame
)
754 usVLANID
= ntohs(*(USHORT
*)(skb
->data
+ sizeof(struct bcm_eth_header
))) & 0xFFF;
756 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "%s Pkt VLANID %x Priority: %d\n", __FUNCTION__
, usVLANID
, uPriority
);
758 if (usVLANID
== ((pstClassifierRule
->usVLANID
& 0xFFF0) >> 4))
759 bClassificationSucceed
= TRUE
;
761 if (!bClassificationSucceed
)
765 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 Q VLAN ID Rule Matched\n");
771 static BOOLEAN
EThCSClassifyPkt(struct bcm_mini_adapter
*Adapter
, struct sk_buff
* skb
,
772 struct bcm_eth_packet_info
*pstEthCsPktInfo
,
773 struct bcm_classifier_rule
*pstClassifierRule
,
774 B_UINT8 EthCSCupport
)
776 BOOLEAN bClassificationSucceed
= FALSE
;
777 bClassificationSucceed
= EthCSMatchSrcMACAddress(pstClassifierRule
, ((struct bcm_eth_header
*)(skb
->data
))->au8SourceAddress
);
778 if (!bClassificationSucceed
)
780 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS SrcMAC Matched\n");
782 bClassificationSucceed
= EthCSMatchDestMACAddress(pstClassifierRule
, ((struct bcm_eth_header
*)(skb
->data
))->au8DestinationAddress
);
783 if (!bClassificationSucceed
)
785 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS DestMAC Matched\n");
787 //classify on ETHType/802.2SAP TLV
788 bClassificationSucceed
= EthCSMatchEThTypeSAP(pstClassifierRule
, skb
, pstEthCsPktInfo
);
789 if (!bClassificationSucceed
)
792 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS EthType/802.2SAP Matched\n");
794 //classify on 802.1VLAN Header Parameters
796 bClassificationSucceed
= EthCSMatchVLANRules(pstClassifierRule
, skb
, pstEthCsPktInfo
);
797 if (!bClassificationSucceed
)
799 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "ETH CS 802.1 VLAN Rules Matched\n");
801 return bClassificationSucceed
;
804 static void EThCSGetPktInfo(struct bcm_mini_adapter
*Adapter
, PVOID pvEthPayload
,
805 struct bcm_eth_packet_info
*pstEthCsPktInfo
)
807 USHORT u16Etype
= ntohs(((struct bcm_eth_header
*)pvEthPayload
)->u16Etype
);
809 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype
);
810 if (u16Etype
> 0x5dc)
812 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCSGetPktInfo : ETH2 Frame\n");
814 if (u16Etype
== ETHERNET_FRAMETYPE_802QVLAN
)
817 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802QVLANFrame
;
818 u16Etype
= ((struct bcm_eth_q_frame
*)pvEthPayload
)->EthType
;
819 //((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
823 pstEthCsPktInfo
->eNwpktEthFrameType
= eEthOtherFrame
;
824 u16Etype
= ntohs(u16Etype
);
831 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "802.2 LLC Frame\n");
832 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802LLCFrame
;
833 pstEthCsPktInfo
->ucDSAP
= ((struct bcm_eth_llc_frame
*)pvEthPayload
)->DSAP
;
834 if (pstEthCsPktInfo
->ucDSAP
== 0xAA && ((struct bcm_eth_llc_frame
*)pvEthPayload
)->SSAP
== 0xAA)
837 pstEthCsPktInfo
->eNwpktEthFrameType
= eEth802LLCSNAPFrame
;
838 u16Etype
= ((struct bcm_eth_llc_snap_frame
*)pvEthPayload
)->usEtherType
;
841 if (u16Etype
== ETHERNET_FRAMETYPE_IPV4
)
842 pstEthCsPktInfo
->eNwpktIPFrameType
= eIPv4Packet
;
843 else if (u16Etype
== ETHERNET_FRAMETYPE_IPV6
)
844 pstEthCsPktInfo
->eNwpktIPFrameType
= eIPv6Packet
;
846 pstEthCsPktInfo
->eNwpktIPFrameType
= eNonIPPacket
;
848 pstEthCsPktInfo
->usEtherType
= ((struct bcm_eth_header
*)pvEthPayload
)->u16Etype
;
849 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo
->eNwpktIPFrameType
);
850 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo
->eNwpktEthFrameType
);
851 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, IPV4_DBG
, DBG_LVL_ALL
, "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo
->usEtherType
);