Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1/**
  2@file Qos.C
  3This file contains the routines related to Quality of Service.
  4*/
  5#include "headers.h"
  6
  7static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload,PS_ETHCS_PKT_INFO pstEthCsPktInfo);
  8static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo,S_CLASSIFIER_RULE *pstClassifierRule, B_UINT8 EthCSCupport);
  9
 10static USHORT	IpVersion4(PMINI_ADAPTER Adapter, struct iphdr *iphd,
 11			   S_CLASSIFIER_RULE *pstClassifierRule );
 12
 13static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex);
 14
 15
 16/*******************************************************************
 17* Function    - MatchSrcIpAddress()
 18*
 19* Description - Checks whether the Source IP address from the packet
 20*				matches with that of Queue.
 21*
 22* Parameters  - pstClassifierRule: Pointer to the packet info structure.
 23* 			  - ulSrcIP	    : Source IP address from the packet.
 24*
 25* Returns     - TRUE(If address matches) else FAIL .
 26*********************************************************************/
 27BOOLEAN MatchSrcIpAddress(S_CLASSIFIER_RULE *pstClassifierRule,ULONG ulSrcIP)
 28{
 29    UCHAR 	ucLoopIndex=0;
 30
 31    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
 32
 33    ulSrcIP=ntohl(ulSrcIP);
 34    if(0 == pstClassifierRule->ucIPSourceAddressLength)
 35       	return TRUE;
 36    for(ucLoopIndex=0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);ucLoopIndex++)
 37    {
 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] ))
 41       	{
 42       		return TRUE;
 43       	}
 44    }
 45    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
 46   	return FALSE;
 47}
 48
 49
 50/*******************************************************************
 51* Function    - MatchDestIpAddress()
 52*
 53* Description - Checks whether the Destination IP address from the packet
 54*				matches with that of Queue.
 55*
 56* Parameters  - pstClassifierRule: Pointer to the packet info structure.
 57* 			  - ulDestIP    : Destination IP address from the packet.
 58*
 59* Returns     - TRUE(If address matches) else FAIL .
 60*********************************************************************/
 61BOOLEAN MatchDestIpAddress(S_CLASSIFIER_RULE *pstClassifierRule,ULONG ulDestIP)
 62{
 63	UCHAR 	ucLoopIndex=0;
 64    PMINI_ADAPTER	Adapter = GET_BCM_ADAPTER(gblpnetdev);
 65
 66	ulDestIP=ntohl(ulDestIP);
 67    if(0 == pstClassifierRule->ucIPDestinationAddressLength)
 68       	return TRUE;
 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]);
 70
 71    for(ucLoopIndex=0;ucLoopIndex<(pstClassifierRule->ucIPDestinationAddressLength);ucLoopIndex++)
 72    {
 73		if((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP)==
 74					(pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
 75       	{
 76       		return TRUE;
 77       	}
 78    }
 79	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
 80    return FALSE;
 81}
 82
 83
 84/************************************************************************
 85* Function    - MatchTos()
 86*
 87* Description - Checks the TOS from the packet matches with that of queue.
 88*
 89* Parameters  - pstClassifierRule   : Pointer to the packet info structure.
 90* 			  - ucTypeOfService: TOS from the packet.
 91*
 92* Returns     - TRUE(If address matches) else FAIL.
 93**************************************************************************/
 94BOOLEAN MatchTos(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucTypeOfService)
 95{
 96
 97	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
 98    if( 3 != pstClassifierRule->ucIPTypeOfServiceLength )
 99       	return TRUE;
100
101    if(((pstClassifierRule->ucTosMask & ucTypeOfService)<=pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService)>=pstClassifierRule->ucTosLow))
102    {
103       	return TRUE;
104    }
105    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
106    return FALSE;
107}
108
109
110/***************************************************************************
111* Function    - MatchProtocol()
112*
113* Description - Checks the protocol from the packet matches with that of queue.
114*
115* Parameters  - pstClassifierRule: Pointer to the packet info structure.
116* 			  - ucProtocol	: Protocol from the packet.
117*
118* Returns     - TRUE(If address matches) else FAIL.
119****************************************************************************/
120BOOLEAN MatchProtocol(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucProtocol)
121{
122   	UCHAR 	ucLoopIndex=0;
123	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
124	if(0 == pstClassifierRule->ucProtocolLength)
125      	return TRUE;
126	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucProtocolLength;ucLoopIndex++)
127    {
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)
130       	{
131       		return TRUE;
132       	}
133    }
134    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
135   	return FALSE;
136}
137
138
139/***********************************************************************
140* Function    - MatchSrcPort()
141*
142* Description - Checks, Source port from the packet matches with that of queue.
143*
144* Parameters  - pstClassifierRule: Pointer to the packet info structure.
145* 			  - ushSrcPort	: Source port from the packet.
146*
147* Returns     - TRUE(If address matches) else FAIL.
148***************************************************************************/
149BOOLEAN MatchSrcPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushSrcPort)
150{
151    	UCHAR 	ucLoopIndex=0;
152
153		PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
154
155
156    	if(0 == pstClassifierRule->ucSrcPortRangeLength)
157        	return TRUE;
158    	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucSrcPortRangeLength;ucLoopIndex++)
159    	{
160        	if(ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
161		    ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
162	    	{
163		    	return TRUE;
164	    	}
165    	}
166		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ",ushSrcPort);
167    	return FALSE;
168}
169
170
171/***********************************************************************
172* Function    - MatchDestPort()
173*
174* Description - Checks, Destination port from packet matches with that of queue.
175*
176* Parameters  - pstClassifierRule: Pointer to the packet info structure.
177* 			  - ushDestPort	: Destination port from the packet.
178*
179* Returns     - TRUE(If address matches) else FAIL.
180***************************************************************************/
181BOOLEAN MatchDestPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushDestPort)
182{
183    	UCHAR 	ucLoopIndex=0;
184		PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
185
186    	if(0 == pstClassifierRule->ucDestPortRangeLength)
187        	return TRUE;
188
189    	for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucDestPortRangeLength;ucLoopIndex++)
190    	{
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]);
192
193 		if(ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
194		    ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
195	    	{
196		    return TRUE;
197	    	}
198    	}
199		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched",ushDestPort);
200    	return FALSE;
201}
202/**
203@ingroup tx_functions
204Compares IPV4 Ip address and port number
205@return Queue Index.
206*/
207static USHORT	IpVersion4(PMINI_ADAPTER Adapter,
208			   struct iphdr *iphd,
209			   S_CLASSIFIER_RULE *pstClassifierRule )
210{
211	xporthdr     		*xprt_hdr=NULL;
212	BOOLEAN	bClassificationSucceed=FALSE;
213
214	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
215
216	xprt_hdr=(xporthdr *)((PUCHAR)iphd + sizeof(struct iphdr));
217
218	do {
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);
222
223		//Checking classifier validity
224		if(!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
225		{
226			bClassificationSucceed = FALSE;
227			break;
228		}
229
230		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
231		if(pstClassifierRule->bIpv6Protocol)
232			break;
233
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)))
238			break;
239		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
240
241		if(FALSE == (bClassificationSucceed =
242			MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
243			break;
244		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
245
246		if(FALSE == (bClassificationSucceed =
247			MatchTos(pstClassifierRule, iphd->tos)))
248		{
249			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
250			break;
251		}
252		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
253
254		if(FALSE == (bClassificationSucceed =
255			MatchProtocol(pstClassifierRule,iphd->protocol)))
256			break;
257		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
258
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)
261			break;
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);
265
266		if(FALSE == (bClassificationSucceed =
267			MatchSrcPort(pstClassifierRule,
268				ntohs((iphd->protocol == UDP)?
269				xprt_hdr->uhdr.source:xprt_hdr->thdr.source))))
270			break;
271		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
272
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))))
280			break;
281	} while(0);
282
283	if(TRUE==bClassificationSucceed)
284	{
285		INT iMatchedSFQueueIndex = 0;
286		iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
287		if(iMatchedSFQueueIndex >= NO_OF_QUEUES)
288		{
289			bClassificationSucceed = FALSE;
290		}
291		else
292		{
293			if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
294			{
295				bClassificationSucceed = FALSE;
296			}
297		}
298	}
299
300	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
301
302	return bClassificationSucceed;
303}
304
305VOID PruneQueueAllSF(PMINI_ADAPTER Adapter)
306{
307	UINT iIndex = 0;
308
309	for(iIndex = 0; iIndex < HiPriority; iIndex++)
310	{
311		if(!Adapter->PackInfo[iIndex].bValid)
312			continue;
313
314		PruneQueue(Adapter, iIndex);
315	}
316}
317
318
319/**
320@ingroup tx_functions
321This function checks if the max queue size for a queue
322is less than number of bytes in the queue. If so -
323drops packets from the Head till the number of bytes is
324less than or equal to max queue size for the queue.
325*/
326static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex)
327{
328	struct sk_buff* PacketToDrop=NULL;
329	struct net_device_stats *netstats;
330
331	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d",iIndex);
332
333   	if(iIndex == HiPriority)
334		return;
335
336	if(!Adapter || (iIndex < 0) || (iIndex > HiPriority))
337		return;
338
339	/* To Store the netdevice statistic */
340	netstats = &Adapter->dev->stats;
341
342	spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
343
344	while(1)
345//	while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
346//		SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
347	{
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);
351
352		PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue;
353
354		if(PacketToDrop == NULL)
355			break;
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))
358			break;
359
360		if(PacketToDrop)
361		{
362			if (netif_msg_tx_err(Adapter))
363				pr_info(PFX "%s: tx queue %d overlimit\n", 
364					Adapter->dev->name, iIndex);
365
366			netstats->tx_dropped++;
367
368			DEQUEUEPACKET(Adapter->PackInfo[iIndex].FirstTxQueue,
369						Adapter->PackInfo[iIndex].LastTxQueue);
370			/// update current bytes and packets count
371			Adapter->PackInfo[iIndex].uiCurrentBytesOnHost -=
372				PacketToDrop->len;
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);
378
379		}
380
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);
384
385		atomic_dec(&Adapter->TotalPacketCount);
386	}
387
388	spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
389
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, "<=====");
393}
394
395VOID flush_all_queues(PMINI_ADAPTER Adapter)
396{
397	INT		iQIndex;
398	UINT	uiTotalPacketLength;
399	struct sk_buff*			PacketToDrop=NULL;
400
401	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
402
403//	down(&Adapter->data_packet_queue_lock);
404	for(iQIndex=LowPriority; iQIndex<HiPriority; iQIndex++)
405	{
406		struct net_device_stats *netstats = &Adapter->dev->stats;
407
408		spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
409		while(Adapter->PackInfo[iQIndex].FirstTxQueue)
410		{
411			PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
412			if(PacketToDrop)
413			{
414				uiTotalPacketLength = PacketToDrop->len;
415				netstats->tx_dropped++;
416			}
417			else
418				uiTotalPacketLength = 0;
419
420			DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue,
421						Adapter->PackInfo[iQIndex].LastTxQueue);
422
423			/* Free the skb */
424			dev_kfree_skb(PacketToDrop);
425
426			/// update current bytes and packets count
427			Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength;
428			Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
429
430			/// update dropped bytes and packets counts
431			Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength;
432			Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
433
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);
438		}
439		spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
440	}
441//	up(&Adapter->data_packet_queue_lock);
442	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<=====");
443}
444
445USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb)
446{
447	INT			uiLoopIndex=0;
448	S_CLASSIFIER_RULE *pstClassifierRule = NULL;
449	S_ETHCS_PKT_INFO stEthCsPktInfo;
450	PVOID pvEThPayload = NULL;
451	struct iphdr 		*pIpHeader = NULL;
452	INT	  uiSfIndex=0;
453	USHORT	usIndex=Adapter->usBestEffortQueueIndex;
454	BOOLEAN	bFragmentedPkt=FALSE,bClassificationSucceed=FALSE;
455	USHORT	usCurrFragment =0;
456
457	PTCP_HEADER pTcpHeader;
458	UCHAR IpHeaderLength;
459	UCHAR TcpHeaderLength;
460
461	pvEThPayload = skb->data;
462	*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = 0;
463	EThCSGetPktInfo(Adapter,pvEThPayload,&stEthCsPktInfo);
464
465	switch(stEthCsPktInfo.eNwpktEthFrameType)
466	{
467		case eEth802LLCFrame:
468		{
469			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n");
470            pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_FRAME);
471			break;
472		}
473
474		case eEth802LLCSNAPFrame:
475		{
476			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n");
477			pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_SNAP_FRAME);
478			break;
479		}
480		case eEth802QVLANFrame:
481		{
482			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n");
483			pIpHeader = pvEThPayload + sizeof(ETH_CS_802_Q_FRAME);
484			break;
485		}
486		case eEthOtherFrame:
487		{
488			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n");
489			pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME);
490			break;
491		}
492		default:
493		{
494			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n");
495			pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME);
496			break;
497		}
498	}
499
500	if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
501	{
502		usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
503		if((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
504			bFragmentedPkt = TRUE;
505
506		if(bFragmentedPkt)
507		{
508				//Fragmented  Packet. Get Frag Classifier Entry.
509			pstClassifierRule = GetFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr);
510			if(pstClassifierRule)
511			{
512					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"It is next Fragmented pkt");
513					bClassificationSucceed=TRUE;
514			}
515			if(!(ntohs(pIpHeader->frag_off) & IP_MF))
516			{
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);
520			}
521		}
522	}
523
524	for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--)
525	{
526		if(bClassificationSucceed)
527			break;
528		//Iterate through all classifiers which are already in order of priority
529		//to classify the packet until match found
530		do
531		{
532			if(FALSE==Adapter->astClassifierTable[uiLoopIndex].bUsed)
533			{
534				bClassificationSucceed=FALSE;
535				break;
536			}
537			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n",uiLoopIndex);
538
539			if(0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection)
540			{
541				bClassificationSucceed=FALSE;//cannot be processed for classification.
542				break;						// it is a down link connection
543			}
544
545			pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
546
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");
550				break;
551			}
552
553			if(Adapter->PackInfo[uiSfIndex].bEthCSSupport)
554			{
555
556				if(eEthUnsupportedFrame==stEthCsPktInfo.eNwpktEthFrameType)
557				{
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;
560					break;
561				}
562
563
564
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);
567
568				if(!bClassificationSucceed)
569				{
570					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ClassifyPacket : Ethernet CS Classification Failed\n");
571					break;
572				}
573			}
574
575			else // No ETH Supported on this SF
576			{
577				if(eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType)
578				{
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;
581					break;
582				}
583			}
584
585			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Proceeding to IP CS Clasification");
586
587			if(Adapter->PackInfo[uiSfIndex].bIPCSSupport)
588			{
589
590				if(stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket)
591				{
592					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  " ClassifyPacket : Packet is Not an IP Packet \n");
593					bClassificationSucceed = FALSE;
594					break;
595				}
596				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Dump IP Header : \n");
597				DumpFullPacket((PUCHAR)pIpHeader,20);
598
599				if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
600					bClassificationSucceed = IpVersion4(Adapter,pIpHeader,pstClassifierRule);
601				else if(stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
602					bClassificationSucceed = IpVersion6(Adapter,pIpHeader,pstClassifierRule);
603			}
604
605		}while(0);
606	}
607
608	if(bClassificationSucceed == TRUE)
609	{
610		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu",pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
611
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) )
615		{
616			 IpHeaderLength   = pIpHeader->ihl;
617			 pTcpHeader = (PTCP_HEADER)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
618			 TcpHeaderLength  = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
619
620			if((pTcpHeader->ucFlags & TCP_ACK) &&
621			   (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
622			{
623    			*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = TCP_ACK;
624			}
625		}
626
627		usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
628		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is	=%d", usIndex);
629
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))
632		{
633			//First Fragment of Fragmented Packet. Create Frag CLS Entry
634			S_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);
641		}
642
643
644	}
645
646	if(bClassificationSucceed)
647		return usIndex;
648	else
649		return INVALID_QUEUE_INDEX;
650}
651
652static BOOLEAN EthCSMatchSrcMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac)
653{
654	UINT i=0;
655    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
656	if(pstClassifierRule->ucEthCSSrcMACLen==0)
657		return TRUE;
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++)
660	{
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]))
664			return FALSE;
665	}
666	return TRUE;
667}
668
669static BOOLEAN EthCSMatchDestMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac)
670{
671	UINT i=0;
672    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
673	if(pstClassifierRule->ucEthCSDestMACLen==0)
674		return TRUE;
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++)
677	{
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]))
681			return FALSE;
682	}
683	return TRUE;
684}
685
686static BOOLEAN EthCSMatchEThTypeSAP(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo)
687{
688    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
689	if((pstClassifierRule->ucEtherTypeLen==0)||
690		(pstClassifierRule->au8EthCSEtherType[0] == 0))
691		return TRUE;
692
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)
695	{
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]);
697
698		if(memcmp(&pstEthCsPktInfo->usEtherType,&pstClassifierRule->au8EthCSEtherType[1],2)==0)
699			return TRUE;
700		else
701			return FALSE;
702	}
703
704	if(pstClassifierRule->au8EthCSEtherType[0] == 2)
705	{
706		if(eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
707			return FALSE;
708
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])
711			return TRUE;
712		else
713			return FALSE;
714
715	}
716
717	return FALSE;
718
719}
720
721static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo)
722{
723	BOOLEAN bClassificationSucceed = FALSE;
724	USHORT usVLANID;
725	B_UINT8 uPriority = 0;
726    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
727
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);
729
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))
732	{
733		if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame)
734				return FALSE;
735
736		uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xF000) >> 13;
737
738		if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
739				bClassificationSucceed = TRUE;
740
741		if(!bClassificationSucceed)
742			return FALSE;
743	}
744
745	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 D  User Priority Rule Matched\n");
746
747	bClassificationSucceed = FALSE;
748
749	if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID))
750	{
751		if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame)
752				return FALSE;
753
754		usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xFFF;
755
756		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority);
757
758		if(usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
759			bClassificationSucceed = TRUE;
760
761		if(!bClassificationSucceed)
762			return FALSE;
763	}
764
765	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 Q VLAN ID Rule Matched\n");
766
767	return TRUE;
768}
769
770
771static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,
772				PS_ETHCS_PKT_INFO pstEthCsPktInfo,
773				S_CLASSIFIER_RULE *pstClassifierRule,
774				B_UINT8 EthCSCupport)
775{
776	BOOLEAN bClassificationSucceed = FALSE;
777	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((ETH_HEADER_STRUC *)(skb->data))->au8SourceAddress);
778	if(!bClassificationSucceed)
779		return FALSE;
780	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS SrcMAC Matched\n");
781
782	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((ETH_HEADER_STRUC*)(skb->data))->au8DestinationAddress);
783	if(!bClassificationSucceed)
784		return FALSE;
785	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS DestMAC Matched\n");
786
787	//classify on ETHType/802.2SAP TLV
788	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,skb,pstEthCsPktInfo);
789	if(!bClassificationSucceed)
790		return FALSE;
791
792	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS EthType/802.2SAP Matched\n");
793
794	//classify on 802.1VLAN Header Parameters
795
796	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,skb,pstEthCsPktInfo);
797	if(!bClassificationSucceed)
798		return FALSE;
799	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 VLAN Rules Matched\n");
800
801	return bClassificationSucceed;
802}
803
804static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload,
805			    PS_ETHCS_PKT_INFO pstEthCsPktInfo)
806{
807	USHORT u16Etype = ntohs(((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype);
808
809	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype);
810	if(u16Etype > 0x5dc)
811	{
812		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : ETH2 Frame \n");
813		//ETH2 Frame
814		if(u16Etype == ETHERNET_FRAMETYPE_802QVLAN)
815		{
816			//802.1Q VLAN Header
817			pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
818			u16Etype = ((ETH_CS_802_Q_FRAME*)pvEthPayload)->EthType;
819			//((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
820		}
821		else
822		{
823			pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
824			u16Etype = ntohs(u16Etype);
825		}
826
827	}
828	else
829	{
830		//802.2 LLC
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 = ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->DSAP;
834		if(pstEthCsPktInfo->ucDSAP == 0xAA && ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->SSAP == 0xAA)
835		{
836			//SNAP Frame
837			pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
838			u16Etype = ((ETH_CS_802_LLC_SNAP_FRAME*)pvEthPayload)->usEtherType;
839		}
840	}
841	if(u16Etype == ETHERNET_FRAMETYPE_IPV4)
842		pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet;
843	else if(u16Etype == ETHERNET_FRAMETYPE_IPV6)
844		pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet;
845	else
846		pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
847
848	pstEthCsPktInfo->usEtherType = ((ETH_HEADER_STRUC*)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);
852}
853
854
855