Acked-by: Nithin Raju <nit...@vmware.com> -----Original Message----- From: Sairam Venugopal <vsai...@vmware.com> Date: Saturday, October 24, 2015 at 1:40 PM To: "dev@openvswitch.org" <dev@openvswitch.org> Subject: [ovs-dev] [PATCH 2/3] datapath-windows: STT - Add support for TCP Segmentation Offload
>Create and initialize the background thread and buffer that >assists in defragmenting and completing a TSO packet. > >Signed-off-by: Sairam Venugopal <vsai...@vmware.com> >--- > datapath-windows/ovsext/Stt.c | 128 >++++++++++++++++++++++++++++++++++++++- > datapath-windows/ovsext/Stt.h | 33 +++++++++- > datapath-windows/ovsext/Switch.c | 7 +++ > 3 files changed, 162 insertions(+), 6 deletions(-) > >diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c >index 4a5a4a6..b78ef95 100644 >--- a/datapath-windows/ovsext/Stt.c >+++ b/datapath-windows/ovsext/Stt.c >@@ -35,6 +35,11 @@ > #define OVS_DBG_MOD OVS_DBG_STT > #include "Debug.h" > >+KSTART_ROUTINE OvsSttDefragCleaner; >+static PLIST_ENTRY OvsSttPktFragHash; >+static NDIS_SPIN_LOCK OvsSttSpinLock; >+static OVS_STT_THREAD_CTX sttDefragThreadCtx; >+ > static NDIS_STATUS > OvsDoEncapStt(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, > const OvsIPv4TunnelKey *tunKey, >@@ -349,7 +354,7 @@ OvsCalculateTCPChecksum(PNET_BUFFER_LIST curNbl, >PNET_BUFFER curNb) > if (csumInfo.Receive.TcpChecksumSucceeded) { > return NDIS_STATUS_SUCCESS; > } >- >+ > EthHdr *eth = (EthHdr *)NdisGetDataBuffer(curNb, sizeof(EthHdr), > NULL, 1, 0); > >@@ -379,6 +384,123 @@ OvsCalculateTCPChecksum(PNET_BUFFER_LIST curNbl, >PNET_BUFFER curNb) > } > > /* >+ >*------------------------------------------------------------------------- >--- >+ * OvsInitSttDefragmentation >+ * Initialize the components used by the stt lso defragmentation >+ >*------------------------------------------------------------------------- >--- >+ */ >+NTSTATUS >+OvsInitSttDefragmentation() >+{ >+ NTSTATUS status; >+ HANDLE threadHandle = NULL; >+ >+ /* Init the sync-lock */ >+ NdisAllocateSpinLock(&OvsSttSpinLock); >+ >+ /* Init the Hash Buffer */ >+ OvsSttPktFragHash = (PLIST_ENTRY) OvsAllocateMemoryWithTag( >+ sizeof(LIST_ENTRY) >+ * STT_HASH_TABLE_SIZE, >+ OVS_STT_POOL_TAG); >+ if (OvsSttPktFragHash == NULL) { >+ NdisFreeSpinLock(&OvsSttSpinLock); >+ return STATUS_INSUFFICIENT_RESOURCES; >+ } >+ >+ for (int i = 0; i < STT_HASH_TABLE_SIZE; i++) { >+ InitializeListHead(&OvsSttPktFragHash[i]); >+ } >+ >+ /* Init Defrag Cleanup Thread */ >+ KeInitializeEvent(&sttDefragThreadCtx.event, NotificationEvent, >FALSE); >+ status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL, >+ NULL, OvsSttDefragCleaner, >+ &sttDefragThreadCtx); >+ >+ if (status != STATUS_SUCCESS) { >+ OvsCleanupSttDefragmentation(); >+ return status; >+ } >+ >+ ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, >KernelMode, >+ &sttDefragThreadCtx.threadObject, NULL); >+ ZwClose(threadHandle); >+ threadHandle = NULL; >+ return STATUS_SUCCESS; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * OvsCleanupSttDefragmentation >+ * Cleanup memory and thread that were spawned for STT LSO >defragmentation >+ >*------------------------------------------------------------------------- >--- >+ */ >+VOID >+OvsCleanupSttDefragmentation(VOID) >+{ >+ NdisAcquireSpinLock(&OvsSttSpinLock); >+ sttDefragThreadCtx.exit = 1; >+ KeSetEvent(&sttDefragThreadCtx.event, 0, FALSE); >+ NdisReleaseSpinLock(&OvsSttSpinLock); >+ >+ KeWaitForSingleObject(sttDefragThreadCtx.threadObject, Executive, >+ KernelMode, FALSE, NULL); >+ ObDereferenceObject(sttDefragThreadCtx.threadObject); >+ >+ if (OvsSttPktFragHash) { >+ OvsFreeMemoryWithTag(OvsSttPktFragHash, OVS_STT_POOL_TAG); >+ OvsSttPktFragHash = NULL; >+ } >+ >+ NdisFreeSpinLock(&OvsSttSpinLock); >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * OvsSttDefragCleaner >+ * Runs periodically and cleans up the buffer to remove expired >segments >+ >*------------------------------------------------------------------------- >--- >+ */ >+VOID >+OvsSttDefragCleaner(PVOID data) >+{ >+ POVS_STT_THREAD_CTX context = (POVS_STT_THREAD_CTX)data; >+ PLIST_ENTRY link, next; >+ POVS_STT_PKT_ENTRY entry; >+ BOOLEAN success = TRUE; >+ >+ while (success) { >+ NdisAcquireSpinLock(&OvsSttSpinLock); >+ if (context->exit) { >+ NdisReleaseSpinLock(&OvsSttSpinLock); >+ break; >+ } >+ >+ /* Set the timeout for the thread and cleanup */ >+ UINT64 currentTime, threadSleepTimeout; >+ NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime); >+ threadSleepTimeout = currentTime + STT_CLEANUP_INTERVAL; >+ >+ for (int i = 0; i < STT_HASH_TABLE_SIZE; i++) { >+ LIST_FORALL_SAFE(&OvsSttPktFragHash[i], link, next) { >+ entry = CONTAINING_RECORD(link, OVS_STT_PKT_ENTRY, link); >+ if (entry->timeout < currentTime) { >+ RemoveEntryList(&entry->link); >+ OvsFreeMemoryWithTag(entry, OVS_STT_POOL_TAG); >+ } >+ } >+ } >+ >+ NdisReleaseSpinLock(&OvsSttSpinLock); >+ KeWaitForSingleObject(&context->event, Executive, KernelMode, >+ FALSE, (LARGE_INTEGER >*)&threadSleepTimeout); >+ } >+ >+ PsTerminateSystemThread(STATUS_SUCCESS); >+} >+ >+/* > * >-------------------------------------------------------------------------- > * OvsDecapStt -- > * Decapsulates an STT packet. >@@ -416,7 +538,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > if (csumInfo.Receive.TcpChecksumFailed) { > return NDIS_STATUS_INVALID_PACKET; > } >- >+ > /* Calculate the TCP Checksum */ > status = OvsCalculateTCPChecksum(curNbl, curNb); > if (status != NDIS_STATUS_SUCCESS) { >@@ -455,7 +577,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > hdrLen = STT_HDR_LEN; > NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); > advanceCnt += hdrLen; >- >+ > /* Verify checksum for inner packet if it's required */ > if (!(sttHdr->flags & STT_CSUM_VERIFIED)) { > BOOLEAN innerChecksumPartial = sttHdr->flags & STT_CSUM_PARTIAL; >diff --git a/datapath-windows/ovsext/Stt.h b/datapath-windows/ovsext/Stt.h >index 38d721c..9a45379 100644 >--- a/datapath-windows/ovsext/Stt.h >+++ b/datapath-windows/ovsext/Stt.h >@@ -34,6 +34,11 @@ > #define STT_PROTO_TCP (1 << 3) > #define STT_PROTO_TYPES (STT_PROTO_IPV4 | STT_PROTO_TCP) > >+#define STT_HASH_TABLE_SIZE ((UINT32)1 << 10) >+#define STT_HASH_TABLE_MASK (STT_HASH_TABLE_SIZE - 1) >+#define STT_ENTRY_TIMEOUT 300000000 // 30s >+#define STT_CLEANUP_INTERVAL 300000000 // 30s >+ > #define STT_ETH_PAD 2 > typedef struct SttHdr { > UINT8 version; >@@ -58,14 +63,32 @@ typedef struct _OVS_STT_VPORT { > UINT64 slowOutPkts; > } OVS_STT_VPORT, *POVS_STT_VPORT; > >+typedef struct _OVS_STT_PKT_KEY { >+ UINT32 sAddr; >+ UINT32 dAddr; >+ UINT32 ackSeq; >+} OVS_STT_PKT_KEY, *POVS_STT_PKT_KEY; >+ >+typedef struct _OVS_STT_PKT_ENTRY { >+ OVS_STT_PKT_KEY ovsPktKey; >+ UINT64 timeout; >+ UINT32 recvdLen; >+ SttHdr sttHdr; >+ PCHAR packetBuf; >+ LIST_ENTRY link; >+} OVS_STT_PKT_ENTRY, *POVS_STT_PKT_ENTRY; >+ >+typedef struct _OVS_STT_THREAD_CTX { >+ KEVENT event; >+ PVOID threadObject; >+ UINT32 exit; >+} OVS_STT_THREAD_CTX, *POVS_STT_THREAD_CTX; >+ > NTSTATUS OvsInitSttTunnel(POVS_VPORT_ENTRY vport, > UINT16 udpDestPort); > > VOID OvsCleanupSttTunnel(POVS_VPORT_ENTRY vport); > >- >-void OvsCleanupSttTunnel(POVS_VPORT_ENTRY vport); >- > NDIS_STATUS OvsEncapStt(POVS_VPORT_ENTRY vport, > PNET_BUFFER_LIST curNbl, > OvsIPv4TunnelKey *tunKey, >@@ -79,6 +102,10 @@ NDIS_STATUS OvsDecapStt(POVS_SWITCH_CONTEXT >switchContext, > OvsIPv4TunnelKey *tunKey, > PNET_BUFFER_LIST *newNbl); > >+NTSTATUS OvsInitSttDefragmentation(); >+ >+VOID OvsCleanupSttDefragmentation(VOID); >+ > static __inline UINT32 > OvsGetSttTunHdrSize(VOID) > { >diff --git a/datapath-windows/ovsext/Switch.c >b/datapath-windows/ovsext/Switch.c >index f176fa0..2878e91 100644 >--- a/datapath-windows/ovsext/Switch.c >+++ b/datapath-windows/ovsext/Switch.c >@@ -212,6 +212,12 @@ OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle, > goto create_switch_done; > } > >+ status = OvsInitSttDefragmentation(); >+ if (status != STATUS_SUCCESS) { >+ OVS_LOG_ERROR("Exit: Failed to initialize Stt Defragmentation"); >+ goto create_switch_done; >+ } >+ > *switchContextOut = switchContext; > > create_switch_done: >@@ -242,6 +248,7 @@ OvsExtDetach(NDIS_HANDLE filterModuleContext) > } > OvsDeleteSwitch(switchContext); > OvsCleanupIpHelper(); >+ OvsCleanupSttDefragmentation(); > /* This completes the cleanup, and a new attach can be handled now. >*/ > > OVS_LOG_TRACE("Exit: OvsDetach Successfully"); >-- >1.9.5.msysgit.0 > >_______________________________________________ >dev mailing list >dev@openvswitch.org >https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma >n_listinfo_dev&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN >HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=LUW2duErC-tdULtAKNhaFj3wo1orb6 >b9QkeMhlK7vps&s=7Ixnj8S6FmY7M6DUTFEGQgD7SJytxzvUnKGSafdRTZo&e= _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev