| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| |
| /* |
| * Copyright 2014 QLogic Corporation |
| * The contents of this file are subject to the terms of the |
| * QLogic End User License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the License at |
| * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ |
| * QLogic_End_User_Software_License.txt |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| */ |
| |
| /* |
| * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. |
| */ |
| |
| #include "bnxe.h" |
| |
| int BnxeRouteTxRing(um_device_t * pUM, |
| mblk_t * pMblk) |
| { |
| u32_t numRings = pUM->devParams.numRings; |
| int ring = 0; |
| uint8_t * pHdr; |
| mblk_t * pTmpMblk; |
| size_t mblkLen; |
| ushort_t etype; |
| size_t eHdrSize; |
| |
| if (!numRings) |
| { |
| return 0; |
| } |
| |
| /* |
| * Need enough space to cover the ethernet header (+vlan), max ip header, |
| * and the first 4 bytes of the TCP/IP header (src/dst ports). |
| */ |
| size_t hdrs_size; |
| uint8_t hdrs_buf[sizeof(struct ether_vlan_header) + |
| IP_MAX_HDR_LENGTH + |
| sizeof(uint32_t)]; |
| |
| switch (pUM->devParams.routeTxRingPolicy) |
| { |
| case BNXE_ROUTE_RING_TCPUDP: |
| |
| pHdr = pMblk->b_rptr; |
| |
| etype = ntohs(((struct ether_header *)pHdr)->ether_type); |
| |
| if (etype == ETHERTYPE_VLAN) |
| { |
| etype = ntohs(((struct ether_vlan_header *)pHdr)->ether_type); |
| eHdrSize = sizeof(struct ether_vlan_header); |
| } |
| else |
| { |
| eHdrSize = sizeof(struct ether_header); |
| } |
| |
| if (etype == ETHERTYPE_IP) |
| { |
| mblkLen = MBLKL(pMblk); |
| pHdr = NULL; |
| |
| if (mblkLen > (eHdrSize + sizeof(uint8_t))) |
| { |
| pHdr = (pMblk->b_rptr + eHdrSize); |
| mblkLen -= eHdrSize; |
| |
| pHdr = (mblkLen > (((*pHdr & 0x0f) << 2) + sizeof(uint32_t))) ? |
| pMblk->b_rptr : NULL; |
| } |
| |
| if (pHdr == NULL) |
| { |
| /* copy the header so it's contiguous in the local hdrs_buf */ |
| pTmpMblk = pMblk; |
| hdrs_size = 0; |
| |
| while (pTmpMblk && (hdrs_size < sizeof(hdrs_buf))) |
| { |
| mblkLen = MBLKL(pTmpMblk); |
| |
| if (mblkLen >= (sizeof(hdrs_buf) - hdrs_size)) |
| { |
| mblkLen = (sizeof(hdrs_buf) - hdrs_size); |
| } |
| |
| bcopy(pTmpMblk->b_rptr, &hdrs_buf[hdrs_size], mblkLen); |
| |
| hdrs_size += mblkLen; |
| pTmpMblk = pTmpMblk->b_cont; |
| } |
| |
| pHdr = hdrs_buf; |
| } |
| |
| pHdr += eHdrSize; |
| |
| if (!(pHdr[6] & 0x3f) && !(pHdr[7] & 0xff)) |
| { |
| switch (pHdr[9]) |
| { |
| case IPPROTO_TCP: |
| case IPPROTO_UDP: |
| case IPPROTO_ESP: |
| |
| /* source and destination ports */ |
| pHdr += (((*pHdr) & 0x0f) << 2); |
| ring = ((u32_t)(pHdr[0] ^ pHdr[1] ^ pHdr[2] ^ pHdr[3]) % |
| numRings); |
| break; |
| |
| case IPPROTO_AH: |
| |
| /* security parameters index */ |
| pHdr += (((*pHdr) & 0x0f) << 2); |
| ring = ((pHdr[4] ^ pHdr[5] ^ pHdr[6] ^ pHdr[7]) % |
| numRings); |
| break; |
| |
| default: |
| |
| /* last byte of the destination IP address */ |
| ring = (pHdr[19] % numRings); |
| break; |
| } |
| } |
| else |
| { |
| /* fragmented packet */ |
| ring = (pHdr[19] % numRings); |
| } |
| } |
| else |
| { |
| ring = (pMblk->b_band % numRings); |
| } |
| |
| break; |
| |
| case BNXE_ROUTE_RING_DEST_MAC: |
| |
| /* last byte of dst mac addr */ |
| pHdr = pMblk->b_rptr; |
| ring = (pHdr[5] % numRings); |
| break; |
| |
| case BNXE_ROUTE_RING_MSG_PRIO: |
| |
| ring = (pMblk->b_band % numRings); |
| break; |
| |
| case BNXE_ROUTE_RING_NONE: |
| default: |
| |
| ring = 0; |
| break; |
| } |
| |
| return ring; |
| } |
| |