[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.