win-pvdrivers

view xennet/xennet5_common.c @ 1001:c21dd04d3ae6

Less noise for xennet6
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 14 21:26:22 2012 +1100 (2012-12-14)
parents f476f07d3b0b
children
line source
1 /*
2 PV Net Driver for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
21 #include "xennet5.h"
23 /* Increase the header to a certain size */
24 BOOLEAN
25 XenNet_BuildHeader(packet_info_t *pi, PUCHAR header, ULONG new_header_size)
26 {
27 ULONG bytes_remaining;
29 //FUNCTION_ENTER();
31 if (!header)
32 header = pi->header;
34 if (new_header_size <= pi->header_length)
35 {
36 return TRUE; /* header is already at least the required size */
37 }
39 if (header == pi->first_buffer_virtual)
40 {
41 /* still working in the first buffer */
42 if (new_header_size <= pi->first_buffer_length)
43 {
44 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " new_header_size <= pi->first_buffer_length\n"));
45 pi->header_length = new_header_size;
46 if (pi->header_length == pi->first_buffer_length)
47 {
48 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
49 pi->curr_mdl_offset = 0;
50 if (pi->curr_pb)
51 pi->curr_pb = pi->curr_pb->next;
52 }
53 else
54 {
55 pi->curr_mdl_offset = (USHORT)new_header_size;
56 }
57 return TRUE;
58 }
59 else
60 {
61 //KdPrint((__DRIVER_NAME " Switching to header_data\n"));
62 memcpy(pi->header_data, header, pi->header_length);
63 header = pi->header = pi->header_data;
64 }
65 }
67 bytes_remaining = new_header_size - pi->header_length;
68 // TODO: if there are only a small number of bytes left in the current buffer then increase to consume that too... it would have to be no more than the size of header+mss though
70 //KdPrint((__DRIVER_NAME " A bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
71 while (bytes_remaining && pi->curr_buffer)
72 {
73 ULONG copy_size;
75 ASSERT(pi->curr_buffer);
76 //KdPrint((__DRIVER_NAME " B bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
77 if (MmGetMdlByteCount(pi->curr_buffer))
78 {
79 PUCHAR src_addr;
80 src_addr = MmGetSystemAddressForMdlSafe(pi->curr_buffer, NormalPagePriority);
81 if (!src_addr)
82 return FALSE;
83 copy_size = min(bytes_remaining, MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset);
84 //KdPrint((__DRIVER_NAME " B copy_size = %d\n", copy_size));
85 memcpy(header + pi->header_length,
86 src_addr + pi->curr_mdl_offset, copy_size);
87 pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + copy_size);
88 pi->header_length += copy_size;
89 bytes_remaining -= copy_size;
90 }
91 if (pi->curr_mdl_offset == MmGetMdlByteCount(pi->curr_buffer))
92 {
93 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
94 if (pi->curr_pb)
95 pi->curr_pb = pi->curr_pb->next;
96 pi->curr_mdl_offset = 0;
97 }
98 }
99 //KdPrint((__DRIVER_NAME " C bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
100 if (bytes_remaining)
101 {
102 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " bytes_remaining\n"));
103 return FALSE;
104 }
105 //FUNCTION_EXIT();
106 return TRUE;
107 }
109 ULONG
110 XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR alt_buffer, ULONG min_header_size)
111 {
112 //FUNCTION_ENTER();
114 ASSERT(pi->first_buffer);
116 NdisQueryBufferSafe(pi->first_buffer, (PVOID)&pi->first_buffer_virtual, &pi->first_buffer_length, NormalPagePriority);
117 pi->curr_buffer = pi->first_buffer;
118 if (alt_buffer)
119 pi->header = alt_buffer;
120 else
121 pi->header = pi->first_buffer_virtual;
123 pi->header_length = 0;
124 pi->curr_mdl_offset = 0;
126 XenNet_BuildHeader(pi, NULL, min_header_size);
128 if (!XenNet_BuildHeader(pi, NULL, (ULONG)XN_HDR_SIZE))
129 {
130 KdPrint((__DRIVER_NAME " packet too small (Ethernet Header)\n"));
131 return PARSE_TOO_SMALL;
132 }
134 switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
135 {
136 case 0x0800:
137 //KdPrint((__DRIVER_NAME " IP\n"));
138 if (pi->header_length < (ULONG)(XN_HDR_SIZE + 20))
139 {
140 if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + 20)))
141 {
142 KdPrint((__DRIVER_NAME " packet too small (IP Header)\n"));
143 return PARSE_TOO_SMALL;
144 }
145 }
146 pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
147 if (pi->ip_version != 4)
148 {
149 KdPrint((__DRIVER_NAME " ip_version = %d\n", pi->ip_version));
150 return PARSE_UNKNOWN_TYPE;
151 }
152 pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
153 pi->ip_has_options = (BOOLEAN)(pi->ip4_header_length > 20);
154 if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
155 {
156 if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)))
157 {
158 //KdPrint((__DRIVER_NAME " packet too small (IP Header + IP Options + TCP Header)\n"));
159 return PARSE_TOO_SMALL;
160 }
161 }
162 break;
163 default:
164 //KdPrint((__DRIVER_NAME " Not IP (%d)\n", GET_NET_PUSHORT(&pi->header[12])));
165 return PARSE_UNKNOWN_TYPE;
166 }
167 pi->ip_proto = pi->header[XN_HDR_SIZE + 9];
168 switch (pi->ip_proto)
169 {
170 case 6: // TCP
171 case 17: // UDP
172 break;
173 default:
174 //KdPrint((__DRIVER_NAME " Not TCP/UDP (%d)\n", pi->ip_proto));
175 return PARSE_UNKNOWN_TYPE;
176 }
177 pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
178 pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
180 if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length))
181 {
182 if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)))
183 {
184 //KdPrint((__DRIVER_NAME " packet too small (IP Header + IP Options + TCP Header + TCP Options)\n"));
185 return PARSE_TOO_SMALL;
186 }
187 }
189 if ((ULONG)XN_HDR_SIZE + pi->ip4_length > pi->total_length)
190 {
191 KdPrint((__DRIVER_NAME " XN_HDR_SIZE + ip4_length (%d) > total_length (%d)\n", XN_HDR_SIZE + pi->ip4_length, pi->total_length));
192 return PARSE_UNKNOWN_TYPE;
193 }
195 pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
196 pi->tcp_remaining = pi->tcp_length;
197 pi->tcp_seq = GET_NET_PULONG(&pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
198 pi->tcp_has_options = (BOOLEAN)(pi->tcp_header_length > 20);
199 if (pi->mss > 0 && pi->tcp_length > pi->mss)
200 pi->split_required = TRUE;
202 //KdPrint((__DRIVER_NAME " ip4_length = %d\n", pi->ip4_length));
203 //KdPrint((__DRIVER_NAME " tcp_length = %d\n", pi->tcp_length));
204 //FUNCTION_EXIT();
206 return PARSE_OK;
207 }
209 VOID
210 XenNet_SumIpHeader(
211 PUCHAR header,
212 USHORT ip4_header_length
213 )
214 {
215 ULONG csum = 0;
216 USHORT i;
218 ASSERT(ip4_header_length > 12);
219 ASSERT(!(ip4_header_length & 1));
221 header[XN_HDR_SIZE + 10] = 0;
222 header[XN_HDR_SIZE + 11] = 0;
223 for (i = 0; i < ip4_header_length; i += 2)
224 {
225 csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
226 }
227 while (csum & 0xFFFF0000)
228 csum = (csum & 0xFFFF) + (csum >> 16);
229 csum = ~csum;
230 SET_NET_USHORT(&header[XN_HDR_SIZE + 10], (USHORT)csum);
231 }
233 BOOLEAN
234 XenNet_CheckIpHeader(
235 PUCHAR header,
236 USHORT ip4_header_length
237 )
238 {
239 ULONG csum = 0;
240 USHORT i;
242 ASSERT(ip4_header_length > 12);
243 ASSERT(!(ip4_header_length & 1));
245 for (i = 0; i < ip4_header_length; i += 2)
246 {
247 csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
248 }
249 while (csum & 0xFFFF0000)
250 csum = (csum & 0xFFFF) + (csum >> 16);
251 return (BOOLEAN)(csum == 0xFFFF);
252 }
254 BOOLEAN
255 XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi)
256 {
257 BOOLEAN is_multicast = FALSE;
258 BOOLEAN is_my_multicast = FALSE;
259 BOOLEAN is_broadcast = FALSE;
260 BOOLEAN is_directed = FALSE;
261 ULONG i;
263 if (pi->header[0] == 0xFF && pi->header[1] == 0xFF
264 && pi->header[2] == 0xFF && pi->header[3] == 0xFF
265 && pi->header[4] == 0xFF && pi->header[5] == 0xFF)
266 {
267 is_broadcast = TRUE;
268 }
269 else if (pi->header[0] & 0x01)
270 {
271 is_multicast = TRUE;
272 for (i = 0; i < xi->multicast_list_size; i++)
273 {
274 if (memcmp(xi->multicast_list[i], pi->header, 6) == 0)
275 break;
276 }
277 if (i < xi->multicast_list_size)
278 {
279 is_my_multicast = TRUE;
280 }
281 }
282 if (memcmp(xi->curr_mac_addr, pi->header, ETH_ALEN) == 0)
283 {
284 is_directed = TRUE;
285 }
287 if (is_directed && (xi->packet_filter & NDIS_PACKET_TYPE_DIRECTED))
288 {
289 return TRUE;
290 }
291 if (is_my_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_MULTICAST))
292 {
293 return TRUE;
294 }
295 if (is_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST))
296 {
297 return TRUE;
298 }
299 if (is_broadcast && (xi->packet_filter & NDIS_PACKET_TYPE_BROADCAST))
300 {
301 return TRUE;
302 }
303 if (xi->packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS)
304 {
305 return TRUE;
306 }
307 return FALSE;
308 }