[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.