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