Merge commit '008b34be09d7b9c3e7a18d3ce9ef8b5c4f4ff8b8'
[unleashed.git] / kernel / drivers / net / sfxge / sfxge_tcp.c
blobd7c4bf90fb861dc912d812782250837225ed9474
1 /*
2 * Copyright (c) 2008-2016 Solarflare Communications Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/stream.h>
36 #include <sys/strsun.h>
37 #include <sys/strsubr.h>
38 #include <sys/pattr.h>
40 #include <sys/ethernet.h>
41 #include <inet/ip.h>
43 #include <netinet/in.h>
44 #include <netinet/ip.h>
45 #include <netinet/tcp.h>
46 #include <netinet/udp.h>
47 #include <netinet/sctp.h>
49 #include "sfxge.h"
51 #include "efx.h"
55 * Parse packet headers and return:
56 * etherhpp Ethernet MAC header
57 * iphpp IPv4 header (NULL for non-IPv4 packet)
58 * thpp TCP header (NULL for non-TCP packet)
59 * offp Offset to TCP payload
60 * sizep Size of TCP payload
61 * dportp TCP/UDP/SCTP dest. port (network order), otherwise zero
62 * sportp TCP/UDP/SCTP source port, (network order) otherwise zero
64 sfxge_packet_type_t
65 sfxge_pkthdr_parse(mblk_t *mp, struct ether_header **etherhpp,
66 struct ip **iphpp, struct tcphdr **thpp,
67 size_t *offp, size_t *sizep,
68 uint16_t *sportp, uint16_t *dportp)
70 struct ether_header *etherhp;
71 uint16_t ether_type;
72 size_t etherhs;
73 struct ip *iphp;
74 size_t iphs;
75 struct tcphdr *thp;
76 size_t len;
77 size_t ths;
78 size_t off;
79 size_t size;
80 uint16_t sport;
81 uint16_t dport;
82 sfxge_packet_type_t pkt_type = SFXGE_PACKET_TYPE_UNKNOWN;
84 etherhp = NULL;
85 iphp = NULL;
86 thp = NULL;
87 off = 0;
88 size = 0;
89 sport = 0;
90 dport = 0;
92 /* Grab the MAC header */
93 etherhs = sizeof (struct ether_header);
94 if ((MBLKL(mp) < etherhs) && (pullupmsg(mp, etherhs) == 0))
95 goto done;
97 /*LINTED*/
98 etherhp = (struct ether_header *)(mp->b_rptr);
99 ether_type = etherhp->ether_type;
101 if (ether_type == htons(ETHERTYPE_VLAN)) {
102 struct ether_vlan_header *ethervhp;
104 etherhs = sizeof (struct ether_vlan_header);
105 if ((MBLKL(mp) < etherhs) && (pullupmsg(mp, etherhs) == 0))
106 goto done;
108 /*LINTED*/
109 ethervhp = (struct ether_vlan_header *)(mp->b_rptr);
110 ether_type = ethervhp->ether_type;
113 if (ether_type != htons(ETHERTYPE_IP))
114 goto done;
116 /* Skip over the MAC header */
117 off += etherhs;
119 /* Grab the IP header */
120 len = off + sizeof (struct ip);
121 if ((MBLKL(mp) < len) && (pullupmsg(mp, len) == 0))
122 goto done;
124 /*LINTED*/
125 iphp = (struct ip *)(mp->b_rptr + off);
126 iphs = iphp->ip_hl * 4;
128 if (iphp->ip_v != IPV4_VERSION)
129 goto done;
131 /* Get the size of the packet */
132 size = ntohs(iphp->ip_len);
134 ASSERT3U(etherhs + size, <=, msgdsize(mp));
136 pkt_type = SFXGE_PACKET_TYPE_IPV4_OTHER;
138 /* Skip over the IP header */
139 off += iphs;
140 size -= iphs;
142 if (iphp->ip_p == IPPROTO_TCP) {
143 /* Grab the TCP header */
144 len = off + sizeof (struct tcphdr);
145 if ((MBLKL(mp) < len) && (pullupmsg(mp, len) == 0))
146 goto done;
148 /*LINTED*/
149 thp = (struct tcphdr *)(mp->b_rptr + off);
150 ths = thp->th_off * 4;
152 dport = thp->th_dport;
153 sport = thp->th_sport;
155 /* Skip over the TCP header */
156 off += ths;
157 size -= ths;
159 pkt_type = SFXGE_PACKET_TYPE_IPV4_TCP;
161 } else if (iphp->ip_p == IPPROTO_UDP) {
162 struct udphdr *uhp;
164 /* Grab the UDP header */
165 len = off + sizeof (struct udphdr);
166 if ((MBLKL(mp) < len) && (pullupmsg(mp, len) == 0))
167 goto done;
169 /*LINTED*/
170 uhp = (struct udphdr *)(mp->b_rptr + off);
171 dport = uhp->uh_dport;
172 sport = uhp->uh_sport;
174 /* Skip over the UDP header */
175 off += sizeof (struct udphdr);
176 size -= sizeof (struct udphdr);
178 pkt_type = SFXGE_PACKET_TYPE_IPV4_UDP;
180 } else if (iphp->ip_p == IPPROTO_SCTP) {
181 struct sctp_hdr *shp;
183 /* Grab the SCTP header */
184 len = off + sizeof (struct sctp_hdr);
185 if ((MBLKL(mp) < len) && (pullupmsg(mp, len) == 0))
186 goto done;
188 /*LINTED*/
189 shp = (struct sctp_hdr *)(mp->b_rptr + off);
190 dport = shp->sh_dport;
191 sport = shp->sh_sport;
193 /* Skip over the SCTP header */
194 off += sizeof (struct sctp_hdr);
195 size -= sizeof (struct sctp_hdr);
197 pkt_type = SFXGE_PACKET_TYPE_IPV4_SCTP;
200 if (MBLKL(mp) < off)
201 (void) pullupmsg(mp, off);
203 done:
204 *etherhpp = etherhp;
205 *iphpp = iphp;
206 *thpp = thp;
207 *offp = off;
208 *sizep = size;
209 *sportp = sport;
210 *dportp = dport;
212 return (pkt_type);