Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Qos.c
Go to the documentation of this file.
1 
5 #include "headers.h"
6 
7 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload,PS_ETHCS_PKT_INFO pstEthCsPktInfo);
8 static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo,struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport);
9 
10 static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
11  struct bcm_classifier_rule *pstClassifierRule );
12 
13 static VOID PruneQueue(struct bcm_mini_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 *********************************************************************/
27 BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulSrcIP)
28 {
29  UCHAR ucLoopIndex=0;
30 
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 *********************************************************************/
61 BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulDestIP)
62 {
63  UCHAR ucLoopIndex=0;
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 **************************************************************************/
94 BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfService)
95 {
96 
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 ****************************************************************************/
120 BOOLEAN MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol)
121 {
122  UCHAR ucLoopIndex=0;
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 ***************************************************************************/
149 BOOLEAN MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort)
150 {
151  UCHAR ucLoopIndex=0;
152 
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 ***************************************************************************/
181 BOOLEAN MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDestPort)
182 {
183  UCHAR ucLoopIndex=0;
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 }
207 static USHORT IpVersion4(struct bcm_mini_adapter *Adapter,
208  struct iphdr *iphd,
209  struct bcm_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 
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 
326 static VOID PruneQueue(struct bcm_mini_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);
371  Adapter->PackInfo[iIndex].uiCurrentBytesOnHost -=
372  PacketToDrop->len;
373  Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost--;
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 
396 {
397  INT iQIndex;
398  UINT uiTotalPacketLength;
399  struct sk_buff* PacketToDrop=NULL;
400 
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 
427  Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength;
428  Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
429 
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);
443 }
444 
446 {
447  INT uiLoopIndex=0;
448  struct bcm_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  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);
641  }
642 
643 
644  }
645 
646  if(bClassificationSucceed)
647  return usIndex;
648  else
649  return INVALID_QUEUE_INDEX;
650 }
651 
652 static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac)
653 {
654  UINT i=0;
655  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
656  if(pstClassifierRule->ucEthCSSrcMACLen==0)
657  return TRUE;
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 
669 static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac)
670 {
671  UINT i=0;
672  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
673  if(pstClassifierRule->ucEthCSDestMACLen==0)
674  return TRUE;
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 
686 static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo)
687 {
688  struct bcm_mini_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 
721 static BOOLEAN EthCSMatchVLANRules(struct bcm_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  struct bcm_mini_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(struct bcm_eth_header))) & 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(struct bcm_eth_header))) & 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 
771 static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb,
772  PS_ETHCS_PKT_INFO pstEthCsPktInfo,
773  struct bcm_classifier_rule *pstClassifierRule,
774  B_UINT8 EthCSCupport)
775 {
776  BOOLEAN bClassificationSucceed = FALSE;
777  bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((struct bcm_eth_header *)(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,((struct bcm_eth_header *)(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 
804 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload,
805  PS_ETHCS_PKT_INFO pstEthCsPktInfo)
806 {
807  USHORT u16Etype = ntohs(((struct bcm_eth_header *)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 = ((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);
852 }
853 
854 
855