Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9 855 lines 32 kB view raw
1/** 2@file Qos.C 3This file contains the routines related to Quality of Service. 4*/ 5#include "headers.h" 6 7static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo); 8static 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); 9 10static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd, 11 struct bcm_classifier_rule *pstClassifierRule ); 12 13static 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*********************************************************************/ 27BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulSrcIP) 28{ 29 UCHAR ucLoopIndex=0; 30 31 struct bcm_mini_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(struct bcm_classifier_rule *pstClassifierRule,ULONG ulDestIP) 62{ 63 UCHAR ucLoopIndex=0; 64 struct bcm_mini_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(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfService) 95{ 96 97 struct bcm_mini_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****************************************************************************/ 120bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol) 121{ 122 UCHAR ucLoopIndex=0; 123 struct bcm_mini_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***************************************************************************/ 149bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort) 150{ 151 UCHAR ucLoopIndex=0; 152 153 struct bcm_mini_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***************************************************************************/ 181bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDestPort) 182{ 183 UCHAR ucLoopIndex=0; 184 struct bcm_mini_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(struct bcm_mini_adapter *Adapter, 208 struct iphdr *iphd, 209 struct bcm_classifier_rule *pstClassifierRule) 210{ 211 struct bcm_transport_header *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=(struct bcm_transport_header *)((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(struct bcm_mini_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(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); 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(struct bcm_mini_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(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) 446{ 447 INT uiLoopIndex=0; 448 struct bcm_classifier_rule *pstClassifierRule = NULL; 449 struct bcm_eth_packet_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 struct bcm_tcp_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(struct bcm_eth_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(struct bcm_eth_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(struct bcm_eth_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(struct bcm_ethernet2_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(struct bcm_ethernet2_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 = (struct bcm_tcp_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 652static 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; 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(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; 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(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_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 721static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_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 771static 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) 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 804static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, 805 struct bcm_eth_packet_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 = ((struct bcm_eth_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 = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP; 834 if(pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) 835 { 836 //SNAP Frame 837 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame; 838 u16Etype = ((struct bcm_eth_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