[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [PATCH 2/4] Add VIF interface version 2



> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@xxxxxxxxxx]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Paul Durrant; Owen Smith
> Subject: [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)) {

You should not need to do this. Newer subscribers should only every use the 
latest version of any API (and should only bind to the matching PDO name).

> +        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);
> +}

I think you need to implement these. You call the Get and Put methods below 
with a FALSE locked argument which suggests that you're not guaranteeing that 
the allocation/freeing code inside the cache cannot be re-entered.

> +
> +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;
>      }
>  }
> -

You should not need the above function since you can assert xennet is using v2 
of the interface, since it should only bind to a Xenvif that exports v2.

> +
> +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(N
> etBufferList);
> +
> +        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);
>      }
> +}
> 

Again, you don't need the above function.

> +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(N
> etBufferList);
> +        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);

Only need this case.

> +        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);
> +}
> +

Don't need the above function.

> +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

You're missing a change to the INF file to bind to the new PDO name.

  Paul

> --
> 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®.