xref: /illumos-gate/usr/src/uts/common/io/bnxe/bnxe_rr.c (revision 8c69cc8fbe729fa7b091e901c4b50508ccc6bb33)
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