|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 6/6] Calculate simple hash of IP/Ports
Pullup the packet headers into a cached buffer, and calculate
a simple hash over the Source/Destination IP Addresses and Ports.
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
src/xennet/transmitter.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 229 insertions(+)
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index c64591d..77bcf1f 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -34,6 +34,7 @@
#include "adapter.h"
#include <vif_interface.h>
#include <cache_interface.h>
+#include <tcpip.h>
#include "dbg_print.h"
#include "assert.h"
@@ -42,10 +43,14 @@ struct _XENNET_TRANSMITTER {
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
PXENBUS_CACHE PacketCache;
KSPIN_LOCK PacketLock;
+ PXENBUS_CACHE BufferCache;
+ KSPIN_LOCK BufferLock;
};
#define XENNET_PACKET_CACHE_MIN 32
#define TRANSMITTER_POOL_TAG 'TteN'
+#define BUFFER_CACHE_ITEM_SIZE 512
+#define MAX_HEADERS_LENGTH (sizeof(IP_ADDRESS) + sizeof(IP_ADDRESS) +
sizeof(USHORT) + sizeof(USHORT))
static NTSTATUS
__TransmitterPacketCtor(
@@ -88,6 +93,47 @@ __TransmitterPacketReleaseLock(
KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
}
+static NTSTATUS
+__TransmitterBufferCtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ UNREFERENCED_PARAMETER(Object);
+ return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterBufferDtor(
+ IN PVOID Argument,
+ IN PVOID Object
+ )
+{
+ UNREFERENCED_PARAMETER(Argument);
+ UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterBufferAcquireLock(
+ IN PVOID Argument
+ )
+{
+ PXENNET_TRANSMITTER Transmitter = Argument;
+
+ KeAcquireSpinLockAtDpcLevel(&Transmitter->BufferLock);
+}
+
+static VOID
+__TransmitterBufferReleaseLock(
+ IN PVOID Argument
+ )
+{
+ PXENNET_TRANSMITTER Transmitter = Argument;
+
+ KeReleaseSpinLockFromDpcLevel(&Transmitter->BufferLock);
+}
+
NDIS_STATUS
TransmitterInitialize (
IN PXENNET_ADAPTER Adapter,
@@ -108,6 +154,7 @@ TransmitterInitialize (
RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
(*Transmitter)->Adapter = Adapter;
KeInitializeSpinLock(&(*Transmitter)->PacketLock);
+ KeInitializeSpinLock(&(*Transmitter)->BufferLock);
status = XENBUS_CACHE(Create,
CacheInterface,
@@ -122,10 +169,30 @@ TransmitterInitialize (
&(*Transmitter)->PacketCache);
if (!NT_SUCCESS(status))
goto fail2;
+
+ status = XENBUS_CACHE(Create,
+ CacheInterface,
+ "buffer_cache",
+ BUFFER_CACHE_ITEM_SIZE,
+ 0,
+ __TransmitterBufferCtor,
+ __TransmitterBufferDtor,
+ __TransmitterBufferAcquireLock,
+ __TransmitterBufferReleaseLock,
+ *Transmitter,
+ &(*Transmitter)->BufferCache);
+ if (!NT_SUCCESS(status))
+ goto fail3;
return NDIS_STATUS_SUCCESS;
+fail3:
+ XENBUS_CACHE(Destroy,
+ CacheInterface,
+ (*Transmitter)->PacketCache);
+ (*Transmitter)->PacketCache = NULL;
fail2:
+ RtlZeroMemory(&(*Transmitter)->BufferLock, sizeof(KSPIN_LOCK));
RtlZeroMemory(&(*Transmitter)->PacketLock, sizeof(KSPIN_LOCK));
ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
*Transmitter = NULL;
@@ -144,10 +211,16 @@ TransmitterTeardown(
Transmitter->Adapter = NULL;
Transmitter->OffloadOptions.Value = 0;
+ RtlZeroMemory(&Transmitter->BufferLock, sizeof(KSPIN_LOCK));
RtlZeroMemory(&Transmitter->PacketLock, sizeof(KSPIN_LOCK));
XENBUS_CACHE(Destroy,
CacheInterface,
+ Transmitter->BufferCache);
+ Transmitter->BufferCache = NULL;
+
+ XENBUS_CACHE(Destroy,
+ CacheInterface,
Transmitter->PacketCache);
Transmitter->PacketCache = NULL;
@@ -188,6 +261,40 @@ __TransmitterPutPacket(
FALSE);
}
+static FORCEINLINE PVOID
+__TransmitterGetBuffer(
+ IN PXENNET_TRANSMITTER Transmitter
+ )
+{
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+ return XENBUS_CACHE(Get,
+ CacheInterface,
+ Transmitter->BufferCache,
+ FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutBuffer(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PVOID Buffer
+ )
+{
+ PXENBUS_CACHE_INTERFACE CacheInterface;
+
+ CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+ RtlZeroMemory(Buffer, BUFFER_CACHE_ITEM_SIZE);
+
+ XENBUS_CACHE(Put,
+ CacheInterface,
+ Transmitter->BufferCache,
+ Buffer,
+ FALSE);
+}
+
typedef struct _NET_BUFFER_LIST_RESERVED {
LONG Reference;
} NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -317,6 +424,127 @@ __TransmitterOffloadOptions(
}
}
+static ULONG
+__Hash(
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+{
+ PUCHAR Array = (PUCHAR)Buffer;
+ ULONG Accumulator;
+ ULONG Index;
+
+ Accumulator = 0;
+
+ for (Index = 0; Index < Length; ++Index) {
+ ULONG Overflow;
+
+ Accumulator = (Accumulator << 4) + Array[Index];
+
+ Overflow = Accumulator & 0x00000f00;
+ if (Overflow != 0) {
+ Accumulator ^= Overflow >> 8;
+ Accumulator ^= Overflow;
+ }
+ }
+
+ return Accumulator;
+}
+
+static ULONG
+__TransmitterCalculateHash(
+ IN PVOID Buffer,
+ IN PXENVIF_PACKET_INFO Info
+ )
+{
+ UCHAR Headers[MAX_HEADERS_LENGTH];
+ PUCHAR Ptr;
+
+ Ptr = (PUCHAR)Headers;
+
+ if (Info->IpHeader.Length) {
+ PIP_HEADER Ip = (PIP_HEADER)((PUCHAR)Buffer + Info->IpHeader.Offset);
+
+ switch (Ip->Version) {
+ case 4:
+ RtlCopyMemory(Ptr, &Ip->Version4.SourceAddress,
sizeof(IPV4_ADDRESS));
+ Ptr += sizeof(IPV4_ADDRESS);
+ RtlCopyMemory(Ptr, &Ip->Version4.DestinationAddress,
sizeof(IPV4_ADDRESS));
+ Ptr += sizeof(IPV4_ADDRESS);
+ break;
+ case 6:
+ RtlCopyMemory(Ptr, &Ip->Version6.SourceAddress,
sizeof(IPV6_ADDRESS));
+ Ptr += sizeof(IPV6_ADDRESS);
+ RtlCopyMemory(Ptr, &Ip->Version6.DestinationAddress,
sizeof(IPV6_ADDRESS));
+ Ptr += sizeof(IPV6_ADDRESS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (Info->TcpHeader.Length) {
+ PTCP_HEADER Tcp = (PTCP_HEADER)((PUCHAR)Buffer +
Info->TcpHeader.Offset);
+
+ RtlCopyMemory(Ptr, &Tcp->SourcePort, sizeof(USHORT));
+ Ptr += sizeof(USHORT);
+ RtlCopyMemory(Ptr, &Tcp->DestinationPort, sizeof(USHORT));
+ Ptr += sizeof(USHORT);
+ } else if (Info->UdpHeader.Length) {
+ PUDP_HEADER Udp = (PUDP_HEADER)((PUCHAR)Buffer +
Info->UdpHeader.Offset);
+
+ RtlCopyMemory(Ptr, &Udp->SourcePort, sizeof(USHORT));
+ Ptr += sizeof(USHORT);
+ RtlCopyMemory(Ptr, &Udp->DestinationPort, sizeof(USHORT));
+ Ptr += sizeof(USHORT);
+ }
+
+ if (Ptr == (PUCHAR)Headers)
+ return 0;
+
+ return __Hash(Headers, (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)Headers));
+}
+
+static ULONG
+__TransmitterGetHash(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PXENVIF_TRANSMITTER_PACKET Packet
+ )
+{
+ PXENVIF_VIF_INTERFACE VifInterface;
+ ULONG Hash;
+ XENVIF_PACKET_INFO Info;
+ PVOID Buffer;
+ NTSTATUS status;
+
+ Hash = 0;
+ VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
+
+ Buffer = __TransmitterGetBuffer(Transmitter);
+ if (Buffer == NULL)
+ goto fail1;
+
+ RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
+
+ status = XENVIF_VIF(TransmitterGetPacketHeaders,
+ VifInterface,
+ Packet,
+ Buffer,
+ &Info);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ Hash = __TransmitterCalculateHash(Buffer, &Info);
+
+ __TransmitterPutBuffer(Transmitter, Buffer);
+ return Hash;
+
+fail2:
+ __TransmitterPutBuffer(Transmitter, Buffer);
+fail1:
+ return 0;
+}
+
VOID
TransmitterSendNetBufferLists(
IN PXENNET_TRANSMITTER Transmitter,
@@ -387,6 +615,7 @@ TransmitterSendNetBufferLists(
Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+ Packet->Value = __TransmitterGetHash(Transmitter, Packet);
InsertTailList(&List, &Packet->ListEntry);
--
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 |