win-pvdrivers

view xennet/xennet5.h @ 995:0879eec3f528

Fix packet leak under 2003
author James Harper <james.harper@bendigoit.com.au>
date Mon Oct 22 21:21:16 2012 +1100 (2012-10-22)
parents 99023e044544
children
line source
1 /*
2 PV Drivers 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 #pragma warning(disable: 4201)
22 #pragma warning(disable: 4214)
24 #include <ntddk.h>
25 #include <wdm.h>
26 #define NDIS_MINIPORT_DRIVER
27 #if NTDDI_VERSION < NTDDI_WINXP
28 # define NDIS50_MINIPORT 1
29 #else
30 # define NDIS51_MINIPORT 1
31 #endif
32 #include <ndis.h>
33 #define NTSTRSAFE_LIB
34 #include <ntstrsafe.h>
35 #include <liblfds.h>
37 #define VENDOR_DRIVER_VERSION_MAJOR 0
38 #define VENDOR_DRIVER_VERSION_MINOR 10
40 #define VENDOR_DRIVER_VERSION (((VENDOR_DRIVER_VERSION_MAJOR) << 16) | (VENDOR_DRIVER_VERSION_MINOR))
42 #define __DRIVER_NAME "XenNet"
44 #include <xen_windows.h>
45 #include <memory.h>
46 #include <grant_table.h>
47 #include <event_channel.h>
48 #include <hvm/params.h>
49 #include <hvm/hvm_op.h>
50 #include <xen_public.h>
51 #include <io/ring.h>
52 #include <io/netif.h>
53 #include <io/xenbus.h>
54 #include <stdlib.h>
55 #define XENNET_POOL_TAG (ULONG) 'XenN'
57 /* Xen macros use these, so they need to be redefined to Win equivs */
58 #define wmb() KeMemoryBarrier()
59 #define mb() KeMemoryBarrier()
61 #define GRANT_INVALID_REF 0
63 #define NAME_SIZE 64
65 #define ETH_ALEN 6
67 /*
68 #define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
69 #define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
71 #define GET_NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
72 #define SET_NET_USHORT(y, x) *((USHORT *)&(y)) = ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
73 */
75 static FORCEINLINE USHORT
76 GET_NET_USHORT(USHORT data)
77 {
78 return (data << 8) | (data >> 8);
79 }
81 static FORCEINLINE USHORT
82 GET_NET_PUSHORT(PVOID pdata)
83 {
84 return (*((PUSHORT)pdata) << 8) | (*((PUSHORT)pdata) >> 8);
85 }
87 static FORCEINLINE VOID
88 SET_NET_USHORT(PVOID ptr, USHORT data)
89 {
90 *((PUSHORT)ptr) = GET_NET_USHORT(data);
91 }
93 static FORCEINLINE ULONG
94 GET_NET_ULONG(ULONG data)
95 {
96 ULONG tmp;
98 tmp = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
99 return (tmp << 16) | (tmp >> 16);
100 }
102 static FORCEINLINE ULONG
103 GET_NET_PULONG(PVOID pdata)
104 {
105 ULONG tmp;
107 tmp = ((*((PULONG)pdata) & 0x00ff00ff) << 8) | ((*((PULONG)pdata) & 0xff00ff00) >> 8);
108 return (tmp << 16) | (tmp >> 16);
109 }
111 static FORCEINLINE VOID
112 SET_NET_ULONG(PVOID ptr, ULONG data)
113 {
114 *((PULONG)ptr) = GET_NET_ULONG(data);
115 }
116 /*
117 #define GET_NET_ULONG(x) ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
118 #define SET_NET_ULONG(y, x) *((ULONG *)&(y)) = ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
119 */
121 #define SUPPORTED_PACKET_FILTERS (\
122 NDIS_PACKET_TYPE_DIRECTED | \
123 NDIS_PACKET_TYPE_MULTICAST | \
124 NDIS_PACKET_TYPE_BROADCAST | \
125 NDIS_PACKET_TYPE_PROMISCUOUS | \
126 NDIS_PACKET_TYPE_ALL_MULTICAST)
128 /* couldn't get regular xen ring macros to work...*/
129 #define __NET_RING_SIZE(type, _sz) \
130 (__RD32( \
131 (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
132 / sizeof(union type##_sring_entry)))
134 #define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
135 #define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
137 #pragma warning(disable: 4127) // conditional expression is constant
139 #define MIN_LARGE_SEND_SEGMENTS 4
141 /* TODO: crank this up if we support higher mtus? */
142 #define XN_HDR_SIZE 14
143 #define XN_MAX_DATA_SIZE 1500
144 #define XN_MIN_FRAME_SIZE 60
145 #define XN_MAX_FRAME_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
146 /*
147 #if !defined(OFFLOAD_LARGE_SEND)
148 #define XN_MAX_PKT_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
149 #else
150 #define XN_MAX_PKT_SIZE MAX_LARGE_SEND_OFFLOAD
151 #endif
152 */
154 #define XN_MAX_SEND_PKTS 16
156 #define XENSOURCE_MAC_HDR 0x00163E
157 #define XN_VENDOR_DESC "Xensource"
158 #define MAX_XENBUS_STR_LEN 128
160 #define RX_MIN_TARGET 8
161 #define RX_DFL_MIN_TARGET 256
162 #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
164 //#define MAX_BUFFERS_PER_PACKET NET_RX_RING_SIZE
166 #define MIN_ETH_HEADER_LENGTH 14
167 #define MAX_ETH_HEADER_LENGTH 14
168 #define MIN_IP4_HEADER_LENGTH 20
169 #define MAX_IP4_HEADER_LENGTH (15 * 4)
170 #define MIN_TCP_HEADER_LENGTH 20
171 #define MAX_TCP_HEADER_LENGTH (15 * 4)
172 #define MAX_PKT_HEADER_LENGTH (MAX_ETH_HEADER_LENGTH + MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
174 #define MIN_LOOKAHEAD_LENGTH (MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
175 #define MAX_LOOKAHEAD_LENGTH 256
177 #define LINUX_MAX_SG_ELEMENTS 19
179 struct _shared_buffer_t;
181 typedef struct _shared_buffer_t shared_buffer_t;
183 struct _shared_buffer_t
184 {
185 struct netif_rx_response rsp;
186 shared_buffer_t *next;
187 grant_ref_t gref;
188 USHORT offset;
189 PVOID virtual;
190 PNDIS_BUFFER buffer;
191 volatile LONG ref_count;
192 };
194 typedef struct
195 {
196 PNDIS_PACKET packet; /* only set on the last packet */
197 PVOID *cb;
198 grant_ref_t gref;
199 } tx_shadow_t;
201 typedef struct {
202 PNDIS_BUFFER first_buffer;
203 PNDIS_BUFFER curr_buffer;
204 shared_buffer_t *first_pb;
205 shared_buffer_t *curr_pb;
206 PUCHAR first_buffer_virtual;
207 ULONG mdl_count;
208 ULONG curr_mdl_offset;
209 USHORT mss;
210 NDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
211 BOOLEAN csum_blank;
212 BOOLEAN data_validated;
213 BOOLEAN split_required;
214 UCHAR ip_version;
215 PUCHAR header;
216 ULONG first_buffer_length;
217 ULONG header_length;
218 UCHAR ip_proto;
219 ULONG total_length;
220 USHORT ip4_header_length;
221 USHORT ip4_length;
222 BOOLEAN ip_has_options;
223 USHORT tcp_header_length;
224 BOOLEAN tcp_has_options;
225 USHORT tcp_length;
226 USHORT tcp_remaining;
227 ULONG tcp_seq;
228 /* anything past here doesn't get cleared automatically by the ClearPacketInfo */
229 UCHAR header_data[MAX_LOOKAHEAD_LENGTH + MAX_ETH_HEADER_LENGTH];
230 } packet_info_t;
232 #define PAGE_LIST_SIZE (max(NET_RX_RING_SIZE, NET_TX_RING_SIZE) * 4)
233 #define MULTICAST_LIST_MAX_SIZE 32
235 #define NDIS_STATUS_RESOURCES_MAX_LENGTH 64
237 struct xennet_info
238 {
239 BOOLEAN inactive;
241 /* Base device vars */
242 PDEVICE_OBJECT pdo;
243 PDEVICE_OBJECT fdo;
244 PDEVICE_OBJECT lower_do;
245 //WDFDEVICE wdf_device;
246 WCHAR dev_desc[NAME_SIZE];
248 /* NDIS-related vars */
249 NDIS_HANDLE adapter_handle;
250 NDIS_MINIPORT_INTERRUPT interrupt;
251 ULONG packet_filter;
252 BOOLEAN connected;
253 BOOLEAN shutting_down;
254 BOOLEAN tx_shutting_down;
255 BOOLEAN rx_shutting_down;
256 uint8_t perm_mac_addr[ETH_ALEN];
257 uint8_t curr_mac_addr[ETH_ALEN];
258 ULONG current_lookahead;
259 NDIS_DEVICE_POWER_STATE new_power_state;
260 NDIS_DEVICE_POWER_STATE power_state;
261 PIO_WORKITEM power_workitem;
263 /* Misc. Xen vars */
264 XENPCI_VECTORS vectors;
265 PXENPCI_DEVICE_STATE device_state;
266 evtchn_port_t event_channel;
267 ULONG state;
268 char backend_path[MAX_XENBUS_STR_LEN];
269 ULONG backend_state;
270 PVOID config_page;
271 UCHAR multicast_list[MULTICAST_LIST_MAX_SIZE][6];
272 ULONG multicast_list_size;
273 KDPC suspend_dpc;
274 PIO_WORKITEM resume_work_item;
275 KSPIN_LOCK resume_lock;
276 KDPC rxtx_dpc;
278 /* tx related - protected by tx_lock */
279 KSPIN_LOCK tx_lock;
280 LIST_ENTRY tx_waiting_pkt_list;
281 struct netif_tx_front_ring tx;
282 ULONG tx_ring_free;
283 tx_shadow_t tx_shadows[NET_TX_RING_SIZE];
284 NDIS_HANDLE tx_buffer_pool;
285 #define TX_HEADER_BUFFER_SIZE 512
286 //#define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE >> 2)
287 #define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE)
288 KEVENT tx_idle_event;
289 ULONG tx_outstanding;
290 ULONG tx_id_free;
291 USHORT tx_id_list[NET_TX_RING_SIZE];
292 NPAGED_LOOKASIDE_LIST tx_lookaside_list;
294 /* rx_related - protected by rx_lock */
295 KSPIN_LOCK rx_lock;
296 struct netif_rx_front_ring rx;
297 ULONG rx_id_free;
298 packet_info_t *rxpi;
299 KEVENT packet_returned_event;
300 //NDIS_MINIPORT_TIMER rx_timer;
301 KTIMER rx_timer;
302 KDPC rx_timer_dpc;
303 NDIS_HANDLE rx_packet_pool;
304 NDIS_HANDLE rx_buffer_pool;
305 volatile LONG rx_pb_free;
306 struct stack_state *rx_packet_stack;
307 struct stack_state *rx_pb_stack;
308 shared_buffer_t *rx_ring_pbs[NET_RX_RING_SIZE];
309 NPAGED_LOOKASIDE_LIST rx_lookaside_list;
310 /* Receive-ring batched refills. */
311 ULONG rx_target;
312 ULONG rx_max_target;
313 ULONG rx_min_target;
314 shared_buffer_t *rx_partial_buf;
315 BOOLEAN rx_partial_extra_info_flag ;
316 BOOLEAN rx_partial_more_data_flag;
318 /* how many packets are in the net stack atm */
319 LONG rx_outstanding;
321 /* config vars from registry */
322 ULONG config_sg;
323 ULONG config_csum;
324 ULONG config_csum_rx_check;
325 ULONG config_csum_rx_dont_fix;
326 ULONG config_gso;
327 ULONG config_mtu;
328 ULONG config_rx_interrupt_moderation;
330 NDIS_TASK_TCP_IP_CHECKSUM setting_csum;
331 ULONG setting_max_offload;
333 /* config stuff calculated from the above */
334 ULONG config_max_pkt_size;
336 /* stats */
337 ULONG64 stat_tx_ok;
338 ULONG64 stat_rx_ok;
339 ULONG64 stat_tx_error;
340 ULONG64 stat_rx_error;
341 ULONG64 stat_rx_no_buffer;
343 } typedef xennet_info_t;
345 VOID
346 XenNet_ReturnPacket(
347 IN NDIS_HANDLE MiniportAdapterContext,
348 IN PNDIS_PACKET Packet
349 );
351 BOOLEAN
352 XenNet_RxInit(xennet_info_t *xi);
354 BOOLEAN
355 XenNet_RxShutdown(xennet_info_t *xi);
357 VOID
358 XenNet_RxResumeStart(xennet_info_t *xi);
360 VOID
361 XenNet_RxResumeEnd(xennet_info_t *xi);
363 BOOLEAN
364 XenNet_RxBufferCheck(struct xennet_info *xi);
366 VOID
367 XenNet_TxResumeStart(xennet_info_t *xi);
369 VOID
370 XenNet_TxResumeEnd(xennet_info_t *xi);
372 VOID
373 XenNet_SendPackets(
374 IN NDIS_HANDLE MiniportAdapterContext,
375 IN PPNDIS_PACKET PacketArray,
376 IN UINT NumberOfPackets
377 );
379 VOID
380 XenNet_CancelSendPackets(
381 NDIS_HANDLE MiniportAdapterContext,
382 PVOID CancelId);
384 BOOLEAN
385 XenNet_TxInit(xennet_info_t *xi);
387 BOOLEAN
388 XenNet_TxShutdown(xennet_info_t *xi);
390 VOID
391 XenNet_TxBufferGC(struct xennet_info *xi, BOOLEAN dont_set_event);
393 NDIS_STATUS
394 XenNet_QueryInformation(
395 IN NDIS_HANDLE MiniportAdapterContext,
396 IN NDIS_OID Oid,
397 IN PVOID InformationBuffer,
398 IN ULONG InformationBufferLength,
399 OUT PULONG BytesWritten,
400 OUT PULONG BytesNeeded);
402 NDIS_STATUS
403 XenNet_SetInformation(
404 IN NDIS_HANDLE MiniportAdapterContext,
405 IN NDIS_OID Oid,
406 IN PVOID InformationBuffer,
407 IN ULONG InformationBufferLength,
408 OUT PULONG BytesRead,
409 OUT PULONG BytesNeeded
410 );
412 NDIS_STATUS
413 XenNet_D0Entry(struct xennet_info *xi);
414 NDIS_STATUS
415 XenNet_D0Exit(struct xennet_info *xi);
416 IO_WORKITEM_ROUTINE
417 XenNet_SetPower;
419 /* return values */
420 #define PARSE_OK 0
421 #define PARSE_TOO_SMALL 1 /* first buffer is too small */
422 #define PARSE_UNKNOWN_TYPE 2
424 BOOLEAN
425 XenNet_BuildHeader(packet_info_t *pi, PVOID header, ULONG new_header_size);
426 ULONG
427 XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR buffer, ULONG min_header_size);
428 BOOLEAN
429 XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi);
431 VOID
432 XenNet_SumIpHeader(
433 PUCHAR header,
434 USHORT ip4_header_length
435 );
437 BOOLEAN
438 XenNet_CheckIpHeader(
439 PUCHAR header,
440 USHORT ip4_header_length
441 );
443 static __forceinline VOID
444 XenNet_ClearPacketInfo(packet_info_t *pi)
445 {
446 #if 1
447 RtlZeroMemory(pi, sizeof(packet_info_t) - FIELD_OFFSET(packet_info_t, header_data));
448 #else
449 pi->mdl_count = 0;
450 pi->mss = 0;
451 pi->ip4_header_length = 0;
452 pi->tcp_header_length = 0;
453 pi->curr_mdl_index = pi->curr_mdl_offset = 0;
454 pi->extra_info = pi->more_frags = pi->csum_blank =
455 pi->data_validated = pi->split_required = 0;
456 #endif
457 }
459 /* Get some data from the current packet, but don't cross a page boundry. */
460 static __forceinline ULONG
461 XenNet_QueryData(packet_info_t *pi, ULONG length)
462 {
463 ULONG offset_in_page;
465 if (length > MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset)
466 length = MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset;
468 offset_in_page = (MmGetMdlByteOffset(pi->curr_buffer) + pi->curr_mdl_offset) & (PAGE_SIZE - 1);
469 if (offset_in_page + length > PAGE_SIZE)
470 length = PAGE_SIZE - offset_in_page;
472 return length;
473 }
475 /* Move the pointers forward by the given amount. No error checking is done. */
476 static __forceinline VOID
477 XenNet_EatData(packet_info_t *pi, ULONG length)
478 {
479 pi->curr_mdl_offset += length;
480 if (pi->curr_mdl_offset >= MmGetMdlByteCount(pi->curr_buffer))
481 {
482 pi->curr_mdl_offset -= MmGetMdlByteCount(pi->curr_buffer);
483 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
484 }
485 }