Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 1 | /** |
| 2 | @file Qos.C |
| 3 | This file contains the routines related to Quality of Service. |
| 4 | */ |
| 5 | #include "headers.h" |
| 6 | |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 7 | static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload,PS_ETHCS_PKT_INFO pstEthCsPktInfo); |
| 8 | static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo,S_CLASSIFIER_RULE *pstClassifierRule, B_UINT8 EthCSCupport); |
| 9 | |
| 10 | static USHORT IpVersion4(PMINI_ADAPTER Adapter, struct iphdr *iphd, |
| 11 | S_CLASSIFIER_RULE *pstClassifierRule ); |
| 12 | |
| 13 | static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex); |
| 14 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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(S_CLASSIFIER_RULE *pstClassifierRule,ULONG ulSrcIP) |
| 28 | { |
| 29 | UCHAR ucLoopIndex=0; |
| 30 | |
| 31 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 32 | |
| 33 | ulSrcIP=ntohl(ulSrcIP); |
| 34 | if(0 == pstClassifierRule->ucIPSourceAddressLength) |
| 35 | return TRUE; |
| 36 | for(ucLoopIndex=0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);ucLoopIndex++) |
| 37 | { |
| 38 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); |
| 39 | if((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP)== |
| 40 | (pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] )) |
| 41 | { |
| 42 | return TRUE; |
| 43 | } |
| 44 | } |
| 45 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched"); |
| 46 | return FALSE; |
| 47 | } |
| 48 | |
| 49 | |
| 50 | /******************************************************************* |
| 51 | * Function - MatchDestIpAddress() |
| 52 | * |
| 53 | * Description - Checks whether the Destination IP address from the packet |
| 54 | * matches with that of Queue. |
| 55 | * |
| 56 | * Parameters - pstClassifierRule: Pointer to the packet info structure. |
| 57 | * - ulDestIP : Destination IP address from the packet. |
| 58 | * |
| 59 | * Returns - TRUE(If address matches) else FAIL . |
| 60 | *********************************************************************/ |
| 61 | BOOLEAN MatchDestIpAddress(S_CLASSIFIER_RULE *pstClassifierRule,ULONG ulDestIP) |
| 62 | { |
| 63 | UCHAR ucLoopIndex=0; |
| 64 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 65 | |
| 66 | ulDestIP=ntohl(ulDestIP); |
| 67 | if(0 == pstClassifierRule->ucIPDestinationAddressLength) |
| 68 | return TRUE; |
| 69 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); |
| 70 | |
| 71 | for(ucLoopIndex=0;ucLoopIndex<(pstClassifierRule->ucIPDestinationAddressLength);ucLoopIndex++) |
| 72 | { |
| 73 | if((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP)== |
| 74 | (pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex])) |
| 75 | { |
| 76 | return TRUE; |
| 77 | } |
| 78 | } |
| 79 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched"); |
| 80 | return FALSE; |
| 81 | } |
| 82 | |
| 83 | |
| 84 | /************************************************************************ |
| 85 | * Function - MatchTos() |
| 86 | * |
| 87 | * Description - Checks the TOS from the packet matches with that of queue. |
| 88 | * |
| 89 | * Parameters - pstClassifierRule : Pointer to the packet info structure. |
| 90 | * - ucTypeOfService: TOS from the packet. |
| 91 | * |
| 92 | * Returns - TRUE(If address matches) else FAIL. |
| 93 | **************************************************************************/ |
| 94 | BOOLEAN MatchTos(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucTypeOfService) |
| 95 | { |
| 96 | |
| 97 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 98 | if( 3 != pstClassifierRule->ucIPTypeOfServiceLength ) |
| 99 | return TRUE; |
| 100 | |
| 101 | if(((pstClassifierRule->ucTosMask & ucTypeOfService)<=pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService)>=pstClassifierRule->ucTosLow)) |
| 102 | { |
| 103 | return TRUE; |
| 104 | } |
| 105 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched"); |
| 106 | return FALSE; |
| 107 | } |
| 108 | |
| 109 | |
| 110 | /*************************************************************************** |
| 111 | * Function - MatchProtocol() |
| 112 | * |
| 113 | * Description - Checks the protocol from the packet matches with that of queue. |
| 114 | * |
| 115 | * Parameters - pstClassifierRule: Pointer to the packet info structure. |
| 116 | * - ucProtocol : Protocol from the packet. |
| 117 | * |
| 118 | * Returns - TRUE(If address matches) else FAIL. |
| 119 | ****************************************************************************/ |
| 120 | BOOLEAN MatchProtocol(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucProtocol) |
| 121 | { |
| 122 | UCHAR ucLoopIndex=0; |
| 123 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 124 | if(0 == pstClassifierRule->ucProtocolLength) |
| 125 | return TRUE; |
| 126 | for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucProtocolLength;ucLoopIndex++) |
| 127 | { |
| 128 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X",ucProtocol,pstClassifierRule->ucProtocol[ucLoopIndex]); |
| 129 | if(pstClassifierRule->ucProtocol[ucLoopIndex]==ucProtocol) |
| 130 | { |
| 131 | return TRUE; |
| 132 | } |
| 133 | } |
| 134 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched"); |
| 135 | return FALSE; |
| 136 | } |
| 137 | |
| 138 | |
| 139 | /*********************************************************************** |
| 140 | * Function - MatchSrcPort() |
| 141 | * |
| 142 | * Description - Checks, Source port from the packet matches with that of queue. |
| 143 | * |
| 144 | * Parameters - pstClassifierRule: Pointer to the packet info structure. |
| 145 | * - ushSrcPort : Source port from the packet. |
| 146 | * |
| 147 | * Returns - TRUE(If address matches) else FAIL. |
| 148 | ***************************************************************************/ |
| 149 | BOOLEAN MatchSrcPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushSrcPort) |
| 150 | { |
| 151 | UCHAR ucLoopIndex=0; |
| 152 | |
| 153 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 154 | |
| 155 | |
| 156 | if(0 == pstClassifierRule->ucSrcPortRangeLength) |
| 157 | return TRUE; |
| 158 | for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucSrcPortRangeLength;ucLoopIndex++) |
| 159 | { |
| 160 | if(ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] && |
| 161 | ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex]) |
| 162 | { |
| 163 | return TRUE; |
| 164 | } |
| 165 | } |
| 166 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ",ushSrcPort); |
| 167 | return FALSE; |
| 168 | } |
| 169 | |
| 170 | |
| 171 | /*********************************************************************** |
| 172 | * Function - MatchDestPort() |
| 173 | * |
| 174 | * Description - Checks, Destination port from packet matches with that of queue. |
| 175 | * |
| 176 | * Parameters - pstClassifierRule: Pointer to the packet info structure. |
| 177 | * - ushDestPort : Destination port from the packet. |
| 178 | * |
| 179 | * Returns - TRUE(If address matches) else FAIL. |
| 180 | ***************************************************************************/ |
| 181 | BOOLEAN MatchDestPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushDestPort) |
| 182 | { |
| 183 | UCHAR ucLoopIndex=0; |
| 184 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 185 | |
| 186 | if(0 == pstClassifierRule->ucDestPortRangeLength) |
| 187 | return TRUE; |
| 188 | |
| 189 | for(ucLoopIndex=0;ucLoopIndex<pstClassifierRule->ucDestPortRangeLength;ucLoopIndex++) |
| 190 | { |
| 191 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X 0x%X 0x%X",ushDestPort,pstClassifierRule->usDestPortRangeLo[ucLoopIndex],pstClassifierRule->usDestPortRangeHi[ucLoopIndex]); |
| 192 | |
| 193 | if(ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] && |
| 194 | ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex]) |
| 195 | { |
| 196 | return TRUE; |
| 197 | } |
| 198 | } |
| 199 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched",ushDestPort); |
| 200 | return FALSE; |
| 201 | } |
| 202 | /** |
| 203 | @ingroup tx_functions |
| 204 | Compares IPV4 Ip address and port number |
| 205 | @return Queue Index. |
| 206 | */ |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 207 | static USHORT IpVersion4(PMINI_ADAPTER Adapter, |
| 208 | struct iphdr *iphd, |
| 209 | S_CLASSIFIER_RULE *pstClassifierRule ) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 210 | { |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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 | } |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 304 | |
| 305 | VOID PruneQueueAllSF(PMINI_ADAPTER Adapter) |
| 306 | { |
| 307 | UINT iIndex = 0; |
| 308 | |
| 309 | for(iIndex = 0; iIndex < HiPriority; iIndex++) |
| 310 | { |
| 311 | if(!Adapter->PackInfo[iIndex].bValid) |
| 312 | continue; |
| 313 | |
| 314 | PruneQueue(Adapter, iIndex); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | |
| 319 | /** |
| 320 | @ingroup tx_functions |
| 321 | This function checks if the max queue size for a queue |
| 322 | is less than number of bytes in the queue. If so - |
| 323 | drops packets from the Head till the number of bytes is |
| 324 | less than or equal to max queue size for the queue. |
| 325 | */ |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 326 | static VOID PruneQueue(PMINI_ADAPTER Adapter, INT iIndex) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 327 | { |
| 328 | struct sk_buff* PacketToDrop=NULL; |
Stephen Hemminger | 92bc605 | 2010-10-29 08:22:10 -0700 | [diff] [blame] | 329 | struct net_device_stats *netstats; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 330 | |
| 331 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d",iIndex); |
| 332 | |
| 333 | if(iIndex == HiPriority) |
Stephen Hemminger | 92bc605 | 2010-10-29 08:22:10 -0700 | [diff] [blame] | 334 | return; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 335 | |
| 336 | if(!Adapter || (iIndex < 0) || (iIndex > HiPriority)) |
| 337 | return; |
| 338 | |
| 339 | /* To Store the netdevice statistic */ |
Stephen Hemminger | 92bc605 | 2010-10-29 08:22:10 -0700 | [diff] [blame] | 340 | netstats = &Adapter->dev->stats; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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 | { |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 362 | if (netif_msg_tx_err(Adapter)) |
| 363 | pr_info(PFX "%s: tx queue %d overlimit\n", |
| 364 | Adapter->dev->name, iIndex); |
| 365 | |
Andres Salomon | e6f597a | 2011-01-17 16:11:12 -0800 | [diff] [blame] | 366 | netstats->tx_dropped++; |
Stephen Hemminger | cacd922 | 2010-11-01 13:34:35 -0400 | [diff] [blame] | 367 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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++; |
Stephen Hemminger | 082e889 | 2010-11-01 09:35:21 -0400 | [diff] [blame] | 377 | dev_kfree_skb(PacketToDrop); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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 | |
| 395 | VOID flush_all_queues(PMINI_ADAPTER Adapter) |
| 396 | { |
| 397 | INT iQIndex; |
| 398 | UINT uiTotalPacketLength; |
Stephen Hemminger | cacd922 | 2010-11-01 13:34:35 -0400 | [diff] [blame] | 399 | struct sk_buff* PacketToDrop=NULL; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 400 | |
| 401 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>"); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 402 | |
| 403 | // down(&Adapter->data_packet_queue_lock); |
| 404 | for(iQIndex=LowPriority; iQIndex<HiPriority; iQIndex++) |
| 405 | { |
Andres Salomon | e6f597a | 2011-01-17 16:11:12 -0800 | [diff] [blame] | 406 | struct net_device_stats *netstats = &Adapter->dev->stats; |
Stephen Hemminger | cacd922 | 2010-11-01 13:34:35 -0400 | [diff] [blame] | 407 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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; |
Andres Salomon | e6f597a | 2011-01-17 16:11:12 -0800 | [diff] [blame] | 415 | netstats->tx_dropped++; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 416 | } |
| 417 | else |
| 418 | uiTotalPacketLength = 0; |
| 419 | |
| 420 | DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, |
| 421 | Adapter->PackInfo[iQIndex].LastTxQueue); |
| 422 | |
| 423 | /* Free the skb */ |
Stephen Hemminger | 082e889 | 2010-11-01 09:35:21 -0400 | [diff] [blame] | 424 | dev_kfree_skb(PacketToDrop); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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 | |
| 445 | USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) |
| 446 | { |
| 447 | INT uiLoopIndex=0; |
| 448 | S_CLASSIFIER_RULE *pstClassifierRule = NULL; |
| 449 | S_ETHCS_PKT_INFO stEthCsPktInfo; |
| 450 | PVOID pvEThPayload = NULL; |
| 451 | struct iphdr *pIpHeader = NULL; |
| 452 | INT uiSfIndex=0; |
| 453 | USHORT usIndex=Adapter->usBestEffortQueueIndex; |
| 454 | BOOLEAN bFragmentedPkt=FALSE,bClassificationSucceed=FALSE; |
| 455 | USHORT usCurrFragment =0; |
| 456 | |
| 457 | PTCP_HEADER pTcpHeader; |
| 458 | UCHAR IpHeaderLength; |
| 459 | UCHAR TcpHeaderLength; |
| 460 | |
| 461 | pvEThPayload = skb->data; |
| 462 | *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = 0; |
| 463 | EThCSGetPktInfo(Adapter,pvEThPayload,&stEthCsPktInfo); |
| 464 | |
| 465 | switch(stEthCsPktInfo.eNwpktEthFrameType) |
| 466 | { |
| 467 | case eEth802LLCFrame: |
| 468 | { |
| 469 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n"); |
| 470 | pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_FRAME); |
| 471 | break; |
| 472 | } |
| 473 | |
| 474 | case eEth802LLCSNAPFrame: |
| 475 | { |
| 476 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n"); |
| 477 | pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_SNAP_FRAME); |
| 478 | break; |
| 479 | } |
| 480 | case eEth802QVLANFrame: |
| 481 | { |
| 482 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n"); |
| 483 | pIpHeader = pvEThPayload + sizeof(ETH_CS_802_Q_FRAME); |
| 484 | break; |
| 485 | } |
| 486 | case eEthOtherFrame: |
| 487 | { |
| 488 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n"); |
| 489 | pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME); |
| 490 | break; |
| 491 | } |
| 492 | default: |
| 493 | { |
| 494 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n"); |
| 495 | pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME); |
| 496 | break; |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) |
| 501 | { |
| 502 | usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET); |
| 503 | if((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment) |
| 504 | bFragmentedPkt = TRUE; |
| 505 | |
| 506 | if(bFragmentedPkt) |
| 507 | { |
| 508 | //Fragmented Packet. Get Frag Classifier Entry. |
| 509 | pstClassifierRule = GetFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); |
| 510 | if(pstClassifierRule) |
| 511 | { |
| 512 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"It is next Fragmented pkt"); |
| 513 | bClassificationSucceed=TRUE; |
| 514 | } |
| 515 | if(!(ntohs(pIpHeader->frag_off) & IP_MF)) |
| 516 | { |
| 517 | //Fragmented Last packet . Remove Frag Classifier Entry |
| 518 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"This is the last fragmented Pkt"); |
| 519 | DelFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); |
| 520 | } |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) |
| 525 | { |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 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); |
Dan Carpenter | 370adc7 | 2010-10-08 15:49:04 +0200 | [diff] [blame] | 548 | if (uiSfIndex >= NO_OF_QUEUES) { |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 549 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Queue Not Valid. SearchSfid for this classifier Failed\n"); |
| 550 | break; |
| 551 | } |
| 552 | |
| 553 | if(Adapter->PackInfo[uiSfIndex].bEthCSSupport) |
| 554 | { |
| 555 | |
| 556 | if(eEthUnsupportedFrame==stEthCsPktInfo.eNwpktEthFrameType) |
| 557 | { |
| 558 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame \n"); |
| 559 | bClassificationSucceed = FALSE; |
| 560 | break; |
| 561 | } |
| 562 | |
| 563 | |
| 564 | |
| 565 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",pstClassifierRule->uiClassifierRuleIndex,Adapter->PackInfo[uiSfIndex].ulSFID); |
| 566 | bClassificationSucceed = EThCSClassifyPkt(Adapter,skb,&stEthCsPktInfo,pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport); |
| 567 | |
| 568 | if(!bClassificationSucceed) |
| 569 | { |
| 570 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Ethernet CS Classification Failed\n"); |
| 571 | break; |
| 572 | } |
| 573 | } |
| 574 | |
| 575 | else // No ETH Supported on this SF |
| 576 | { |
| 577 | if(eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) |
| 578 | { |
| 579 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF \n"); |
| 580 | bClassificationSucceed = FALSE; |
| 581 | break; |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Proceeding to IP CS Clasification"); |
| 586 | |
| 587 | if(Adapter->PackInfo[uiSfIndex].bIPCSSupport) |
| 588 | { |
| 589 | |
| 590 | if(stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) |
| 591 | { |
| 592 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet \n"); |
| 593 | bClassificationSucceed = FALSE; |
| 594 | break; |
| 595 | } |
| 596 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header : \n"); |
| 597 | DumpFullPacket((PUCHAR)pIpHeader,20); |
| 598 | |
| 599 | if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) |
| 600 | bClassificationSucceed = IpVersion4(Adapter,pIpHeader,pstClassifierRule); |
| 601 | else if(stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet) |
| 602 | bClassificationSucceed = IpVersion6(Adapter,pIpHeader,pstClassifierRule); |
| 603 | } |
| 604 | |
| 605 | }while(0); |
| 606 | } |
| 607 | |
| 608 | if(bClassificationSucceed == TRUE) |
| 609 | { |
| 610 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu",pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID); |
| 611 | |
| 612 | //Store The matched Classifier in SKB |
| 613 | *((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex; |
| 614 | if((TCP == pIpHeader->protocol ) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len) ) |
| 615 | { |
| 616 | IpHeaderLength = pIpHeader->ihl; |
| 617 | pTcpHeader = (PTCP_HEADER)(((PUCHAR)pIpHeader)+(IpHeaderLength*4)); |
| 618 | TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength); |
| 619 | |
| 620 | if((pTcpHeader->ucFlags & TCP_ACK) && |
| 621 | (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4))) |
| 622 | { |
| 623 | *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = TCP_ACK; |
| 624 | } |
| 625 | } |
| 626 | |
| 627 | usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); |
| 628 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex); |
| 629 | |
| 630 | //If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt. |
| 631 | if(bFragmentedPkt && (usCurrFragment == 0)) |
| 632 | { |
| 633 | //First Fragment of Fragmented Packet. Create Frag CLS Entry |
| 634 | S_FRAGMENTED_PACKET_INFO stFragPktInfo; |
| 635 | stFragPktInfo.bUsed = TRUE; |
| 636 | stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr; |
| 637 | stFragPktInfo.usIpIdentification = pIpHeader->id; |
| 638 | stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule; |
| 639 | stFragPktInfo.bOutOfOrderFragment = FALSE; |
| 640 | AddFragIPClsEntry(Adapter,&stFragPktInfo); |
| 641 | } |
| 642 | |
| 643 | |
| 644 | } |
| 645 | |
| 646 | if(bClassificationSucceed) |
| 647 | return usIndex; |
| 648 | else |
| 649 | return INVALID_QUEUE_INDEX; |
| 650 | } |
| 651 | |
Arnd Bergmann | 44a17ef | 2010-09-30 10:24:12 +0200 | [diff] [blame] | 652 | static BOOLEAN EthCSMatchSrcMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 653 | { |
| 654 | UINT i=0; |
| 655 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 656 | if(pstClassifierRule->ucEthCSSrcMACLen==0) |
| 657 | return TRUE; |
| 658 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); |
| 659 | for(i=0;i<MAC_ADDRESS_SIZE;i++) |
| 660 | { |
| 661 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",i,Mac[i],pstClassifierRule->au8EThCSSrcMAC[i],pstClassifierRule->au8EThCSSrcMACMask[i]); |
| 662 | if((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i])!= |
| 663 | (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i])) |
| 664 | return FALSE; |
| 665 | } |
| 666 | return TRUE; |
| 667 | } |
| 668 | |
Arnd Bergmann | 44a17ef | 2010-09-30 10:24:12 +0200 | [diff] [blame] | 669 | static BOOLEAN EthCSMatchDestMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 670 | { |
| 671 | UINT i=0; |
| 672 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 673 | if(pstClassifierRule->ucEthCSDestMACLen==0) |
| 674 | return TRUE; |
| 675 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); |
| 676 | for(i=0;i<MAC_ADDRESS_SIZE;i++) |
| 677 | { |
| 678 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",i,Mac[i],pstClassifierRule->au8EThCSDestMAC[i],pstClassifierRule->au8EThCSDestMACMask[i]); |
| 679 | if((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i])!= |
| 680 | (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i])) |
| 681 | return FALSE; |
| 682 | } |
| 683 | return TRUE; |
| 684 | } |
| 685 | |
Arnd Bergmann | 44a17ef | 2010-09-30 10:24:12 +0200 | [diff] [blame] | 686 | static BOOLEAN EthCSMatchEThTypeSAP(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 687 | { |
| 688 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 689 | if((pstClassifierRule->ucEtherTypeLen==0)|| |
| 690 | (pstClassifierRule->au8EthCSEtherType[0] == 0)) |
| 691 | return TRUE; |
| 692 | |
| 693 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n",__FUNCTION__,pstEthCsPktInfo->usEtherType,pstClassifierRule->au8EthCSEtherType[0]); |
| 694 | if(pstClassifierRule->au8EthCSEtherType[0] == 1) |
| 695 | { |
| 696 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n",__FUNCTION__,pstClassifierRule->au8EthCSEtherType[1],pstClassifierRule->au8EthCSEtherType[2]); |
| 697 | |
| 698 | if(memcmp(&pstEthCsPktInfo->usEtherType,&pstClassifierRule->au8EthCSEtherType[1],2)==0) |
| 699 | return TRUE; |
| 700 | else |
| 701 | return FALSE; |
| 702 | } |
| 703 | |
| 704 | if(pstClassifierRule->au8EthCSEtherType[0] == 2) |
| 705 | { |
| 706 | if(eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType) |
| 707 | return FALSE; |
| 708 | |
| 709 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n",__FUNCTION__,pstEthCsPktInfo->ucDSAP,pstClassifierRule->au8EthCSEtherType[2]); |
| 710 | if(pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2]) |
| 711 | return TRUE; |
| 712 | else |
| 713 | return FALSE; |
| 714 | |
| 715 | } |
| 716 | |
| 717 | return FALSE; |
| 718 | |
| 719 | } |
| 720 | |
Arnd Bergmann | 44a17ef | 2010-09-30 10:24:12 +0200 | [diff] [blame] | 721 | static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 722 | { |
| 723 | BOOLEAN bClassificationSucceed = FALSE; |
| 724 | USHORT usVLANID; |
| 725 | B_UINT8 uPriority = 0; |
| 726 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 727 | |
| 728 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID); |
| 729 | |
Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 730 | /* In case FW didn't receive the TLV, the priority field should be ignored */ |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 731 | if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) |
| 732 | { |
| 733 | if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame) |
| 734 | return FALSE; |
| 735 | |
| 736 | uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xF000) >> 13; |
| 737 | |
| 738 | if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1])) |
| 739 | bClassificationSucceed = TRUE; |
| 740 | |
| 741 | if(!bClassificationSucceed) |
| 742 | return FALSE; |
| 743 | } |
| 744 | |
| 745 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 D User Priority Rule Matched\n"); |
| 746 | |
| 747 | bClassificationSucceed = FALSE; |
| 748 | |
| 749 | if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID)) |
| 750 | { |
| 751 | if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame) |
| 752 | return FALSE; |
| 753 | |
| 754 | usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xFFF; |
| 755 | |
| 756 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority); |
| 757 | |
| 758 | if(usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4)) |
| 759 | bClassificationSucceed = TRUE; |
| 760 | |
| 761 | if(!bClassificationSucceed) |
| 762 | return FALSE; |
| 763 | } |
| 764 | |
| 765 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 Q VLAN ID Rule Matched\n"); |
| 766 | |
| 767 | return TRUE; |
| 768 | } |
| 769 | |
| 770 | |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 771 | static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, |
| 772 | PS_ETHCS_PKT_INFO pstEthCsPktInfo, |
| 773 | S_CLASSIFIER_RULE *pstClassifierRule, |
| 774 | B_UINT8 EthCSCupport) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 775 | { |
| 776 | BOOLEAN bClassificationSucceed = FALSE; |
| 777 | bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((ETH_HEADER_STRUC *)(skb->data))->au8SourceAddress); |
| 778 | if(!bClassificationSucceed) |
| 779 | return FALSE; |
| 780 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n"); |
| 781 | |
| 782 | bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((ETH_HEADER_STRUC*)(skb->data))->au8DestinationAddress); |
| 783 | if(!bClassificationSucceed) |
| 784 | return FALSE; |
| 785 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n"); |
| 786 | |
| 787 | //classify on ETHType/802.2SAP TLV |
| 788 | bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,skb,pstEthCsPktInfo); |
| 789 | if(!bClassificationSucceed) |
| 790 | return FALSE; |
| 791 | |
| 792 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS EthType/802.2SAP Matched\n"); |
| 793 | |
| 794 | //classify on 802.1VLAN Header Parameters |
| 795 | |
| 796 | bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,skb,pstEthCsPktInfo); |
| 797 | if(!bClassificationSucceed) |
| 798 | return FALSE; |
| 799 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 VLAN Rules Matched\n"); |
| 800 | |
| 801 | return bClassificationSucceed; |
| 802 | } |
| 803 | |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 804 | static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload, |
| 805 | PS_ETHCS_PKT_INFO pstEthCsPktInfo) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 806 | { |
| 807 | USHORT u16Etype = ntohs(((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype); |
Stephen Hemminger | 9dd47ee | 2010-11-01 12:24:00 -0400 | [diff] [blame] | 808 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 809 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype); |
| 810 | if(u16Etype > 0x5dc) |
| 811 | { |
| 812 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame \n"); |
| 813 | //ETH2 Frame |
| 814 | if(u16Etype == ETHERNET_FRAMETYPE_802QVLAN) |
| 815 | { |
| 816 | //802.1Q VLAN Header |
| 817 | pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame; |
| 818 | u16Etype = ((ETH_CS_802_Q_FRAME*)pvEthPayload)->EthType; |
| 819 | //((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority |
| 820 | } |
| 821 | else |
| 822 | { |
| 823 | pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame; |
| 824 | u16Etype = ntohs(u16Etype); |
| 825 | } |
| 826 | |
| 827 | } |
| 828 | else |
| 829 | { |
| 830 | //802.2 LLC |
| 831 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame \n"); |
| 832 | pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame; |
| 833 | pstEthCsPktInfo->ucDSAP = ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->DSAP; |
| 834 | if(pstEthCsPktInfo->ucDSAP == 0xAA && ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->SSAP == 0xAA) |
| 835 | { |
| 836 | //SNAP Frame |
| 837 | pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame; |
| 838 | u16Etype = ((ETH_CS_802_LLC_SNAP_FRAME*)pvEthPayload)->usEtherType; |
| 839 | } |
| 840 | } |
| 841 | if(u16Etype == ETHERNET_FRAMETYPE_IPV4) |
| 842 | pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet; |
| 843 | else if(u16Etype == ETHERNET_FRAMETYPE_IPV6) |
| 844 | pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet; |
| 845 | else |
| 846 | pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket; |
| 847 | |
| 848 | pstEthCsPktInfo->usEtherType = ((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype; |
| 849 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n",pstEthCsPktInfo->eNwpktIPFrameType); |
| 850 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n",pstEthCsPktInfo->eNwpktEthFrameType); |
| 851 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n",pstEthCsPktInfo->usEtherType); |
| 852 | } |
| 853 | |
| 854 | |
| 855 | |