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.18-rc6 1200 lines 33 kB view raw
1/** 2 * @file Qos.C 3 * This file contains the routines related to Quality of Service. 4*/ 5#include "headers.h" 6 7static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, 8 PVOID pvEthPayload, 9 struct bcm_eth_packet_info *pstEthCsPktInfo); 10 11static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, 12 struct sk_buff *skb, 13 struct bcm_eth_packet_info *pstEthCsPktInfo, 14 struct bcm_classifier_rule *pstClassifierRule, 15 B_UINT8 EthCSCupport); 16 17static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd, 18 struct bcm_classifier_rule *pstClassifierRule); 19 20static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex); 21 22 23/******************************************************************* 24* Function - MatchSrcIpAddress() 25* 26* Description - Checks whether the Source IP address from the packet 27* matches with that of Queue. 28* 29* Parameters - pstClassifierRule: Pointer to the packet info structure. 30* - ulSrcIP : Source IP address from the packet. 31* 32* Returns - TRUE(If address matches) else FAIL . 33*********************************************************************/ 34static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, 35 ULONG ulSrcIP) 36{ 37 UCHAR ucLoopIndex = 0; 38 39 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 40 union u_ip_address *src_addr; 41 42 ulSrcIP = ntohl(ulSrcIP); 43 if (0 == pstClassifierRule->ucIPSourceAddressLength) 44 return TRUE; 45 for (ucLoopIndex = 0; 46 ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); 47 ucLoopIndex++) { 48 src_addr = &pstClassifierRule->stSrcIpAddress; 49 BCM_DEBUG_PRINT(Adapter, 50 DBG_TYPE_TX, 51 IPV4_DBG, 52 DBG_LVL_ALL, 53 "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", 54 (UINT)src_addr->ulIpv4Mask[ucLoopIndex], 55 (UINT)ulSrcIP, 56 (UINT)src_addr->ulIpv6Addr[ucLoopIndex]); 57 58 if ((src_addr->ulIpv4Mask[ucLoopIndex] & ulSrcIP) == 59 (src_addr->ulIpv4Addr[ucLoopIndex] & 60 src_addr->ulIpv4Mask[ucLoopIndex])) 61 return TRUE; 62 } 63 BCM_DEBUG_PRINT(Adapter, 64 DBG_TYPE_TX, 65 IPV4_DBG, 66 DBG_LVL_ALL, 67 "Src Ip Address Not Matched"); 68 return false; 69} 70 71 72/******************************************************************* 73* Function - MatchDestIpAddress() 74* 75* Description - Checks whether the Destination IP address from the packet 76* matches with that of Queue. 77* 78* Parameters - pstClassifierRule: Pointer to the packet info structure. 79* - ulDestIP : Destination IP address from the packet. 80* 81* Returns - TRUE(If address matches) else FAIL . 82*********************************************************************/ 83static bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP) 84{ 85 UCHAR ucLoopIndex = 0; 86 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 87 union u_ip_address *dest_addr = &pstClassifierRule->stDestIpAddress; 88 89 ulDestIP = ntohl(ulDestIP); 90 if (0 == pstClassifierRule->ucIPDestinationAddressLength) 91 return TRUE; 92 BCM_DEBUG_PRINT(Adapter, 93 DBG_TYPE_TX, 94 IPV4_DBG, 95 DBG_LVL_ALL, 96 "Destination Ip Address 0x%x 0x%x 0x%x ", 97 (UINT)ulDestIP, 98 (UINT)dest_addr->ulIpv4Mask[ucLoopIndex], 99 (UINT)dest_addr->ulIpv4Addr[ucLoopIndex]); 100 101 for (ucLoopIndex = 0; 102 ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); 103 ucLoopIndex++) { 104 if ((dest_addr->ulIpv4Mask[ucLoopIndex] & ulDestIP) == 105 (dest_addr->ulIpv4Addr[ucLoopIndex] & 106 dest_addr->ulIpv4Mask[ucLoopIndex])) 107 return TRUE; 108 } 109 BCM_DEBUG_PRINT(Adapter, 110 DBG_TYPE_TX, 111 IPV4_DBG, 112 DBG_LVL_ALL, 113 "Destination Ip Address Not Matched"); 114 return false; 115} 116 117 118/************************************************************************ 119* Function - MatchTos() 120* 121* Description - Checks the TOS from the packet matches with that of queue. 122* 123* Parameters - pstClassifierRule : Pointer to the packet info structure. 124* - ucTypeOfService: TOS from the packet. 125* 126* Returns - TRUE(If address matches) else FAIL. 127**************************************************************************/ 128static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule, 129 UCHAR ucTypeOfService) 130{ 131 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 132 133 if (3 != pstClassifierRule->ucIPTypeOfServiceLength) 134 return TRUE; 135 136 if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= 137 pstClassifierRule->ucTosHigh) && 138 ((pstClassifierRule->ucTosMask & ucTypeOfService) >= 139 pstClassifierRule->ucTosLow)) 140 return TRUE; 141 142 BCM_DEBUG_PRINT(Adapter, 143 DBG_TYPE_TX, 144 IPV4_DBG, 145 DBG_LVL_ALL, 146 "Type Of Service Not Matched"); 147 return false; 148} 149 150 151/*************************************************************************** 152* Function - MatchProtocol() 153* 154* Description - Checks the protocol from the packet matches with that of queue. 155* 156* Parameters - pstClassifierRule: Pointer to the packet info structure. 157* - ucProtocol : Protocol from the packet. 158* 159* Returns - TRUE(If address matches) else FAIL. 160****************************************************************************/ 161bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, 162 UCHAR ucProtocol) 163{ 164 UCHAR ucLoopIndex = 0; 165 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 166 167 if (0 == pstClassifierRule->ucProtocolLength) 168 return TRUE; 169 for (ucLoopIndex = 0; 170 ucLoopIndex < pstClassifierRule->ucProtocolLength; 171 ucLoopIndex++) { 172 BCM_DEBUG_PRINT(Adapter, 173 DBG_TYPE_TX, 174 IPV4_DBG, 175 DBG_LVL_ALL, 176 "Protocol:0x%X Classification Protocol:0x%X", 177 ucProtocol, 178 pstClassifierRule->ucProtocol[ucLoopIndex]); 179 if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol) 180 return TRUE; 181 } 182 BCM_DEBUG_PRINT(Adapter, 183 DBG_TYPE_TX, 184 IPV4_DBG, 185 DBG_LVL_ALL, 186 "Protocol Not Matched"); 187 return false; 188} 189 190 191/*********************************************************************** 192* Function - MatchSrcPort() 193* 194* Description - Checks, Source port from the packet matches with that of queue. 195* 196* Parameters - pstClassifierRule: Pointer to the packet info structure. 197* - ushSrcPort : Source port from the packet. 198* 199* Returns - TRUE(If address matches) else FAIL. 200***************************************************************************/ 201bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, 202 USHORT ushSrcPort) 203{ 204 UCHAR ucLoopIndex = 0; 205 206 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 207 208 209 if (0 == pstClassifierRule->ucSrcPortRangeLength) 210 return TRUE; 211 for (ucLoopIndex = 0; 212 ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; 213 ucLoopIndex++) { 214 if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] && 215 ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex]) 216 return TRUE; 217 } 218 BCM_DEBUG_PRINT(Adapter, 219 DBG_TYPE_TX, 220 IPV4_DBG, 221 DBG_LVL_ALL, 222 "Src Port: %x Not Matched ", 223 ushSrcPort); 224 return false; 225} 226 227 228/*********************************************************************** 229* Function - MatchDestPort() 230* 231* Description - Checks, Destination port from packet matches with that of queue. 232* 233* Parameters - pstClassifierRule: Pointer to the packet info structure. 234* - ushDestPort : Destination port from the packet. 235* 236* Returns - TRUE(If address matches) else FAIL. 237***************************************************************************/ 238bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, 239 USHORT ushDestPort) 240{ 241 UCHAR ucLoopIndex = 0; 242 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 243 244 if (0 == pstClassifierRule->ucDestPortRangeLength) 245 return TRUE; 246 247 for (ucLoopIndex = 0; 248 ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; 249 ucLoopIndex++) { 250 BCM_DEBUG_PRINT(Adapter, 251 DBG_TYPE_TX, 252 IPV4_DBG, 253 DBG_LVL_ALL, 254 "Matching Port:0x%X 0x%X 0x%X", 255 ushDestPort, 256 pstClassifierRule->usDestPortRangeLo[ucLoopIndex], 257 pstClassifierRule->usDestPortRangeHi[ucLoopIndex]); 258 259 if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] && 260 ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex]) 261 return TRUE; 262 } 263 BCM_DEBUG_PRINT(Adapter, 264 DBG_TYPE_TX, 265 IPV4_DBG, 266 DBG_LVL_ALL, 267 "Dest Port: %x Not Matched", 268 ushDestPort); 269 return false; 270} 271/** 272 * @ingroup tx_functions 273 * Compares IPV4 Ip address and port number 274 * @return Queue Index. 275*/ 276static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, 277 struct iphdr *iphd, 278 struct bcm_classifier_rule *pstClassifierRule) 279{ 280 struct bcm_transport_header *xprt_hdr = NULL; 281 bool bClassificationSucceed = false; 282 283 BCM_DEBUG_PRINT(Adapter, 284 DBG_TYPE_TX, 285 IPV4_DBG, 286 DBG_LVL_ALL, 287 "========>"); 288 289 xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr)); 290 291 BCM_DEBUG_PRINT(Adapter, 292 DBG_TYPE_TX, 293 IPV4_DBG, 294 DBG_LVL_ALL, 295 "Trying to see Direction = %d %d", 296 pstClassifierRule->ucDirection, 297 pstClassifierRule->usVCID_Value); 298 299 /* Checking classifier validity */ 300 if (!pstClassifierRule->bUsed || 301 pstClassifierRule->ucDirection == DOWNLINK_DIR) 302 goto out; 303 304 BCM_DEBUG_PRINT(Adapter, 305 DBG_TYPE_TX, 306 IPV4_DBG, 307 DBG_LVL_ALL, 308 "is IPv6 check!"); 309 if (pstClassifierRule->bIpv6Protocol) 310 goto out; 311 312 /* Checking IP header parameter */ 313 BCM_DEBUG_PRINT(Adapter, 314 DBG_TYPE_TX, 315 IPV4_DBG, 316 DBG_LVL_ALL, 317 "Trying to match Source IP Address"); 318 if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr)) 319 goto out; 320 BCM_DEBUG_PRINT(Adapter, 321 DBG_TYPE_TX, 322 IPV4_DBG, 323 DBG_LVL_ALL, 324 "Source IP Address Matched"); 325 326 if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr)) 327 goto out; 328 BCM_DEBUG_PRINT(Adapter, 329 DBG_TYPE_TX, 330 IPV4_DBG, 331 DBG_LVL_ALL, 332 "Destination IP Address Matched"); 333 334 if (!MatchTos(pstClassifierRule, iphd->tos)) { 335 BCM_DEBUG_PRINT(Adapter, 336 DBG_TYPE_TX, 337 IPV4_DBG, 338 DBG_LVL_ALL, 339 "TOS Match failed\n"); 340 goto out; 341 } 342 BCM_DEBUG_PRINT(Adapter, 343 DBG_TYPE_TX, 344 IPV4_DBG, 345 DBG_LVL_ALL, 346 "TOS Matched"); 347 348 if (!MatchProtocol(pstClassifierRule, iphd->protocol)) 349 goto out; 350 BCM_DEBUG_PRINT(Adapter, 351 DBG_TYPE_TX, 352 IPV4_DBG, 353 DBG_LVL_ALL, 354 "Protocol Matched"); 355 356 /* 357 * if protocol is not TCP or UDP then no 358 * need of comparing source port and destination port 359 */ 360 if (iphd->protocol != TCP && iphd->protocol != UDP) { 361 bClassificationSucceed = TRUE; 362 goto out; 363 } 364 /* Checking Transport Layer Header field if present */ 365 BCM_DEBUG_PRINT(Adapter, 366 DBG_TYPE_TX, 367 IPV4_DBG, 368 DBG_LVL_ALL, 369 "Source Port %04x", 370 (iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source); 371 372 if (!MatchSrcPort(pstClassifierRule, 373 ntohs((iphd->protocol == UDP) ? 374 xprt_hdr->uhdr.source : xprt_hdr->thdr.source))) 375 goto out; 376 BCM_DEBUG_PRINT(Adapter, 377 DBG_TYPE_TX, 378 IPV4_DBG, 379 DBG_LVL_ALL, 380 "Src Port Matched"); 381 382 BCM_DEBUG_PRINT(Adapter, 383 DBG_TYPE_TX, 384 IPV4_DBG, 385 DBG_LVL_ALL, 386 "Destination Port %04x", 387 (iphd->protocol == UDP) ? xprt_hdr->uhdr.dest : 388 xprt_hdr->thdr.dest); 389 390 if (!MatchDestPort(pstClassifierRule, 391 ntohs((iphd->protocol == UDP) ? 392 xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))) 393 goto out; 394 bClassificationSucceed = TRUE; 395 396out: 397 if (TRUE == bClassificationSucceed) { 398 INT iMatchedSFQueueIndex = 0; 399 400 iMatchedSFQueueIndex = 401 SearchSfid(Adapter, pstClassifierRule->ulSFID); 402 if (iMatchedSFQueueIndex >= NO_OF_QUEUES) 403 bClassificationSucceed = false; 404 else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) 405 bClassificationSucceed = false; 406 } 407 408 BCM_DEBUG_PRINT(Adapter, 409 DBG_TYPE_TX, 410 IPV4_DBG, 411 DBG_LVL_ALL, 412 "IpVersion4 <=========="); 413 414 return bClassificationSucceed; 415} 416 417VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter) 418{ 419 UINT iIndex = 0; 420 421 for (iIndex = 0; iIndex < HiPriority; iIndex++) { 422 if (!Adapter->PackInfo[iIndex].bValid) 423 continue; 424 425 PruneQueue(Adapter, iIndex); 426 } 427} 428 429 430/** 431 * @ingroup tx_functions 432 * This function checks if the max queue size for a queue 433 * is less than number of bytes in the queue. If so - 434 * drops packets from the Head till the number of bytes is 435 * less than or equal to max queue size for the queue. 436 */ 437static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) 438{ 439 struct sk_buff *PacketToDrop = NULL; 440 struct net_device_stats *netstats; 441 struct bcm_packet_info *curr_pack_info = &Adapter->PackInfo[iIndex]; 442 443 BCM_DEBUG_PRINT(Adapter, 444 DBG_TYPE_TX, 445 PRUNE_QUEUE, 446 DBG_LVL_ALL, 447 "=====> Index %d", 448 iIndex); 449 450 if (iIndex == HiPriority) 451 return; 452 453 if (!Adapter || (iIndex < 0) || (iIndex > HiPriority)) 454 return; 455 456 /* To Store the netdevice statistic */ 457 netstats = &Adapter->dev->stats; 458 459 spin_lock_bh(&curr_pack_info->SFQueueLock); 460 461 while (1) { 462/* while((UINT)curr_pack_info->uiCurrentPacketsOnHost > 463 SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { */ 464 465 BCM_DEBUG_PRINT(Adapter, 466 DBG_TYPE_TX, 467 PRUNE_QUEUE, 468 DBG_LVL_ALL, 469 "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x", 470 curr_pack_info->uiCurrentBytesOnHost, 471 curr_pack_info->uiMaxBucketSize); 472 473 PacketToDrop = curr_pack_info->FirstTxQueue; 474 475 if (PacketToDrop == NULL) 476 break; 477 if ((curr_pack_info->uiCurrentPacketsOnHost < 478 SF_MAX_ALLOWED_PACKETS_TO_BACKUP) && 479 ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb) + 480 SKB_CB_LATENCY_OFFSET))/HZ) <= 481 curr_pack_info->uiMaxLatency)) 482 break; 483 484 if (PacketToDrop) { 485 if (netif_msg_tx_err(Adapter)) 486 pr_info(PFX "%s: tx queue %d overlimit\n", 487 Adapter->dev->name, iIndex); 488 489 netstats->tx_dropped++; 490 491 DEQUEUEPACKET(curr_pack_info->FirstTxQueue, 492 curr_pack_info->LastTxQueue); 493 /* update current bytes and packets count */ 494 curr_pack_info->uiCurrentBytesOnHost -= 495 PacketToDrop->len; 496 curr_pack_info->uiCurrentPacketsOnHost--; 497 /* update dropped bytes and packets counts */ 498 curr_pack_info->uiDroppedCountBytes += PacketToDrop->len; 499 curr_pack_info->uiDroppedCountPackets++; 500 dev_kfree_skb(PacketToDrop); 501 502 } 503 504 BCM_DEBUG_PRINT(Adapter, 505 DBG_TYPE_TX, 506 PRUNE_QUEUE, 507 DBG_LVL_ALL, 508 "Dropped Bytes:%x Dropped Packets:%x", 509 curr_pack_info->uiDroppedCountBytes, 510 curr_pack_info->uiDroppedCountPackets); 511 512 atomic_dec(&Adapter->TotalPacketCount); 513 } 514 515 spin_unlock_bh(&curr_pack_info->SFQueueLock); 516 517 BCM_DEBUG_PRINT(Adapter, 518 DBG_TYPE_TX, 519 PRUNE_QUEUE, 520 DBG_LVL_ALL, 521 "TotalPacketCount:%x", 522 atomic_read(&Adapter->TotalPacketCount)); 523 BCM_DEBUG_PRINT(Adapter, 524 DBG_TYPE_TX, 525 PRUNE_QUEUE, 526 DBG_LVL_ALL, 527 "<====="); 528} 529 530VOID flush_all_queues(struct bcm_mini_adapter *Adapter) 531{ 532 INT iQIndex; 533 UINT uiTotalPacketLength; 534 struct sk_buff *PacketToDrop = NULL; 535 struct bcm_packet_info *curr_packet_info; 536 537 BCM_DEBUG_PRINT(Adapter, 538 DBG_TYPE_OTHERS, 539 DUMP_INFO, 540 DBG_LVL_ALL, 541 "=====>"); 542 543 /* down(&Adapter->data_packet_queue_lock); */ 544 for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) { 545 struct net_device_stats *netstats = &Adapter->dev->stats; 546 547 curr_packet_info = &Adapter->PackInfo[iQIndex]; 548 549 spin_lock_bh(&curr_packet_info->SFQueueLock); 550 while (curr_packet_info->FirstTxQueue) { 551 PacketToDrop = curr_packet_info->FirstTxQueue; 552 if (PacketToDrop) { 553 uiTotalPacketLength = PacketToDrop->len; 554 netstats->tx_dropped++; 555 } else 556 uiTotalPacketLength = 0; 557 558 DEQUEUEPACKET(curr_packet_info->FirstTxQueue, 559 curr_packet_info->LastTxQueue); 560 561 /* Free the skb */ 562 dev_kfree_skb(PacketToDrop); 563 564 /* update current bytes and packets count */ 565 curr_packet_info->uiCurrentBytesOnHost -= uiTotalPacketLength; 566 curr_packet_info->uiCurrentPacketsOnHost--; 567 568 /* update dropped bytes and packets counts */ 569 curr_packet_info->uiDroppedCountBytes += uiTotalPacketLength; 570 curr_packet_info->uiDroppedCountPackets++; 571 572 BCM_DEBUG_PRINT(Adapter, 573 DBG_TYPE_OTHERS, 574 DUMP_INFO, 575 DBG_LVL_ALL, 576 "Dropped Bytes:%x Dropped Packets:%x", 577 curr_packet_info->uiDroppedCountBytes, 578 curr_packet_info->uiDroppedCountPackets); 579 atomic_dec(&Adapter->TotalPacketCount); 580 } 581 spin_unlock_bh(&curr_packet_info->SFQueueLock); 582 } 583 /* up(&Adapter->data_packet_queue_lock); */ 584 BCM_DEBUG_PRINT(Adapter, 585 DBG_TYPE_OTHERS, 586 DUMP_INFO, 587 DBG_LVL_ALL, 588 "<====="); 589} 590 591USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff *skb) 592{ 593 INT uiLoopIndex = 0; 594 struct bcm_classifier_rule *pstClassifierRule = NULL; 595 struct bcm_eth_packet_info stEthCsPktInfo; 596 PVOID pvEThPayload = NULL; 597 struct iphdr *pIpHeader = NULL; 598 INT uiSfIndex = 0; 599 USHORT usIndex = Adapter->usBestEffortQueueIndex; 600 bool bFragmentedPkt = false, bClassificationSucceed = false; 601 USHORT usCurrFragment = 0; 602 603 struct bcm_tcp_header *pTcpHeader; 604 UCHAR IpHeaderLength; 605 UCHAR TcpHeaderLength; 606 607 pvEThPayload = skb->data; 608 *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = 0; 609 EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo); 610 611 switch (stEthCsPktInfo.eNwpktEthFrameType) { 612 case eEth802LLCFrame: 613 BCM_DEBUG_PRINT(Adapter, 614 DBG_TYPE_TX, 615 IPV4_DBG, 616 DBG_LVL_ALL, 617 "ClassifyPacket : 802LLCFrame\n"); 618 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame); 619 break; 620 case eEth802LLCSNAPFrame: 621 BCM_DEBUG_PRINT(Adapter, 622 DBG_TYPE_TX, 623 IPV4_DBG, 624 DBG_LVL_ALL, 625 "ClassifyPacket : 802LLC SNAP Frame\n"); 626 pIpHeader = pvEThPayload + 627 sizeof(struct bcm_eth_llc_snap_frame); 628 break; 629 case eEth802QVLANFrame: 630 BCM_DEBUG_PRINT(Adapter, 631 DBG_TYPE_TX, 632 IPV4_DBG, 633 DBG_LVL_ALL, 634 "ClassifyPacket : 802.1Q VLANFrame\n"); 635 pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame); 636 break; 637 case eEthOtherFrame: 638 BCM_DEBUG_PRINT(Adapter, 639 DBG_TYPE_TX, 640 IPV4_DBG, 641 DBG_LVL_ALL, 642 "ClassifyPacket : ETH Other Frame\n"); 643 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame); 644 break; 645 default: 646 BCM_DEBUG_PRINT(Adapter, 647 DBG_TYPE_TX, 648 IPV4_DBG, 649 DBG_LVL_ALL, 650 "ClassifyPacket : Unrecognized ETH Frame\n"); 651 pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame); 652 break; 653 } 654 655 if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) { 656 usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET); 657 if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment) 658 bFragmentedPkt = TRUE; 659 660 if (bFragmentedPkt) { 661 /* Fragmented Packet. Get Frag Classifier Entry. */ 662 pstClassifierRule = GetFragIPClsEntry(Adapter, 663 pIpHeader->id, 664 pIpHeader->saddr); 665 if (pstClassifierRule) { 666 BCM_DEBUG_PRINT(Adapter, 667 DBG_TYPE_TX, 668 IPV4_DBG, 669 DBG_LVL_ALL, 670 "It is next Fragmented pkt"); 671 bClassificationSucceed = TRUE; 672 } 673 if (!(ntohs(pIpHeader->frag_off) & IP_MF)) { 674 /* Fragmented Last packet . Remove Frag Classifier Entry */ 675 BCM_DEBUG_PRINT(Adapter, 676 DBG_TYPE_TX, 677 IPV4_DBG, 678 DBG_LVL_ALL, 679 "This is the last fragmented Pkt"); 680 DelFragIPClsEntry(Adapter, 681 pIpHeader->id, 682 pIpHeader->saddr); 683 } 684 } 685 } 686 687 for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) { 688 if (bClassificationSucceed) 689 break; 690 /* 691 * Iterate through all classifiers which are already in order of priority 692 * to classify the packet until match found 693 */ 694 if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) { 695 bClassificationSucceed = false; 696 continue; 697 } 698 BCM_DEBUG_PRINT(Adapter, 699 DBG_TYPE_TX, 700 IPV4_DBG, 701 DBG_LVL_ALL, 702 "Adapter->PackInfo[%d].bvalid=True\n", 703 uiLoopIndex); 704 705 if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) { 706 bClassificationSucceed = false; /* cannot be processed for classification. */ 707 continue; /* it is a down link connection */ 708 } 709 710 pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex]; 711 712 uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); 713 if (uiSfIndex >= NO_OF_QUEUES) { 714 BCM_DEBUG_PRINT(Adapter, 715 DBG_TYPE_TX, 716 IPV4_DBG, 717 DBG_LVL_ALL, 718 "Queue Not Valid. SearchSfid for this classifier Failed\n"); 719 continue; 720 } 721 722 if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) { 723 724 if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) { 725 BCM_DEBUG_PRINT(Adapter, 726 DBG_TYPE_TX, 727 IPV4_DBG, 728 DBG_LVL_ALL, 729 " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n"); 730 bClassificationSucceed = false; 731 continue; 732 } 733 734 735 736 BCM_DEBUG_PRINT(Adapter, 737 DBG_TYPE_TX, 738 IPV4_DBG, 739 DBG_LVL_ALL, 740 "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", 741 pstClassifierRule->uiClassifierRuleIndex, 742 Adapter->PackInfo[uiSfIndex].ulSFID); 743 bClassificationSucceed = EThCSClassifyPkt(Adapter, 744 skb, 745 &stEthCsPktInfo, 746 pstClassifierRule, 747 Adapter->PackInfo[uiSfIndex].bEthCSSupport); 748 749 if (!bClassificationSucceed) { 750 BCM_DEBUG_PRINT(Adapter, 751 DBG_TYPE_TX, 752 IPV4_DBG, 753 DBG_LVL_ALL, 754 "ClassifyPacket : Ethernet CS Classification Failed\n"); 755 continue; 756 } 757 } else { /* No ETH Supported on this SF */ 758 if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) { 759 BCM_DEBUG_PRINT(Adapter, 760 DBG_TYPE_TX, 761 IPV4_DBG, 762 DBG_LVL_ALL, 763 " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n"); 764 bClassificationSucceed = false; 765 continue; 766 } 767 } 768 769 BCM_DEBUG_PRINT(Adapter, 770 DBG_TYPE_TX, 771 IPV4_DBG, 772 DBG_LVL_ALL, 773 "Proceeding to IP CS Clasification"); 774 775 if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) { 776 777 if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) { 778 BCM_DEBUG_PRINT(Adapter, 779 DBG_TYPE_TX, 780 IPV4_DBG, 781 DBG_LVL_ALL, 782 " ClassifyPacket : Packet is Not an IP Packet\n"); 783 bClassificationSucceed = false; 784 continue; 785 } 786 BCM_DEBUG_PRINT(Adapter, 787 DBG_TYPE_TX, 788 IPV4_DBG, 789 DBG_LVL_ALL, 790 "Dump IP Header :\n"); 791 DumpFullPacket((PUCHAR)pIpHeader, 20); 792 793 if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) 794 bClassificationSucceed = IpVersion4(Adapter, 795 pIpHeader, 796 pstClassifierRule); 797 else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet) 798 bClassificationSucceed = IpVersion6(Adapter, 799 pIpHeader, 800 pstClassifierRule); 801 } 802 } 803 804 if (bClassificationSucceed == TRUE) { 805 BCM_DEBUG_PRINT(Adapter, 806 DBG_TYPE_TX, 807 IPV4_DBG, 808 DBG_LVL_ALL, 809 "CF id : %d, SF ID is =%lu", 810 pstClassifierRule->uiClassifierRuleIndex, 811 pstClassifierRule->ulSFID); 812 813 /* Store The matched Classifier in SKB */ 814 *((UINT32 *)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = 815 pstClassifierRule->uiClassifierRuleIndex; 816 if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && 817 (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= 818 skb->len)) { 819 IpHeaderLength = pIpHeader->ihl; 820 pTcpHeader = 821 (struct bcm_tcp_header *)(((PUCHAR)pIpHeader) + 822 (IpHeaderLength*4)); 823 TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength); 824 825 if ((pTcpHeader->ucFlags & TCP_ACK) && 826 (ntohs(pIpHeader->tot_len) == 827 (IpHeaderLength*4)+(TcpHeaderLength*4))) 828 *((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = 829 TCP_ACK; 830 } 831 832 usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); 833 BCM_DEBUG_PRINT(Adapter, 834 DBG_TYPE_TX, 835 IPV4_DBG, 836 DBG_LVL_ALL, 837 "index is =%d", 838 usIndex); 839 840 /* 841 * If this is the first fragment of a Fragmented pkt, 842 * add this CF. Only This CF should be used for all other 843 * fragment of this Pkt. 844 */ 845 if (bFragmentedPkt && (usCurrFragment == 0)) { 846 /* 847 * First Fragment of Fragmented Packet. 848 * Create Frag CLS Entry 849 */ 850 struct bcm_fragmented_packet_info stFragPktInfo; 851 852 stFragPktInfo.bUsed = TRUE; 853 stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr; 854 stFragPktInfo.usIpIdentification = pIpHeader->id; 855 stFragPktInfo.pstMatchedClassifierEntry = 856 pstClassifierRule; 857 stFragPktInfo.bOutOfOrderFragment = false; 858 AddFragIPClsEntry(Adapter, &stFragPktInfo); 859 } 860 861 862 } 863 864 return bClassificationSucceed ? usIndex : INVALID_QUEUE_INDEX; 865} 866 867static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, 868 PUCHAR Mac) 869{ 870 UINT i = 0; 871 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 872 873 if (pstClassifierRule->ucEthCSSrcMACLen == 0) 874 return TRUE; 875 BCM_DEBUG_PRINT(Adapter, 876 DBG_TYPE_TX, 877 IPV4_DBG, 878 DBG_LVL_ALL, 879 "%s\n", __func__); 880 for (i = 0; i < MAC_ADDRESS_SIZE; i++) { 881 BCM_DEBUG_PRINT(Adapter, 882 DBG_TYPE_TX, 883 IPV4_DBG, 884 DBG_LVL_ALL, 885 "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", 886 i, 887 Mac[i], 888 pstClassifierRule->au8EThCSSrcMAC[i], 889 pstClassifierRule->au8EThCSSrcMACMask[i]); 890 if ((pstClassifierRule->au8EThCSSrcMAC[i] & 891 pstClassifierRule->au8EThCSSrcMACMask[i]) != 892 (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i])) 893 return false; 894 } 895 return TRUE; 896} 897 898static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, 899 PUCHAR Mac) 900{ 901 UINT i = 0; 902 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 903 904 if (pstClassifierRule->ucEthCSDestMACLen == 0) 905 return TRUE; 906 BCM_DEBUG_PRINT(Adapter, 907 DBG_TYPE_TX, 908 IPV4_DBG, 909 DBG_LVL_ALL, 910 "%s\n", 911 __func__); 912 for (i = 0; i < MAC_ADDRESS_SIZE; i++) { 913 BCM_DEBUG_PRINT(Adapter, 914 DBG_TYPE_TX, 915 IPV4_DBG, 916 DBG_LVL_ALL, 917 "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", 918 i, 919 Mac[i], 920 pstClassifierRule->au8EThCSDestMAC[i], 921 pstClassifierRule->au8EThCSDestMACMask[i]); 922 if ((pstClassifierRule->au8EThCSDestMAC[i] & 923 pstClassifierRule->au8EThCSDestMACMask[i]) != 924 (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i])) 925 return false; 926 } 927 return TRUE; 928} 929 930static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, 931 struct sk_buff *skb, 932 struct bcm_eth_packet_info *pstEthCsPktInfo) 933{ 934 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 935 936 if ((pstClassifierRule->ucEtherTypeLen == 0) || 937 (pstClassifierRule->au8EthCSEtherType[0] == 0)) 938 return TRUE; 939 940 BCM_DEBUG_PRINT(Adapter, 941 DBG_TYPE_TX, 942 IPV4_DBG, 943 DBG_LVL_ALL, 944 "%s SrcEtherType:%x CLS EtherType[0]:%x\n", 945 __func__, 946 pstEthCsPktInfo->usEtherType, 947 pstClassifierRule->au8EthCSEtherType[0]); 948 if (pstClassifierRule->au8EthCSEtherType[0] == 1) { 949 BCM_DEBUG_PRINT(Adapter, 950 DBG_TYPE_TX, 951 IPV4_DBG, 952 DBG_LVL_ALL, 953 "%s CLS EtherType[1]:%x EtherType[2]:%x\n", 954 __func__, 955 pstClassifierRule->au8EthCSEtherType[1], 956 pstClassifierRule->au8EthCSEtherType[2]); 957 958 if (memcmp(&pstEthCsPktInfo->usEtherType, 959 &pstClassifierRule->au8EthCSEtherType[1], 960 2) == 0) 961 return TRUE; 962 else 963 return false; 964 } 965 966 if (pstClassifierRule->au8EthCSEtherType[0] == 2) { 967 if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType) 968 return false; 969 970 BCM_DEBUG_PRINT(Adapter, 971 DBG_TYPE_TX, 972 IPV4_DBG, 973 DBG_LVL_ALL, 974 "%s EthCS DSAP:%x EtherType[2]:%x\n", 975 __func__, 976 pstEthCsPktInfo->ucDSAP, 977 pstClassifierRule->au8EthCSEtherType[2]); 978 if (pstEthCsPktInfo->ucDSAP == 979 pstClassifierRule->au8EthCSEtherType[2]) 980 return TRUE; 981 else 982 return false; 983 984 } 985 986 return false; 987 988} 989 990static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, 991 struct sk_buff *skb, 992 struct bcm_eth_packet_info *pstEthCsPktInfo) 993{ 994 bool bClassificationSucceed = false; 995 USHORT usVLANID; 996 B_UINT8 uPriority = 0; 997 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 998 999 BCM_DEBUG_PRINT(Adapter, 1000 DBG_TYPE_TX, 1001 IPV4_DBG, 1002 DBG_LVL_ALL, 1003 "%s CLS UserPrio:%x CLS VLANID:%x\n", 1004 __func__, 1005 ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), 1006 pstClassifierRule->usVLANID); 1007 1008 /* 1009 * In case FW didn't receive the TLV, 1010 * the priority field should be ignored 1011 */ 1012 if (pstClassifierRule->usValidityBitMap & 1013 (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) { 1014 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame) 1015 return false; 1016 1017 uPriority = (ntohs(*(USHORT *)(skb->data + 1018 sizeof(struct bcm_eth_header))) & 1019 0xF000) >> 13; 1020 1021 if ((uPriority >= pstClassifierRule->usUserPriority[0]) && 1022 (uPriority <= 1023 pstClassifierRule->usUserPriority[1])) 1024 bClassificationSucceed = TRUE; 1025 1026 if (!bClassificationSucceed) 1027 return false; 1028 } 1029 1030 BCM_DEBUG_PRINT(Adapter, 1031 DBG_TYPE_TX, 1032 IPV4_DBG, 1033 DBG_LVL_ALL, 1034 "ETH CS 802.1 D User Priority Rule Matched\n"); 1035 1036 bClassificationSucceed = false; 1037 1038 if (pstClassifierRule->usValidityBitMap & 1039 (1<<PKT_CLASSIFICATION_VLANID_VALID)) { 1040 if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame) 1041 return false; 1042 1043 usVLANID = ntohs(*(USHORT *)(skb->data + 1044 sizeof(struct bcm_eth_header))) & 0xFFF; 1045 1046 BCM_DEBUG_PRINT(Adapter, 1047 DBG_TYPE_TX, 1048 IPV4_DBG, 1049 DBG_LVL_ALL, 1050 "%s Pkt VLANID %x Priority: %d\n", 1051 __func__, 1052 usVLANID, 1053 uPriority); 1054 1055 if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4)) 1056 bClassificationSucceed = TRUE; 1057 1058 if (!bClassificationSucceed) 1059 return false; 1060 } 1061 1062 BCM_DEBUG_PRINT(Adapter, 1063 DBG_TYPE_TX, 1064 IPV4_DBG, 1065 DBG_LVL_ALL, 1066 "ETH CS 802.1 Q VLAN ID Rule Matched\n"); 1067 1068 return TRUE; 1069} 1070 1071 1072static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, 1073 struct sk_buff *skb, 1074 struct bcm_eth_packet_info *pstEthCsPktInfo, 1075 struct bcm_classifier_rule *pstClassifierRule, 1076 B_UINT8 EthCSCupport) 1077{ 1078 bool bClassificationSucceed = false; 1079 1080 bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, 1081 ((struct bcm_eth_header *)(skb->data))->au8SourceAddress); 1082 if (!bClassificationSucceed) 1083 return false; 1084 BCM_DEBUG_PRINT(Adapter, 1085 DBG_TYPE_TX, 1086 IPV4_DBG, 1087 DBG_LVL_ALL, 1088 "ETH CS SrcMAC Matched\n"); 1089 1090 bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, 1091 ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress); 1092 if (!bClassificationSucceed) 1093 return false; 1094 BCM_DEBUG_PRINT(Adapter, 1095 DBG_TYPE_TX, 1096 IPV4_DBG, 1097 DBG_LVL_ALL, 1098 "ETH CS DestMAC Matched\n"); 1099 1100 /* classify on ETHType/802.2SAP TLV */ 1101 bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, 1102 skb, 1103 pstEthCsPktInfo); 1104 if (!bClassificationSucceed) 1105 return false; 1106 1107 BCM_DEBUG_PRINT(Adapter, 1108 DBG_TYPE_TX, 1109 IPV4_DBG, 1110 DBG_LVL_ALL, 1111 "ETH CS EthType/802.2SAP Matched\n"); 1112 1113 /* classify on 802.1VLAN Header Parameters */ 1114 bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, 1115 skb, 1116 pstEthCsPktInfo); 1117 if (!bClassificationSucceed) 1118 return false; 1119 BCM_DEBUG_PRINT(Adapter, 1120 DBG_TYPE_TX, 1121 IPV4_DBG, 1122 DBG_LVL_ALL, 1123 "ETH CS 802.1 VLAN Rules Matched\n"); 1124 1125 return bClassificationSucceed; 1126} 1127 1128static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, 1129 PVOID pvEthPayload, 1130 struct bcm_eth_packet_info *pstEthCsPktInfo) 1131{ 1132 USHORT u16Etype = ntohs( 1133 ((struct bcm_eth_header *)pvEthPayload)->u16Etype); 1134 1135 BCM_DEBUG_PRINT(Adapter, 1136 DBG_TYPE_TX, 1137 IPV4_DBG, 1138 DBG_LVL_ALL, 1139 "EthCSGetPktInfo : Eth Hdr Type : %X\n", 1140 u16Etype); 1141 if (u16Etype > 0x5dc) { 1142 BCM_DEBUG_PRINT(Adapter, 1143 DBG_TYPE_TX, 1144 IPV4_DBG, 1145 DBG_LVL_ALL, 1146 "EthCSGetPktInfo : ETH2 Frame\n"); 1147 /* ETH2 Frame */ 1148 if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) { 1149 /* 802.1Q VLAN Header */ 1150 pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame; 1151 u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType; 1152 /* ((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority */ 1153 } else { 1154 pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame; 1155 u16Etype = ntohs(u16Etype); 1156 } 1157 } else { 1158 /* 802.2 LLC */ 1159 BCM_DEBUG_PRINT(Adapter, 1160 DBG_TYPE_TX, 1161 IPV4_DBG, 1162 DBG_LVL_ALL, 1163 "802.2 LLC Frame\n"); 1164 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame; 1165 pstEthCsPktInfo->ucDSAP = 1166 ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP; 1167 if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) { 1168 /* SNAP Frame */ 1169 pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame; 1170 u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType; 1171 } 1172 } 1173 if (u16Etype == ETHERNET_FRAMETYPE_IPV4) 1174 pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet; 1175 else if (u16Etype == ETHERNET_FRAMETYPE_IPV6) 1176 pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet; 1177 else 1178 pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket; 1179 1180 pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype; 1181 BCM_DEBUG_PRINT(Adapter, 1182 DBG_TYPE_TX, 1183 IPV4_DBG, 1184 DBG_LVL_ALL, 1185 "EthCsPktInfo->eNwpktIPFrameType : %x\n", 1186 pstEthCsPktInfo->eNwpktIPFrameType); 1187 BCM_DEBUG_PRINT(Adapter, 1188 DBG_TYPE_TX, 1189 IPV4_DBG, 1190 DBG_LVL_ALL, 1191 "EthCsPktInfo->eNwpktEthFrameType : %x\n", 1192 pstEthCsPktInfo->eNwpktEthFrameType); 1193 BCM_DEBUG_PRINT(Adapter, 1194 DBG_TYPE_TX, 1195 IPV4_DBG, 1196 DBG_LVL_ALL, 1197 "EthCsPktInfo->usEtherType : %x\n", 1198 pstEthCsPktInfo->usEtherType); 1199} 1200