|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 2/4] Add VIF interface version 2
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
include/cache_interface.h | 232 +++++++++++++++++++++++
include/vif_interface.h | 454 ++++++++++++++++++++++++++++++++++++++++++++--
src/xennet/adapter.c | 73 +++++++-
src/xennet/adapter.h | 6 +
src/xennet/receiver.c | 22 ++-
src/xennet/transmitter.c | 354 +++++++++++++++++++++++++++++++-----
src/xennet/transmitter.h | 12 +-
7 files changed, 1072 insertions(+), 81 deletions(-)
create mode 100644 include/cache_interface.h
diff --git a/include/cache_interface.h b/include/cache_interface.h
new file mode 100644
index 0000000..12599ef
--- /dev/null
+++ b/include/cache_interface.h
@@ -0,0 +1,232 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file cache_interface.h
+ \brief XENBUS CACHE Interface
+
+ This interface provides access to XENBUS's object cache
+ implementation.
+*/
+
+#ifndef _XENBUS_CACHE_INTERFACE_H
+#define _XENBUS_CACHE_INTERFACE_H
+
+#ifndef _WINDLL
+
+/*! \typedef XENBUS_CACHE
+ \brief Cache handle
+*/
+typedef struct _XENBUS_CACHE XENBUS_CACHE, *PXENBUS_CACHE;
+
+/*! \typedef XENBUS_CACHE_ACQUIRE
+ \brief Acquire a reference to the CACHE interface
+
+ \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENBUS_CACHE_ACQUIRE)(
+ IN PINTERFACE Interface
+ );
+
+/*! \typedef XENBUS_CACHE_RELEASE
+ \brief Release a reference to the CACHE interface
+
+ \param Interface The interface header
+*/
+typedef VOID
+(*XENBUS_CACHE_RELEASE)(
+ IN PINTERFACE Interface
+ );
+
+/*! \typedef XENBUS_CACHE_CTOR
+ \brief Object creator callback
+
+ \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+ \param Object Newly allocated object
+
+ This callback is invoked just after a new object is allocated and may
+ be used to initialize any object data prior to its insertion into the
+ cache.
+*/
+typedef NTSTATUS
+(*XENBUS_CACHE_CTOR)(
+ IN PVOID Argument,
+ IN PVOID Object
+ );
+
+/*! \typedef XENBUS_CACHE_DTOR
+ \brief Object destructor callback
+
+ \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+ \param Object Object about to be freed
+
+ This callback is invoked just after an object is removed from the
+ cache and before it is freed and may be used to tear down any object data.
+*/
+typedef VOID
+(*XENBUS_CACHE_DTOR)(
+ IN PVOID Argument,
+ IN PVOID Object
+ );
+
+/*! \typedef XENBUS_CACHE_ACQUIRE_LOCK
+ \brief Cache lock callback
+
+ \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+ This callback is invoked if the cache implementation requires mutual
+ exclusion.
+*/
+typedef VOID
+(*XENBUS_CACHE_ACQUIRE_LOCK)(
+ IN PVOID Argument
+ );
+
+/*! \typedef XENBUS_CACHE_RELEASE_LOCK
+ \brief Cache unlock callback
+
+ \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+ This callback is invoked to release the mutual exclusion lock acquired
+ by a previous invocation of \a XENBUS_CACHE_ACQUIRE_LOCK.
+*/
+typedef VOID
+(*XENBUS_CACHE_RELEASE_LOCK)(
+ IN PVOID Argument
+ );
+
+/*! \typedef XENBUS_CACHE_CREATE
+ \brief Create a cache of objects of the given \a Size
+
+ \param Interface The interface header
+ \param Name A name for the cache which will be used in debug output
+ \param Size The size of each object in bytes
+ \param Reservation The target minimum population of the cache
+ \param Ctor A callback which is invoked when a new object created
+ \param Dtor A callback which is invoked when an object is destroyed
+ \param AcquireLock A callback invoked to acquire a spinlock
+ \param ReleaseLock A callback invoked to release the spinlock
+ \param Argument An optional context argument passed to the callbacks
+ \param Cache A pointer to a cache handle to be initialized
+
+ If a non-zero \a Reservation is specified then this method will fail
+ unless that number of objects can be immediately created.
+*/
+typedef NTSTATUS
+(*XENBUS_CACHE_CREATE)(
+ IN PINTERFACE Interface,
+ IN const CHAR *Name,
+ IN ULONG Size,
+ IN ULONG Reservation,
+ IN XENBUS_CACHE_CTOR Ctor,
+ IN XENBUS_CACHE_DTOR Dtor,
+ IN XENBUS_CACHE_ACQUIRE_LOCK AcquireLock,
+ IN XENBUS_CACHE_RELEASE_LOCK ReleaseLock,
+ IN PVOID Argument OPTIONAL,
+ OUT PXENBUS_CACHE *Cache
+ );
+
+/*! \typedef XENBUS_CACHE_GET
+ \brief Get an object from a \a Cache
+
+ \param Interface The interface header
+ \param Cache The cache handle
+ \param Locked If mutually exclusive access to the cache is already
+ guaranteed then set this to TRUE
+*/
+typedef PVOID
+(*XENBUS_CACHE_GET)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_CACHE Cache,
+ IN BOOLEAN Locked
+ );
+
+/*! \typedef XENBUS_CACHE_PUT
+ \brief Return an object to a \a Cache
+
+ \param Interface The interface header
+ \param Cache The cache handle
+ \param Locked If mutually exclusive access to the cache is already
+ guaranteed then set this to TRUE
+*/
+typedef VOID
+(*XENBUS_CACHE_PUT)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_CACHE Cache,
+ IN PVOID Object,
+ IN BOOLEAN Locked
+ );
+
+/*! \typedef XENBUS_CACHE_DESTROY
+ \brief Destroy a \a Cache
+
+ \param Interface The interface header
+ \param Cache The cache handle
+
+ All objects must have been returned to the cache prior to destruction
+*/
+typedef VOID
+(*XENBUS_CACHE_DESTROY)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_CACHE Cache
+ );
+
+// {A98DFD78-416A-4949-92A5-E084F2F4B44E}
+DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE,
+0xa98dfd78, 0x416a, 0x4949, 0x92, 0xa5, 0xe0, 0x84, 0xf2, 0xf4, 0xb4, 0x4e);
+
+/*! \struct _XENBUS_CACHE_INTERFACE_V1
+ \brief CACHE interface version 1
+*/
+struct _XENBUS_CACHE_INTERFACE_V1 {
+ INTERFACE Interface;
+ XENBUS_CACHE_ACQUIRE CacheAcquire;
+ XENBUS_CACHE_RELEASE CacheRelease;
+ XENBUS_CACHE_CREATE CacheCreate;
+ XENBUS_CACHE_GET CacheGet;
+ XENBUS_CACHE_PUT CachePut;
+ XENBUS_CACHE_DESTROY CacheDestroy;
+};
+
+typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE,
*PXENBUS_CACHE_INTERFACE;
+
+/*! \def XENBUS_CACHE
+ \brief Macro at assist in method invocation
+*/
+#define XENBUS_CACHE(_Method, _Interface, ...) \
+ (_Interface)->Cache ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+
+#endif // _WINDLL
+
+#define XENBUS_CACHE_INTERFACE_VERSION_MIN 1
+#define XENBUS_CACHE_INTERFACE_VERSION_MAX 1
+
+#endif // _XENBUS_CACHE_INTERFACE_H
diff --git a/include/vif_interface.h b/include/vif_interface.h
index 60a3e9c..4ce61c4 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -29,6 +29,12 @@
* SUCH DAMAGE.
*/
+/*! \file vif_interface.h
+ \brief XENVIF VIF Interface
+
+ This interface provides access to the PV network frontend
+*/
+
#ifndef _XENVIF_VIF_INTERFACE_H
#define _XENVIF_VIF_INTERFACE_H
@@ -37,21 +43,39 @@
#include <ifdef.h>
#include <ethernet.h>
+/*! \struct _XENVIF_PACKET_HEADER_V1
+ \brief Packet header information
+*/
struct _XENVIF_PACKET_HEADER_V1 {
+ /*! Offset from beginning of packet */
ULONG Offset;
+ /*! Length of header (0 indicates a header is not present) */
ULONG Length;
};
+/*! \struct _XENVIF_PACKET_INFO_V1
+ \brief Packet information
+*/
struct _XENVIF_PACKET_INFO_V1 {
+ /*! Total length of all headers */
ULONG Length;
+ /*! VLAN TCI if present (0 indicates not present) */
USHORT TagControlInformation;
+ /*! TRUE if the packet is an IP fragment */
BOOLEAN IsAFragment;
+ /*! Ethernet header (stripped of any VLAN tag) */
struct _XENVIF_PACKET_HEADER_V1 EthernetHeader;
+ /*! LLC header (used for IPX or 802.3 IP) */
struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader;
+ /*! IP header (v4 or v6) */
struct _XENVIF_PACKET_HEADER_V1 IpHeader;
+ /*! IP options (v4 or v6) */
struct _XENVIF_PACKET_HEADER_V1 IpOptions;
+ /*! TCP header */
struct _XENVIF_PACKET_HEADER_V1 TcpHeader;
+ /*! TCP options */
struct _XENVIF_PACKET_HEADER_V1 TcpOptions;
+ /*! UDP header */
struct _XENVIF_PACKET_HEADER_V1 UdpHeader;
};
@@ -61,38 +85,63 @@ typedef struct _XENVIF_PACKET_INFO_V1 XENVIF_PACKET_INFO,
*PXENVIF_PACKET_INFO
#pragma warning(disable:4214) // nonstandard extension used : bit field
types other than int
#pragma warning(disable:4201) // nonstandard extension used : nameless
struct/union
+/*! \struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
+ \brief Packet checksum flags
+*/
struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
union {
struct {
+ /*! IPv4 header checksum validation succeeded */
ULONG IpChecksumSucceeded:1;
+ /*! IPv4 header checksum validation failed */
ULONG IpChecksumFailed:1;
+ /*! IPv4 header checksum is present */
ULONG IpChecksumPresent:1;
+ /*! TCP checksum validation succeeded */
ULONG TcpChecksumSucceeded:1;
+ /*! TCP checksum validation failed */
ULONG TcpChecksumFailed:1;
+ /*! TCP checksum is present */
ULONG TcpChecksumPresent:1;
+ /*! UDP checksum validation succeeded */
ULONG UdpChecksumSucceeded:1;
+ /*! UDP checksum validation failed */
ULONG UdpChecksumFailed:1;
+ /*! UDP checksum is present */
ULONG UdpChecksumPresent:1;
ULONG Reserved:23;
};
-
+ /*! Raw representation */
ULONG Value;
};
};
+
typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS,
*PXENVIF_PACKET_CHECKSUM_FLAGS;
#pragma warning(pop)
+/*! \struct _XENVIF_RECEIVER_PACKET_V1
+ \brief Receive-side packet structure
+*/
struct _XENVIF_RECEIVER_PACKET_V1 {
+ /*! List entry used for chaining packets together */
LIST_ENTRY ListEntry;
+ /*! Pointer to packet information */
struct _XENVIF_PACKET_INFO_V1 *Info;
+ /*! Offset of start of packet in MDL */
ULONG Offset;
+ /*! Total length of packet */
ULONG Length;
+ /*! Checksum flags */
struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags;
+ /*! TCP MSS if the packet contains a TCP large segment */
USHORT MaximumSegmentSize;
+ /*! Opaque cookie used to store context information for packet return */
PVOID Cookie;
+ /*! MDL referencing the initial buffer of the packet */
MDL Mdl;
+ /*! PFN information, which must always follow an MDL */
PFN_NUMBER __Pfn;
};
@@ -102,22 +151,36 @@ typedef struct _XENVIF_RECEIVER_PACKET_V1
XENVIF_RECEIVER_PACKET, *PXENVIF_RECEI
#pragma warning(disable:4214) // nonstandard extension used : bit field
types other than int
#pragma warning(disable:4201) // nonstandard extension used : nameless
struct/union
+/*! \struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
+ \brief Offload options
+*/
struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 {
union {
struct {
+ /*! Insert/strip VLAN tags */
USHORT OffloadTagManipulation:1;
+ /*! Segment/coalesce IPv4 packets containing TCP large segments */
USHORT OffloadIpVersion4LargePacket:1;
+ /*! Calculate/validate IPv4 header checksum */
USHORT OffloadIpVersion4HeaderChecksum:1;
+ /*! Calculate/validate IPv4 TCP checksum */
USHORT OffloadIpVersion4TcpChecksum:1;
+ /*! Calculate/validate IPv4 UDP checksum */
USHORT OffloadIpVersion4UdpChecksum:1;
+ /*! Segment/coalesce IPv6 packets containing TCP large segments */
USHORT OffloadIpVersion6LargePacket:1;
+ /*! Calculate/validate IPv6 TCP checksum */
USHORT OffloadIpVersion6TcpChecksum:1;
+ /*! Calculate/validate IPv6 UDP checksum */
USHORT OffloadIpVersion6UdpChecksum:1;
+ /*! Force calculation of any missing checksums on receive side */
USHORT NeedChecksumValue:1;
+ /*! Force segmentation of packets containing TCP large segments on
receive side */
USHORT NeedLargePacketSplit:1;
USHORT Reserved:6;
};
+ /*! Raw representation */
USHORT Value;
};
};
@@ -126,28 +189,55 @@ typedef struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
XENVIF_VIF_OFFLOAD_OPTIONS, *PXENV
#pragma warning(pop)
-// To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures the
XENVIF_TRANSMITTER_PACKET
-// structure must be at most the size of 3 pointer types.
-
#pragma pack(push, 1)
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
+ \brief Packet information passed from subscriber to provider on
+ transmit side packet send
+
+ To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+ this structure must be at most the size of 3 pointer types.
+*/
struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 {
+ /*! Offload options for this packet */
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
- USHORT MaximumSegmentSize; // Only used if
OffloadOptions.OffloadIpVersion[4|6]LargePacket is set
- USHORT TagControlInformation; // Only used if
OffloadOptions.OffloadTagManipulation is set
+ /*! TCP MSS (used only if OffloadOptions.OffloadIpVersion[4|6]LargePacket
is set) */
+ USHORT MaximumSegmentSize;
+ /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set) */
+ USHORT TagControlInformation;
};
typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
XENVIF_TRANSMITTER_PACKET_SEND_INFO, *PXENVIF_TRANSMITTER_PACKET_SEND_INFO;
+/*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS
+ \brief Transmit-side packet status
+*/
+typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS {
+ /*! Packet was queued for the backend */
+ XENVIF_TRANSMITTER_PACKET_PENDING = 1,
+ /*! Packet has been successfully processed by the backend */
+ XENVIF_TRANSMITTER_PACKET_OK,
+ /*! Packet was dropped */
+ XENVIF_TRANSMITTER_PACKET_DROPPED,
+ /*! There was a problem handling the packet */
+ XENVIF_TRANSMITTER_PACKET_ERROR
+} XENVIF_TRANSMITTER_PACKET_STATUS, *PXENVIF_TRANSMITTER_PACKET_STATUS;
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
+ \brief Packet information passed from provider to subsriber on
+ transmit side packet return
+
+ To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+ this structure must be at most the size of 3 pointer types.
+*/
struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 {
+ /*! Ethernet address type (see \ref _ETHERNET_ADDRESS_TYPE) */
UCHAR Type;
+ /*! Send status (see \ref _XENVIF_TRANSMITTER_PACKET_STATUS) */
UCHAR Status;
-
-#define XENVIF_TRANSMITTER_PACKET_PENDING 1
-#define XENVIF_TRANSMITTER_PACKET_OK 2
-#define XENVIF_TRANSMITTER_PACKET_DROPPED 3
-#define XENVIF_TRANSMITTER_PACKET_ERROR 4
-
+ /*! Total length of the sent packet */
USHORT PacketLength;
+ /*! Length of packet payload after recognized headers are removed */
USHORT PayloadLength;
};
@@ -156,7 +246,11 @@ typedef struct
_XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 XENVIF_TRANSMITTER_
#pragma warning(push)
#pragma warning(disable:4201) // nonstandard extension used : nameless
struct/union
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V1
+ \brief Transmit-side packet structure
+*/
struct _XENVIF_TRANSMITTER_PACKET_V1 {
+ /*! Pointer used for chaining packets together */
struct _XENVIF_TRANSMITTER_PACKET_V1 *Next;
union {
struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 Send;
@@ -164,7 +258,7 @@ struct _XENVIF_TRANSMITTER_PACKET_V1 {
};
};
-typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET,
*PXENVIF_TRANSMITTER_PACKET;
+typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET_V1,
*PXENVIF_TRANSMITTER_PACKET_V1;
#pragma warning(pop)
@@ -172,64 +266,169 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1
XENVIF_TRANSMITTER_PACKET, *PXENVIF
C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof
(PVOID)));
+/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
+ \brief Transmit-side packet structure
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+ /*! List entry used for chaining packets together */
+ LIST_ENTRY ListEntry;
+ /*! MDL referencing the packet's buffer */
+ PMDL Mdl;
+ /*! Offset of start of packet in MDL */
+ ULONG Offset;
+ /*! Total length of packet */
+ ULONG Length;
+ /*! Opaque cookie used to store context information for packet return */
+ PVOID Cookie;
+ /*! Packet information passed down to subscriber */
+ XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
+ /*! Information passed up from subscriber for packet completion */
+ XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2,
*PXENVIF_TRANSMITTER_PACKET_V2;
+
+
+/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
+ \brief Offsets of packet metadata relative to
+ XENVIF_TRANSMITTER_PACKET_V1 pointer
+
+ Because the transmit side packet structure is limited to 3 pointer
+ types in size, not all information about the packet can be passed in
+ the structure. Other information can, however, be found by applying
+ these byte offsets to the structure pointer and then dereferencing the
+ specified type.
+*/
typedef enum _XENVIF_TRANSMITTER_PACKET_OFFSET {
+ /*! The offset of the start of the packet within the MDL (type ULONG) */
XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET = 0,
+ /*! The total length of the packet (type ULONG) */
XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
+ /*! MDL referencing the initial buffer of the packet (type PMDL) */
XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT
} XENVIF_TRANSMITTER_PACKET_OFFSET, *PXENVIF_TRANSMITTER_PACKET_OFFSET;
+/*! \enum _XENVIF_VIF_STATISTIC
+ \brief Interface statistics
+*/
typedef enum _XENVIF_VIF_STATISTIC {
+ /*! RFC 2863 ifOutDiscards */
XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
+ /*! Backend component of RFC 2863 ifOutErrors */
XENVIF_TRANSMITTER_BACKEND_ERRORS,
+ /*! Frontend component of RFC 2863 ifOutErrors */
XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+ /*! RFC 2863 ifOutUcastPkts */
XENVIF_TRANSMITTER_UNICAST_PACKETS,
+ /*! Total number of octets in ifOutUcastPkts */
XENVIF_TRANSMITTER_UNICAST_OCTETS,
+ /*! RFC 2863 ifOutMulticastPkts */
XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+ /*! Total number of octets in ifOutMulticastPkts */
XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+ /*! RFC 2863 ifOutBroadcastPkts */
XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+ /*! Total number of octets in ifOutBroadcastPkts */
XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+ /*! RFC 2863 ifInDiscards */
XENVIF_RECEIVER_PACKETS_DROPPED,
+ /*! Backend component of RFC 2863 ifInErrors */
XENVIF_RECEIVER_BACKEND_ERRORS,
+ /*! Frontend component of RFC 2863 ifInErrors */
XENVIF_RECEIVER_FRONTEND_ERRORS,
+ /*! RFC 2863 ifInUcastPkts */
XENVIF_RECEIVER_UNICAST_PACKETS,
+ /*! Total number of octets in ifInUcastPkts */
XENVIF_RECEIVER_UNICAST_OCTETS,
+ /*! RFC 2863 ifInMulticastPkts */
XENVIF_RECEIVER_MULTICAST_PACKETS,
+ /*! Total number of octets in ifInMulticastPkts */
XENVIF_RECEIVER_MULTICAST_OCTETS,
+ /*! RFC 2863 ifInBroadcastPkts */
XENVIF_RECEIVER_BROADCAST_PACKETS,
+ /*! Total number of octets in ifInBroadcastPkts */
XENVIF_RECEIVER_BROADCAST_OCTETS,
XENVIF_VIF_STATISTIC_COUNT
} XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
+/*! \enum _XENVIF_MAC_FILTER_LEVEL
+ \brief Filter level applied to packets
+*/
typedef enum _XENVIF_MAC_FILTER_LEVEL {
+ /*! Don't filter out any packets */
XENVIF_MAC_FILTER_NONE = 0,
+ /*! Filter out all packets except those with a matching destination
address */
XENVIF_MAC_FILTER_MATCHING = 1,
+ /*! Filter out all packets */
XENVIF_MAC_FILTER_ALL = 2
} XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
+/*! \enum _XENVIF_VIF_CALLBACK_TYPE
+ \brief Type of callback (see \ref XENVIF_VIF_CALLBACK)
+*/
typedef enum _XENVIF_VIF_CALLBACK_TYPE {
+ /*! Return transmit side packets to the subscriber */
XENVIF_TRANSMITTER_RETURN_PACKETS = 0,
+ /*! Queue receive side packets at the subscriber */
XENVIF_RECEIVER_QUEUE_PACKETS,
+ /*! Notify the subscriber of a MAC (link) state has change */
XENVIF_MAC_STATE_CHANGE
} XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE;
+/*! \typedef XENVIF_VIF_ACQUIRE
+ \brief Acquire a reference to the VIF interface
+
+ \param Interface The interface header
+*/
typedef NTSTATUS
(*XENVIF_VIF_ACQUIRE)(
IN PINTERFACE Interface
);
+/*! \typedef XENVIF_VIF_RELEASE
+ \brief Release a reference to the VIF interface
+
+ \param Interface The interface header
+*/
typedef VOID
(*XENVIF_VIF_RELEASE)(
IN PINTERFACE Interface
);
+/*! \typedef XENVIF_VIF_CALLBACK
+ \brief Provider to subscriber callback function
+
+ \param Argument An optional context argument passed to the callback
+ \param Type The callback type
+ \param ... Additional paramaters required by \a Type
+
+ \b XENVIF_TRANSMITTER_RETURN_PACKETS:
+ \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
+
+ \b XENVIF_RECEIVER_QUEUE_PACKETS:
+ \param List List of XENVIF_RECEIVER_PACKET
+
+ \b XENVIF_MAC_STATE_CHANGE:
+ No additional arguments
+*/
typedef VOID
(*XENVIF_VIF_CALLBACK)(
- IN PVOID Argument,
+ IN PVOID Argument OPTIONAL,
IN XENVIF_VIF_CALLBACK_TYPE Type,
...
);
+/*! \typedef XENVIF_VIF_ENABLE
+ \brief Enable the VIF interface
+
+ All packets queued for transmit will be rejected and no packets will
+ be queued for receive until this method completes.
+
+ \param Interface The interface header
+ \param Callback The subscriber's callback function
+ \param Argument An optional context argument passed to the callback
+*/
typedef NTSTATUS
(*XENVIF_VIF_ENABLE)(
IN PINTERFACE Interface,
@@ -237,11 +436,31 @@ typedef NTSTATUS
IN PVOID Argument OPTIONAL
);
+/*! \typedef XENVIF_VIF_DISABLE
+ \brief Disable the VIF interface
+
+ This method will not complete until any packets queued for receive
+ have been returned. Any packets queued for transmit may be aborted.
+
+ \param Interface The interface header
+*/
typedef VOID
(*XENVIF_VIF_DISABLE)(
IN PINTERFACE Interface
);
+/*! \typedef XENVIF_VIF_QUERY_STATISTIC
+ \brief Query the value of an interface statistic
+
+ Interface statistics are 64-bits wide and zero based. They are
+ zeroed when the vif device object is created. They are not
+ zeroed by this call or by any vif state change (e.g. reconnection
+ across migration).
+
+ \param Interface The interface header
+ \param Index The index of the statistic in \ref _XENVIF_VIF_STATISTIC
+ \param Value Buffer to receive the value of the statistic
+*/
typedef NTSTATUS
(*XENVIF_VIF_QUERY_STATISTIC)(
IN PINTERFACE Interface,
@@ -249,12 +468,29 @@ typedef NTSTATUS
OUT PULONGLONG Value
);
+/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS
+ \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK
+ (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS)
+
+ \param Interface The interface header
+ \param List List of \ref _XENVIF_RECEIVER_PACKET_V1
+*/
typedef VOID
(*XENVIF_VIF_RECEIVER_RETURN_PACKETS)(
IN PINTERFACE Interface,
IN PLIST_ENTRY List
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
+ \brief Set byte offset of packet information relative to
+ XENVIF_TRANSMITTER_PACKET_V1 pointer.
+
+ See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
+
+ \param Interface The interface header
+ \param Type The offset type
+ \param Value The offset value
+*/
typedef NTSTATUS
(*XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET)(
IN PINTERFACE Interface,
@@ -262,24 +498,80 @@ typedef NTSTATUS
IN LONG_PTR Value
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
+ \brief Queue transmit side packets at the provider
+
+ \param Interface The interface header
+ \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
+*/
typedef NTSTATUS
-(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)(
- IN PINTERFACE Interface,
- IN PXENVIF_TRANSMITTER_PACKET Head
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
+ IN PINTERFACE Interface,
+ IN PXENVIF_TRANSMITTER_PACKET_V1 Head
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
+ \brief Queue transmit side packets at the provider
+
+ \param Interface The interface header
+ \param List List of XENVIF_TRANSMITTER_PACKET_V2
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)(
+ IN PINTERFACE Interface,
+ IN PLIST_ENTRY List
+ );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+ \brief Get a copy of the packet headers and each the offset of each
+
+ \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+ IN PINTERFACE Interface,
+ IN PMDL Mdl,
+ IN ULONG Offset,
+ IN ULONG Length,
+ OUT PVOID HeaderBuffer,
+ IN ULONG HeaderLength,
+ OUT PXENVIF_PACKET_INFO Info
+ );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
+ \brief Query the available set of transmit side offload options
+
+ \param Interface The interface header
+ \param Options Buffer to receive the avilable options
+ (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
typedef VOID
(*XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS)(
IN PINTERFACE Interface,
OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
);
+/*! \typedef XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
+ \brief Set the required set of receive side offload options
+
+ \param Interface The interface header
+ \param Options The required options
+ (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
typedef VOID
(*XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS)(
IN PINTERFACE Interface,
IN XENVIF_VIF_OFFLOAD_OPTIONS Options
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
+ \brief Query the maximum size of packet containing a TCP large segment
+ that can be handled by the transmit side
+
+ \param Interface The interface header
+ \param Version The IP version (4 or 6)
+ \param Size Buffer to receive the maximum packet size
+*/
typedef VOID
(*XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE)(
IN PINTERFACE Interface,
@@ -287,18 +579,40 @@ typedef VOID
OUT PULONG Size
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
+ \brief Query the maximum number of transmit side packets that can
+ be queued in the shared ring between frontend and backend
+
+ \param Interface The interface header
+ \param Size Buffer to receive the maximum number of packets
+*/
typedef VOID
(*XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE)(
IN PINTERFACE Interface,
OUT PULONG Size
);
+/*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE
+ \brief Query the maximum number of receive side packets that can
+ be queued in the shared ring between backend and frontend
+
+ \param Interface The interface header
+ \param Size Buffer to receive the maximum number of packets
+*/
typedef VOID
(*XENVIF_VIF_RECEIVER_QUERY_RING_SIZE)(
IN PINTERFACE Interface,
OUT PULONG Size
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
+ \brief Query the current MAC (link) state
+
+ \param Interface The interface header
+ \param MediaConnectState Buffer to receive the current connection state
+ \param LinkSpeed Buffer to receive the current link speed in Gbps
+ \param MediaDuplexState Buffer to receive the current duplex state
+*/
typedef VOID
(*XENVIF_VIF_MAC_QUERY_STATE)(
IN PINTERFACE Interface,
@@ -307,24 +621,58 @@ typedef VOID
OUT PNET_IF_MEDIA_DUPLEX_STATE MediaDuplexState OPTIONAL
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE
+ \brief Query the maximum MAC (i.e. on the wire) frame size (not
+ including CRC)
+
+ \param Interface The interface header
+ \param Size Buffer to receive the maximum frame size
+*/
typedef VOID
(*XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE)(
IN PINTERFACE Interface,
OUT PULONG Size
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS
+ \brief Query the permanent MAC address (set by the toolstack)
+
+ \param Interface The interface header
+ \param Address Buffer to receive the permanent address
+*/
typedef VOID
(*XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS)(
IN PINTERFACE Interface,
OUT PETHERNET_ADDRESS Address
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS
+ \brief Query the current MAC address (may be set by the guest)
+
+ The guest OS may override the MAC address using the registry. If this
+ is not done then the current address will be identical to the
+ permanent address.
+
+ \param Interface The interface header
+ \param Address Buffer to receive the current address
+*/
typedef VOID
(*XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS)(
IN PINTERFACE Interface,
OUT PETHERNET_ADDRESS Address
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES
+ \brief Query the current set of active multicast addresses
+
+ \param Interface The interface header
+ \param Address An optional buffer to receive the set of addresses
+ \param Count A buffer to receive the number of active addresses
+
+ Call this method with \a Address set to NULL to get the \a Count,
+ which can then be used to allocate a buffer of suitable size to receive
+ the array of addresses.
+*/
typedef NTSTATUS
(*XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES)(
IN PINTERFACE Interface,
@@ -332,6 +680,16 @@ typedef NTSTATUS
IN OUT PULONG Count
);
+/*! \typedef XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
+ \brief Update the set of active multicast addresses
+
+ \param Interface The interface header
+ \param Address An optional buffer containing the set of addresses
+ \param Count The number of addresses in the buffer
+
+ The \a Address buffer may only by NULL if \a Count is zero, in which
+ case the set of active multicast addresses will be cleared.
+*/
typedef NTSTATUS
(*XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES)(
IN PINTERFACE Interface,
@@ -339,6 +697,14 @@ typedef NTSTATUS
IN ULONG Count
);
+/*! \typedef XENVIF_VIF_MAC_SET_FILTER_LEVEL
+ \brief Set a filter level for a given type of packet
+
+ \param Interface The interface header
+ \param Type The destination address type of the packet
+ (see \ref _ETHERNET_ADDRESS_TYPE)
+ \param Level The new filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
+*/
typedef NTSTATUS
(*XENVIF_VIF_MAC_SET_FILTER_LEVEL)(
IN PINTERFACE Interface,
@@ -346,6 +712,14 @@ typedef NTSTATUS
IN XENVIF_MAC_FILTER_LEVEL Level
);
+/*! \typedef XENVIF_VIF_MAC_QUERY_FILTER_LEVEL
+ \brief Query the current filter level for a given type of packet
+
+ \param Interface The interface header
+ \param Type The destination address type of the packet
+ (see \ref _ETHERNET_ADDRESS_TYPE)
+ \param Level Buffer to receive the filter level (see \ref
_XENVIF_MAC_FILTER_LEVEL)
+*/
typedef NTSTATUS
(*XENVIF_VIF_MAC_QUERY_FILTER_LEVEL)(
IN PINTERFACE Interface,
@@ -368,7 +742,34 @@ struct _XENVIF_VIF_INTERFACE_V1 {
XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET TransmitterSetPacketOffset;
- XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS TransmitterQueuePackets;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1 TransmitterQueuePackets;
+ XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
TransmitterQueryOffloadOptions;
+ XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
TransmitterQueryLargePacketSize;
+ XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
+ XENVIF_VIF_MAC_QUERY_STATE MacQueryState;
+ XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE MacQueryMaximumFrameSize;
+ XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS MacQueryPermanentAddress;
+ XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS MacQueryCurrentAddress;
+ XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES MacQueryMulticastAddresses;
+ XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES MacSetMulticastAddresses;
+ XENVIF_VIF_MAC_SET_FILTER_LEVEL MacSetFilterLevel;
+ XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE_V1,
*PXENVIF_VIF_INTERFACE_V1;
+
+struct _XENVIF_VIF_INTERFACE_V2 {
+ INTERFACE Interface;
+ XENVIF_VIF_ACQUIRE Acquire;
+ XENVIF_VIF_RELEASE Release;
+ XENVIF_VIF_ENABLE Enable;
+ XENVIF_VIF_DISABLE Disable;
+ XENVIF_VIF_QUERY_STATISTIC QueryStatistic;
+ XENVIF_VIF_RECEIVER_RETURN_PACKETS ReceiverReturnPackets;
+ XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
+ XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
+ XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
TransmitterSetPacketOffset; // obsolete
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1 TransmitterQueuePackets;
// obsolete
XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
TransmitterQueryOffloadOptions;
XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
TransmitterQueryLargePacketSize;
XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
@@ -380,16 +781,29 @@ struct _XENVIF_VIF_INTERFACE_V1 {
XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES MacSetMulticastAddresses;
XENVIF_VIF_MAC_SET_FILTER_LEVEL MacSetFilterLevel;
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2 TransmitterQueuePacketsV2;
+ XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
TransmitterGetPacketHeaders;
};
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE,
*PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2,
*PXENVIF_VIF_INTERFACE_V2;
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE,
*PXENVIF_VIF_INTERFACE;
+
+/*! \def XENVIF_VIF
+ \brief Macro to assist in method invocation
+*/
#define XENVIF_VIF(_Method, _Interface, ...) \
(_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+/*! \def XENVIF_VIF_VERSION
+ \brief Macro to assist in getting interface version in use
+*/
+#define XENVIF_VIF_VERSION(_Interface) \
+ ((_Interface)->Interface.Version)
+
#endif // _WINDLL
#define XENVIF_VIF_INTERFACE_VERSION_MIN 1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX 1
+#define XENVIF_VIF_INTERFACE_VERSION_MAX 2
#endif // _XENVIF_INTERFACE_H
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index 6b32d1a..e3d6e05 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -41,6 +41,7 @@
struct _XENNET_ADAPTER {
XENVIF_VIF_INTERFACE VifInterface;
+ XENBUS_CACHE_INTERFACE CacheInterface;
BOOLEAN Enabled;
ULONG MaximumFrameSize;
@@ -171,14 +172,30 @@ AdapterVifCallback(
va_start(Arguments, Type);
switch (Type) {
- case XENVIF_TRANSMITTER_RETURN_PACKETS: {
- PXENVIF_TRANSMITTER_PACKET HeadPacket;
+ case XENVIF_TRANSMITTER_RETURN_PACKETS:
+ switch (XENVIF_VIF_VERSION(&Adapter->VifInterface)) {
+ case 1: {
+ PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
+
+ HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET_V1);
+
+ TransmitterCompletePacketsV1(Adapter->Transmitter, HeadPacket);
+ break;
+ }
+ case 2: {
+ PLIST_ENTRY List;
- HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+ List = va_arg(Arguments, PLIST_ENTRY);
- TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+ TransmitterCompletePacketsV2(Adapter->Transmitter, List);
+ break;
+ }
+ default:
+ ASSERT(FALSE);
+ break;
+ }
break;
- }
+
case XENVIF_RECEIVER_QUEUE_PACKETS: {
PLIST_ENTRY List;
@@ -1986,6 +2003,14 @@ AdapterGetVifInterface(
return &Adapter->VifInterface;
}
+PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+ IN PXENNET_ADAPTER Adapter
+ )
+{
+ return &Adapter->CacheInterface;
+}
+
NDIS_HANDLE
AdapterGetHandle(
IN PXENNET_ADAPTER Adapter
@@ -2026,14 +2051,39 @@ AdapterInitialize(
VIF,
XENVIF_VIF_INTERFACE_VERSION_MAX,
(PINTERFACE)&(*Adapter)->VifInterface,
- sizeof ((*Adapter)->VifInterface),
+ sizeof (XENVIF_VIF_INTERFACE_V2),
+ FALSE);
+ if (!NT_SUCCESS(status)) {
+ Trace("QUERY_INTERFACE (VIF v2) failed (%08x)\n", status);
+ status = QUERY_INTERFACE(DeviceObject,
+ XENVIF,
+ VIF,
+ XENVIF_VIF_INTERFACE_VERSION_MIN,
+ (PINTERFACE)&(*Adapter)->VifInterface,
+ sizeof (XENVIF_VIF_INTERFACE_V1),
+ FALSE);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+ }
+ Trace("VIF interface version %u\n",
(*Adapter)->VifInterface.Interface.Version);
+
+ status = QUERY_INTERFACE(DeviceObject,
+ XENBUS,
+ CACHE,
+ XENBUS_CACHE_INTERFACE_VERSION_MAX,
+ (PINTERFACE)&(*Adapter)->CacheInterface,
+ sizeof (XENBUS_CACHE_INTERFACE),
FALSE);
if (!NT_SUCCESS(status))
- goto fail2;
+ goto fail2a;
status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
if (!NT_SUCCESS(status))
goto fail3;
+
+ status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface);
+ if (!NT_SUCCESS(status))
+ goto fail3a;
status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
if (!NT_SUCCESS(status))
@@ -2103,9 +2153,15 @@ fail5:
(*Adapter)->Transmitter = NULL;
fail4:
Error("fail4\n");
+ XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
+fail3a:
+ Error("fail3a\n");
XENVIF_VIF(Release, &(*Adapter)->VifInterface);
fail3:
Error("fail3\n");
+ RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+fail2a:
+ Error("fail2a\n");
RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
fail2:
Error("fail2\n");
@@ -2130,6 +2186,9 @@ AdapterTeardown(
TransmitterTeardown(Adapter->Transmitter);
Adapter->Transmitter = NULL;
+ XENBUS_CACHE(Release, &Adapter->CacheInterface);
+ RtlZeroMemory(&Adapter->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+
XENVIF_VIF(Release, &Adapter->VifInterface);
RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index a1f4b85..02eb6fd 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -96,6 +96,12 @@ AdapterGetVifInterface(
IN PXENNET_ADAPTER Adapter
);
+#include <cache_interface.h>
+extern PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+ IN PXENNET_ADAPTER Adapter
+ );
+
extern NDIS_HANDLE
AdapterGetHandle(
IN PXENNET_ADAPTER Adapter
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index ee01a18..e09db55 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -38,6 +38,7 @@
struct _XENNET_RECEIVER {
PXENNET_ADAPTER Adapter;
+ PXENVIF_VIF_INTERFACE VifInterface;
NDIS_HANDLE NetBufferListPool;
PNET_BUFFER_LIST PutList;
PNET_BUFFER_LIST GetList[MAXIMUM_PROCESSORS];
@@ -185,12 +186,9 @@ __ReceiverReturnNetBufferLists(
IN BOOLEAN Cache
)
{
- PXENNET_ADAPTER Adapter;
LIST_ENTRY List;
ULONG Count;
- Adapter = Receiver->Adapter;
-
InitializeListHead(&List);
Count = 0;
@@ -220,7 +218,7 @@ __ReceiverReturnNetBufferLists(
if (Count != 0) {
XENVIF_VIF(ReceiverReturnPackets,
- AdapterGetVifInterface(Adapter),
+ Receiver->VifInterface,
&List);
}
return Count;
@@ -292,13 +290,11 @@ ReceiverReceivePackets(
IN PLIST_ENTRY List
)
{
- PXENNET_ADAPTER Adapter;
PNET_BUFFER_LIST HeadNetBufferList;
PNET_BUFFER_LIST *TailNetBufferList;
ULONG Count;
BOOLEAN LowResources;
- Adapter = Receiver->Adapter;
LowResources = FALSE;
again:
@@ -354,7 +350,7 @@ again:
InsertTailList(&PacketList, &Packet->ListEntry);
XENVIF_VIF(ReceiverReturnPackets,
- AdapterGetVifInterface(Adapter),
+ Receiver->VifInterface,
&PacketList);
}
}
@@ -411,8 +407,17 @@ ReceiverInitialize(
if ((*Receiver)->NetBufferListPool == NULL)
goto fail2;
+ (*Receiver)->VifInterface = AdapterGetVifInterface(Adapter);
+ status = XENVIF_VIF(Acquire, (*Receiver)->VifInterface);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
return STATUS_SUCCESS;
+fail3:
+ Error("fail3\n");
+ NdisFreeNetBufferListPool((*Receiver)->NetBufferListPool);
+ (*Receiver)->NetBufferListPool = NULL;
fail2:
Error("fail2\n");
ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
@@ -460,6 +465,9 @@ ReceiverTeardown(
NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
Receiver->NetBufferListPool = NULL;
+ XENVIF_VIF(Release, Receiver->VifInterface);
+ Receiver->VifInterface = NULL;
+
ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
}
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index be07458..9bf730c 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -37,11 +37,84 @@
struct _XENNET_TRANSMITTER {
PXENNET_ADAPTER Adapter;
+ PXENVIF_VIF_INTERFACE VifInterface;
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
+
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+ PXENBUS_CACHE Cache;
};
#define TRANSMITTER_POOL_TAG 'teNX'
+static NTSTATUS
+__PacketCtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
+ return STATUS_SUCCESS;
+}
+
+static VOID
+__PacketDtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__PacketAcquire(
+ IN PVOID Argument
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+}
+
+static VOID
+__PacketRelease(
+ IN PVOID Argument
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
+__TransmitterGetPacket(
+ IN PXENNET_TRANSMITTER Transmitter
+ )
+{
+ ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+ ASSERT(Transmitter->CacheInterface != NULL);
+ ASSERT(Transmitter->Cache != NULL);
+
+ return XENBUS_CACHE(Get,
+ Transmitter->CacheInterface,
+ Transmitter->Cache,
+ FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET_V2 Packet
+ )
+{
+ ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+ ASSERT(Transmitter->CacheInterface != NULL);
+ ASSERT(Transmitter->Cache != NULL);
+
+ XENBUS_CACHE(Put,
+ Transmitter->CacheInterface,
+ Transmitter->Cache,
+ Packet,
+ FALSE);
+}
+
typedef struct _NET_BUFFER_LIST_RESERVED {
LONG Reference;
} NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -49,8 +122,8 @@ typedef struct _NET_BUFFER_LIST_RESERVED {
C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST,
MiniportReserved));
typedef struct _NET_BUFFER_RESERVED {
- XENVIF_TRANSMITTER_PACKET Packet;
- PNET_BUFFER_LIST NetBufferList;
+ XENVIF_TRANSMITTER_PACKET_V1 Packet;
+ PNET_BUFFER_LIST NetBufferList;
} NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER,
MiniportReserved));
@@ -83,17 +156,17 @@ TransmitterCompleteNetBufferList(
}
static VOID
-__TransmitterCompletePackets(
- IN PXENNET_TRANSMITTER Transmitter,
- IN PXENVIF_TRANSMITTER_PACKET Packet,
- IN NDIS_STATUS NdisStatus
+__TransmitterCompletePacketsV1(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET_V1 Packet,
+ IN NDIS_STATUS NdisStatus
)
{
while (Packet != NULL) {
- PXENVIF_TRANSMITTER_PACKET Next;
- PNET_BUFFER_RESERVED Reserved;
- PNET_BUFFER_LIST NetBufferList;
- PNET_BUFFER_LIST_RESERVED ListReserved;
+ PXENVIF_TRANSMITTER_PACKET_V1 Next;
+ PNET_BUFFER_RESERVED Reserved;
+ PNET_BUFFER_LIST NetBufferList;
+ PNET_BUFFER_LIST_RESERVED ListReserved;
Next = Packet->Next;
Packet->Next = NULL;
@@ -112,7 +185,38 @@ __TransmitterCompletePackets(
Packet = Next;
}
}
-
+
+static VOID
+__TransmitterCompletePacketsV2(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PLIST_ENTRY List,
+ IN NDIS_STATUS NdisStatus
+ )
+{
+ while (!IsListEmpty(List)) {
+ PLIST_ENTRY ListEntry;
+ PXENVIF_TRANSMITTER_PACKET_V2 Packet;
+ PNET_BUFFER_LIST NetBufferList;
+ PNET_BUFFER_LIST_RESERVED ListReserved;
+
+ ListEntry = RemoveHeadList(List);
+ ASSERT3P(ListEntry, !=, List);
+
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2,
ListEntry);
+
+ NetBufferList = Packet->Cookie;
+ ASSERT(NetBufferList != NULL);
+
+ ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+
+ ASSERT(ListReserved->Reference != 0);
+ if (InterlockedDecrement(&ListReserved->Reference) == 0)
+ TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
NdisStatus);
+
+ __TransmitterPutPacket(Transmitter, Packet);
+ }
+}
+
static FORCEINLINE VOID
__OffloadOptions(
IN PNET_BUFFER_LIST NetBufferList,
@@ -177,31 +281,18 @@ __OffloadOptions(
}
}
-VOID
-TransmitterSendNetBufferLists(
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV1(
IN PXENNET_TRANSMITTER Transmitter,
- IN PNET_BUFFER_LIST NetBufferList,
- IN NDIS_PORT_NUMBER PortNumber,
- IN ULONG SendFlags
+ IN PNET_BUFFER_LIST NetBufferList
)
{
- PXENNET_ADAPTER Adapter = Transmitter->Adapter;
- PXENVIF_TRANSMITTER_PACKET HeadPacket;
- PXENVIF_TRANSMITTER_PACKET *TailPacket;
- KIRQL Irql;
-
- UNREFERENCED_PARAMETER(PortNumber);
+ PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
+ PXENVIF_TRANSMITTER_PACKET_V1 *TailPacket;
HeadPacket = NULL;
TailPacket = &HeadPacket;
-
- if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
- ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
- NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
- } else {
- Irql = DISPATCH_LEVEL;
- }
-
+
while (NetBufferList != NULL) {
PNET_BUFFER_LIST ListNext;
PNET_BUFFER_LIST_RESERVED ListReserved;
@@ -220,8 +311,8 @@ TransmitterSendNetBufferLists(
NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
while (NetBuffer != NULL) {
- PNET_BUFFER_RESERVED Reserved;
- PXENVIF_TRANSMITTER_PACKET Packet;
+ PNET_BUFFER_RESERVED Reserved;
+ PXENVIF_TRANSMITTER_PACKET_V1 Packet;
Reserved =
(PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
@@ -248,24 +339,146 @@ TransmitterSendNetBufferLists(
NTSTATUS status;
status = XENVIF_VIF(TransmitterQueuePackets,
- AdapterGetVifInterface(Adapter),
+ Transmitter->VifInterface,
HeadPacket);
if (!NT_SUCCESS(status))
- __TransmitterCompletePackets(Transmitter, HeadPacket,
NDIS_STATUS_NOT_ACCEPTED);
+ __TransmitterCompletePacketsV1(Transmitter, HeadPacket,
NDIS_STATUS_NOT_ACCEPTED);
}
+}
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV2(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PNET_BUFFER_LIST NetBufferList
+ )
+{
+ LIST_ENTRY List;
+
+ InitializeListHead(&List);
+
+ while (NetBufferList != NULL) {
+ PNET_BUFFER_LIST ListNext;
+ PNET_BUFFER_LIST_RESERVED ListReserved;
+ XENVIF_VIF_OFFLOAD_OPTIONS Options;
+ USHORT TagControlInformation;
+ USHORT MaximumSegmentSize;
+ PNET_BUFFER NetBuffer;
+
+ ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+ NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+ ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+ RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+
+ __OffloadOptions(NetBufferList, &Options, &TagControlInformation,
&MaximumSegmentSize);
+
+ NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+ while (NetBuffer != NULL) {
+ PXENVIF_TRANSMITTER_PACKET_V2 Packet;
+
+ Packet = __TransmitterGetPacket(Transmitter);
+ if (Packet == NULL) {
+ while (ListReserved->Reference--) {
+ PLIST_ENTRY ListEntry;
+
+ ListEntry = RemoveTailList(&List);
+ ASSERT3U(ListEntry, !=, &List);
+
+ Packet = CONTAINING_RECORD(ListEntry,
XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+ __TransmitterPutPacket(Transmitter, Packet);
+ }
+ TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
NDIS_STATUS_NOT_ACCEPTED);
+ break;
+ }
+
+ Packet->Cookie = NetBufferList;
+ ListReserved->Reference++;
+
+ Packet->Send.OffloadOptions.Value = Options.Value &
Transmitter->OffloadOptions.Value;
+ Packet->Send.TagControlInformation = TagControlInformation;
+ Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
+ Packet->Mdl =
NET_BUFFER_CURRENT_MDL(NetBuffer);
+ Packet->Offset =
NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+ Packet->Length =
NET_BUFFER_DATA_LENGTH(NetBuffer);
+ RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
+
+ InsertTailList(&List, &Packet->ListEntry);
+
+ NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
+ }
+
+ NetBufferList = ListNext;
+ }
+
+ if (!IsListEmpty(&List)) {
+ NTSTATUS status;
+
+ status = XENVIF_VIF(TransmitterQueuePacketsV2,
+ Transmitter->VifInterface,
+ &List);
+ if (!NT_SUCCESS(status))
+ __TransmitterCompletePacketsV2(Transmitter, &List,
NDIS_STATUS_NOT_ACCEPTED);
+ }
+}
+
+VOID
+TransmitterSendNetBufferLists(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PNET_BUFFER_LIST NetBufferList,
+ IN NDIS_PORT_NUMBER PortNumber,
+ IN ULONG SendFlags
+ )
+{
+ KIRQL Irql;
+
+ UNREFERENCED_PARAMETER(PortNumber);
+
+ if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
+ ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
+ NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
+ } else {
+ Irql = DISPATCH_LEVEL;
+ }
+
+ switch (XENVIF_VIF_VERSION(Transmitter->VifInterface)) {
+ case 1:
+ __TransmitterSendNetBufferListsV1(Transmitter, NetBufferList);
+ break;
+
+ case 2:
+ __TransmitterSendNetBufferListsV2(Transmitter, NetBufferList);
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
}
VOID
-TransmitterCompletePackets(
- IN PXENNET_TRANSMITTER Transmitter,
- IN PXENVIF_TRANSMITTER_PACKET Packet
+TransmitterCompletePacketsV1(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET_V1 Packet
)
{
- __TransmitterCompletePackets(Transmitter,
- Packet,
- NDIS_STATUS_SUCCESS);
+ ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 1);
+ __TransmitterCompletePacketsV1(Transmitter,
+ Packet,
+ NDIS_STATUS_SUCCESS);
+}
+
+VOID
+TransmitterCompletePacketsV2(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PLIST_ENTRY List
+ )
+{
+ ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+ __TransmitterCompletePacketsV2(Transmitter,
+ List,
+ NDIS_STATUS_SUCCESS);
}
VOID
@@ -273,22 +486,23 @@ TransmitterEnable(
IN PXENNET_TRANSMITTER Transmitter
)
{
- PXENVIF_VIF_INTERFACE Vif = AdapterGetVifInterface(Transmitter->Adapter);
+ if (XENVIF_VIF_VERSION(Transmitter->VifInterface) != 1)
+ return;
(VOID) XENVIF_VIF(TransmitterSetPacketOffset,
- Vif,
+ Transmitter->VifInterface,
XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
(LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
(LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
(VOID) XENVIF_VIF(TransmitterSetPacketOffset,
- Vif,
+ Transmitter->VifInterface,
XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
(LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
(LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
(VOID) XENVIF_VIF(TransmitterSetPacketOffset,
- Vif,
+ Transmitter->VifInterface,
XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
(LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
(LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
@@ -318,8 +532,47 @@ TransmitterInitialize(
RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
(*Transmitter)->Adapter = Adapter;
+ (*Transmitter)->VifInterface = AdapterGetVifInterface(Adapter);
+ status = XENVIF_VIF(Acquire, (*Transmitter)->VifInterface);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
+ goto done;
+
+ (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
+ status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ status = XENBUS_CACHE(Create,
+ (*Transmitter)->CacheInterface,
+ "packets",
+ sizeof(XENVIF_TRANSMITTER_PACKET_V2),
+ 32,
+ __PacketCtor,
+ __PacketDtor,
+ __PacketAcquire,
+ __PacketRelease,
+ *Transmitter,
+ &(*Transmitter)->Cache);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+done:
return STATUS_SUCCESS;
+fail4:
+ Error("fail4\n");
+ XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
+ (*Transmitter)->CacheInterface = NULL;
+fail3:
+ Error("fail3\n");
+ XENVIF_VIF(Release, (*Transmitter)->VifInterface);
+ (*Transmitter)->VifInterface = NULL;
+fail2:
+ Error("fail2\n");
+ ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
fail1:
Error("fail1 (%08x)\n", status);
return status;
@@ -331,6 +584,19 @@ TransmitterTeardown(
IN PXENNET_TRANSMITTER Transmitter
)
{
+ if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
+ goto done;
+
+ XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->Cache);
+ Transmitter->Cache = NULL;
+
+ XENBUS_CACHE(Release, Transmitter->CacheInterface);
+ Transmitter->CacheInterface = NULL;
+
+done:
+ XENVIF_VIF(Release, Transmitter->VifInterface);
+ Transmitter->VifInterface = NULL;
+
ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
}
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index f99ffd3..adf3b4c 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -45,9 +45,15 @@ TransmitterSendNetBufferLists(
);
extern VOID
-TransmitterCompletePackets(
- IN PXENNET_TRANSMITTER Transmitter,
- IN PXENVIF_TRANSMITTER_PACKET Packet
+TransmitterCompletePacketsV1(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET_V1 Packet
+ );
+
+extern VOID
+TransmitterCompletePacketsV2(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PLIST_ENTRY List
);
extern VOID
--
1.9.4.msysgit.1
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |