1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 QLogic Corporation 24 * The contents of this file are subject to the terms of the 25 * QLogic End User License (the "License"). 26 * You may not use this file except in compliance with the License. 27 * 28 * You can obtain a copy of the License at 29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 30 * QLogic_End_User_Software_License.txt 31 * See the License for the specific language governing permissions 32 * and limitations under the License. 33 */ 34 35 /* 36 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 #include "bnxe.h" 40 41 int BnxeRouteTxRing(um_device_t * pUM, 42 mblk_t * pMblk) 43 { 44 u32_t numRings = pUM->devParams.numRings; 45 int ring = 0; 46 uint8_t * pHdr; 47 mblk_t * pTmpMblk; 48 size_t mblkLen; 49 ushort_t etype; 50 size_t eHdrSize; 51 52 if (!numRings) 53 { 54 return 0; 55 } 56 57 /* 58 * Need enough space to cover the ethernet header (+vlan), max ip header, 59 * and the first 4 bytes of the TCP/IP header (src/dst ports). 60 */ 61 size_t hdrs_size; 62 uint8_t hdrs_buf[sizeof(struct ether_vlan_header) + 63 IP_MAX_HDR_LENGTH + 64 sizeof(uint32_t)]; 65 66 switch (pUM->devParams.routeTxRingPolicy) 67 { 68 case BNXE_ROUTE_RING_TCPUDP: 69 70 pHdr = pMblk->b_rptr; 71 72 etype = ntohs(((struct ether_header *)pHdr)->ether_type); 73 74 if (etype == ETHERTYPE_VLAN) 75 { 76 etype = ntohs(((struct ether_vlan_header *)pHdr)->ether_type); 77 eHdrSize = sizeof(struct ether_vlan_header); 78 } 79 else 80 { 81 eHdrSize = sizeof(struct ether_header); 82 } 83 84 if (etype == ETHERTYPE_IP) 85 { 86 mblkLen = MBLKL(pMblk); 87 pHdr = NULL; 88 89 if (mblkLen > (eHdrSize + sizeof(uint8_t))) 90 { 91 pHdr = (pMblk->b_rptr + eHdrSize); 92 mblkLen -= eHdrSize; 93 94 pHdr = (mblkLen > (((*pHdr & 0x0f) << 2) + sizeof(uint32_t))) ? 95 pMblk->b_rptr : NULL; 96 } 97 98 if (pHdr == NULL) 99 { 100 /* copy the header so it's contiguous in the local hdrs_buf */ 101 pTmpMblk = pMblk; 102 hdrs_size = 0; 103 104 while (pTmpMblk && (hdrs_size < sizeof(hdrs_buf))) 105 { 106 mblkLen = MBLKL(pTmpMblk); 107 108 if (mblkLen >= (sizeof(hdrs_buf) - hdrs_size)) 109 { 110 mblkLen = (sizeof(hdrs_buf) - hdrs_size); 111 } 112 113 bcopy(pTmpMblk->b_rptr, &hdrs_buf[hdrs_size], mblkLen); 114 115 hdrs_size += mblkLen; 116 pTmpMblk = pTmpMblk->b_cont; 117 } 118 119 pHdr = hdrs_buf; 120 } 121 122 pHdr += eHdrSize; 123 124 if (!(pHdr[6] & 0x3f) && !(pHdr[7] & 0xff)) 125 { 126 switch (pHdr[9]) 127 { 128 case IPPROTO_TCP: 129 case IPPROTO_UDP: 130 case IPPROTO_ESP: 131 132 /* source and destination ports */ 133 pHdr += (((*pHdr) & 0x0f) << 2); 134 ring = ((u32_t)(pHdr[0] ^ pHdr[1] ^ pHdr[2] ^ pHdr[3]) % 135 numRings); 136 break; 137 138 case IPPROTO_AH: 139 140 /* security parameters index */ 141 pHdr += (((*pHdr) & 0x0f) << 2); 142 ring = ((pHdr[4] ^ pHdr[5] ^ pHdr[6] ^ pHdr[7]) % 143 numRings); 144 break; 145 146 default: 147 148 /* last byte of the destination IP address */ 149 ring = (pHdr[19] % numRings); 150 break; 151 } 152 } 153 else 154 { 155 /* fragmented packet */ 156 ring = (pHdr[19] % numRings); 157 } 158 } 159 else 160 { 161 ring = (pMblk->b_band % numRings); 162 } 163 164 break; 165 166 case BNXE_ROUTE_RING_DEST_MAC: 167 168 /* last byte of dst mac addr */ 169 pHdr = pMblk->b_rptr; 170 ring = (pHdr[5] % numRings); 171 break; 172 173 case BNXE_ROUTE_RING_MSG_PRIO: 174 175 ring = (pMblk->b_band % numRings); 176 break; 177 178 case BNXE_ROUTE_RING_NONE: 179 default: 180 181 ring = 0; 182 break; 183 } 184 185 return ring; 186 } 187 188