diff mbox

[ovs-dev,2/3] datapath-windows: STT - Add support for TCP Segmentation Offload

Message ID 1445719222-4664-3-git-send-email-vsairam@vmware.com
State Superseded
Headers show

Commit Message

Sairam Venugopal Oct. 24, 2015, 8:40 p.m. UTC
Create and initialize the background thread and buffer that
assists in defragmenting and completing a TSO packet.

Signed-off-by: Sairam Venugopal <vsairam@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(-)

Comments

Nithin Raju Oct. 27, 2015, 5:14 p.m. UTC | #1
Acked-by: Nithin Raju <nithin@vmware.com>

-----Original Message-----
From: Sairam Venugopal <vsairam@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 <vsairam@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 *)&currentTime);
>+        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=
diff mbox

Patch

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 *)&currentTime);
+        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");