[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |