};
};
-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)
C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V2
+ \brief Transmit-side packet structure (v2)
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+ /*! List entry used for chaining packets together */
+ LIST_ENTRY ListEntry;
+ /*! Opaque cookie used to store context information for packet return */
+ PVOID Cookie;
+ /*! Hash value set by subscriber */
+ ULONG Value;
+ /*! Packet information passed from subscriber to provider */
+ XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
+ /*! Packet information passed from provider to subscriber on packet return */
+ XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion;
+ /*! Packet data MDL */
+ PMDL Mdl;
+ /*! Offset into MDL to start of packet */
+ ULONG Offset;
+ /*! Packet length */
+ ULONG Length;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
\brief Offsets of packet metadata relative to
XENVIF_TRANSMITTER_PACKET pointer
IN LONG_PTR Value
);
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+ \brief Get the packet headers into supplied buffer
+
+ \param Interface The interface header
+ \param Packet The packet to acquire headers for.
+ \param Headers The buffer to receive headers.
+ \param Info The offsets into Headers for relevant headers
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+ IN PINTERFACE Interface,
+ IN PXENVIF_TRANSMITTER_PACKET Packet,
+ OUT PVOID Headers,
+ OUT PXENVIF_PACKET_INFO Info
+ );
+
/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
\brief Queue transmit side packets at the provider
\param Interface The interface header
- \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+ \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
+ 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_QUERY_OFFLOAD_OPTIONS
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \struct _XENVIF_VIF_INTERFACE_V2
+ \brief VIF interface version 2
+ \ingroup interfaces
+*/
+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_GET_PACKET_HEADERS TransmitterGetPacketHeaders;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2 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_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
/*! \def XENVIF_VIF
\brief Macro at assist in method invocation
#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
#include "transmitter.h"
#include "adapter.h"
#include <vif_interface.h>
+#include <cache_interface.h>
#include "dbg_print.h"
#include "assert.h"
struct _XENNET_TRANSMITTER {
PXENNET_ADAPTER Adapter;
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
+ KSPIN_LOCK Lock;
+ PXENBUS_CACHE PacketCache;
};
+#define XENNET_PACKET_CACHE_MIN 32
#define TRANSMITTER_POOL_TAG 'TteN'
+static NTSTATUS
+__TransmitterPacketCtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ UNREFERENCED_PARAMETER(Object);
+ return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterPacketDtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterPacketAcquireLock(
+ IN PVOID Argument
+ )
+{
+ PXENNET_TRANSMITTER Transmitter = Argument;
+
+ KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
+}
+
+static VOID
+__TransmitterPacketReleaseLock(
+ IN PVOID Argument
+ )
+{
+ PXENNET_TRANSMITTER Transmitter = Argument;
+
+#pragma prefast(suppress:26110)
+ KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
+}
+
NDIS_STATUS
TransmitterInitialize (
IN PXENNET_ADAPTER Adapter,
OUT PXENNET_TRANSMITTER *Transmitter
)
{
+ NTSTATUS status;
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Adapter);
+
*Transmitter = ExAllocatePoolWithTag(NonPagedPool,
sizeof(XENNET_TRANSMITTER),
TRANSMITTER_POOL_TAG);
+
+ status = STATUS_NO_MEMORY;
if (*Transmitter == NULL)
goto fail1;
RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
+
(*Transmitter)->Adapter = Adapter;
+ KeInitializeSpinLock(&(*Transmitter)->Lock);
+
+ status = XENBUS_CACHE(Create,
+ CacheInterface,
+ "packet_cache",
+ sizeof(XENVIF_TRANSMITTER_PACKET),
+ XENNET_PACKET_CACHE_MIN,
+ __TransmitterPacketCtor,
+ __TransmitterPacketDtor,
+ __TransmitterPacketAcquireLock,
+ __TransmitterPacketReleaseLock,
+ *Transmitter,
+ &(*Transmitter)->PacketCache);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
return NDIS_STATUS_SUCCESS;
+fail2:
+ Error("fail2\n");
+
+ RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK));
+
+ ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
+
+ *Transmitter = NULL;
+
fail1:
+ Error("fail1\n (%08x)", status);
+
return NDIS_STATUS_FAILURE;
}
IN PXENNET_TRANSMITTER Transmitter
)
{
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
Transmitter->Adapter = NULL;
Transmitter->OffloadOptions.Value = 0;
+ RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK));
+
+ XENBUS_CACHE(Destroy,
+ CacheInterface,
+ Transmitter->PacketCache);
+ Transmitter->PacketCache = NULL;
ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
}
-VOID
-TransmitterEnable(
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+__TransmitterGetPacket(
IN PXENNET_TRANSMITTER Transmitter
)
{
- PXENVIF_VIF_INTERFACE VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
-
- (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
- 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,
- 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,
- VifInterface,
- XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
- (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
- (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+ return XENBUS_CACHE(Get,
+ CacheInterface,
+ Transmitter->PacketCache,
+ FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET Packet
+ )
+{
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+ RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET));
+
+ XENBUS_CACHE(Put,
+ CacheInterface,
+ Transmitter->PacketCache,
+ Packet,
+ FALSE);
}
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;
-} NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
-
-C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
-
static VOID
__TransmitterCompleteNetBufferList(
IN PXENNET_TRANSMITTER Transmitter,
NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
}
-
static VOID
__TransmitterCompletePackets(
- IN PXENNET_TRANSMITTER Transmitter,
- IN PXENVIF_TRANSMITTER_PACKET Packet,
- IN NDIS_STATUS Status
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PLIST_ENTRY List,
+ IN NDIS_STATUS Status
)
{
- while (Packet != NULL) {
- PXENVIF_TRANSMITTER_PACKET Next;
- PNET_BUFFER_RESERVED Reserved;
+ while (!IsListEmpty(List)) {
+ PLIST_ENTRY ListEntry;
+ PXENVIF_TRANSMITTER_PACKET Packet;
PNET_BUFFER_LIST NetBufferList;
PNET_BUFFER_LIST_RESERVED ListReserved;
- Next = Packet->Next;
- Packet->Next = NULL;
+ ListEntry = RemoveHeadList(List);
+ ASSERT3P(ListEntry, !=, List);
- Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
- NetBufferList = Reserved->NetBufferList;
+ NetBufferList = Packet->Cookie;
ASSERT(NetBufferList != NULL);
ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
if (InterlockedDecrement(&ListReserved->Reference) == 0)
__TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
- Packet = Next;
+ __TransmitterPutPacket(Transmitter, Packet);
}
}
IN ULONG SendFlags
)
{
- PXENVIF_TRANSMITTER_PACKET HeadPacket;
- PXENVIF_TRANSMITTER_PACKET *TailPacket;
+ LIST_ENTRY List;
KIRQL Irql;
UNREFERENCED_PARAMETER(PortNumber);
- HeadPacket = NULL;
- TailPacket = &HeadPacket;
+ InitializeListHead(&List);
if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
while (NetBuffer != NULL) {
- PNET_BUFFER_RESERVED Reserved;
PXENVIF_TRANSMITTER_PACKET Packet;
- Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
- RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
+ Packet = __TransmitterGetPacket(Transmitter);
+ if (Packet == NULL) {
+ while (ListReserved->Reference--) {
+ PLIST_ENTRY ListEntry;
+
+ ListEntry = RemoveTailList(&List);
+ ASSERT3P(ListEntry, !=, &List);
+
+ Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+
+ __TransmitterPutPacket(Transmitter, Packet);
+ }
+ __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NDIS_STATUS_NOT_ACCEPTED);
+ break;
+ }
- Reserved->NetBufferList = NetBufferList;
ListReserved->Reference++;
- Packet = &Reserved->Packet;
+ Packet->Cookie = NetBufferList;
Packet->Send.OffloadOptions.Value = OffloadOptions.Value & Transmitter->OffloadOptions.Value;
Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
Packet->Send.TagControlInformation = TagControlInformation;
+ Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
+ Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
+ Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
- ASSERT3P(Packet->Next, ==, NULL);
- *TailPacket = Packet;
- TailPacket = &Packet->Next;
+ InsertTailList(&List, &Packet->ListEntry);
NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
}
NetBufferList = ListNext;
}
- if (HeadPacket != NULL) {
+ if (!IsListEmpty(&List)) {
NTSTATUS status;
status = XENVIF_VIF(TransmitterQueuePackets,
AdapterGetVifInterface(Transmitter->Adapter),
- HeadPacket);
+ &List);
if (!NT_SUCCESS(status))
- __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
+ __TransmitterCompletePackets(Transmitter, &List, NDIS_STATUS_NOT_ACCEPTED);
}
NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
VOID
TransmitterCompletePackets(
- IN PXENNET_TRANSMITTER Transmitter,
- IN PXENVIF_TRANSMITTER_PACKET Packet
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PLIST_ENTRY List
)
{
- __TransmitterCompletePackets(Transmitter, Packet, NDIS_STATUS_SUCCESS);
+ __TransmitterCompletePackets(Transmitter, List, NDIS_STATUS_SUCCESS);
}
PXENVIF_VIF_OFFLOAD_OPTIONS