Hi Sorin,
Thank you for addressing these issues. Please find some minor comments below.
The issue I see now is that the IOCTL completion is not synchronized with the 
engine execution and if the transaction fails it is not propagated to user mode 
. I realize that the thread exists when the transaction fails but we might just 
fail the transaction.
I think once we have the IOCTL synced we can go ahead with this challenging 
change.
Eitan

-----Original Message-----
From: Eitan Eliahu 
Sent: Tuesday, January 20, 2015 9:07 AM
To: 'Sorin Vinturis'
Subject: RE: [ovs-dev] [PATCH v2] datapath-windows: Support for custom VXLAN 
tunnel port


Hi Sorin, once you comment out the call to OvsDetectTunnelRxPkt() the driver 
should ignore the received packet and to indicate it up to the host stack. This 
means that any packet (not just fragmented) will be indicated to the host.
We can deal with adding the opening of the socket in vswitchd later. For 
purpose of testing this code you can run any other application which open a 
VXLAN UDP port (concurrently with vswitchd.exe) .
Thanks,
Eitan

-----Original Message-----
From: Sorin Vinturis [mailto:[email protected]]
Sent: Monday, January 19, 2015 7:04 AM
To: Eitan Eliahu; [email protected]
Subject: RE: [ovs-dev] [PATCH v2] datapath-windows: Support for custom VXLAN 
tunnel port

Hi Eitan,

I have not manage to successfully shortcut fast path. I have changed the 
netlink library to create the necessary socket in order for the packets to go 
through the filter, but the resulted vswitchd binary hangs when I execute it. 
Thus could not perform the test that shortcuts the fast path.

For testing the patch I have created a script that adds vxlan tunnels with 
different destination ports. Each add vxlan tunnel command, that triggers a 
OVS_VPORT_CMD_NEW command, is followed by a set command, that triggers first a 
OVS_VPORT_CMD_NEW command for the new vport with the new destination port, and 
an OVS_VPORT_CMD_DELETE command for deleting the first vport. 

Below is an excerpt of the script I used:

start .\rundb.bat
Start-Sleep -s 2
start .\runvswitch.bat
.\ovs-vsctl.exe --db=tcp:127.0.0.1:8777 add-br br0 .\ovs-vsctl.exe 
--db=tcp:127.0.0.1:8777 add-port br0 vxlan1 -- set interface vxxlan1 type=vxlan 
options:remote_ip=10.1.1.112 options:dst_port=5000 .\ovs-vsctl.exe 
--db=tcp:127.0.0.1:8777 -- set interface vxlan1 type=vxlan 
options:remote_ip=10.1.1.112 options:dst_port=5001

--
Sorin

-----Original Message-----
From: Eitan Eliahu [mailto:[email protected]]
Sent: Friday, 16 January, 2015 17:38
To: Sorin Vinturis; [email protected]
Subject: RE: [ovs-dev] [PATCH v2] datapath-windows: Support for custom VXLAN 
tunnel port

Hi Sorin,
Thank you for addressing the issues, specifically,  executing the engine from a 
thread running in lower IRQL.
Can you please add some comments on the testing you performed? Where you able 
to shortcut the fast path and to open the VXLAN UDP port in user mode so 
packets will go through the filter?

Eitan 

-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Sorin Vinturis
Sent: Thursday, January 15, 2015 1:11 PM
To: [email protected]
Subject: [ovs-dev] [PATCH v2] datapath-windows: Support for custom VXLAN tunnel 
port

The kernel datapath supports only port 4789 for VXLAN tunnel creation.
Added support in order to allow for the VXLAN tunnel port to be configurable to 
any port number set by the userspace.

The patch also checks to see if an existing WFP filter, for the necessary UDP 
tunnel port, is already created before adding a new one.
This is a double check, because currently the userspace also verifies this, but 
it is necessary to avoid future issues.

Custom VXLAN tunnel port requires the addition of a new WFP filter with the new 
UDP tunnel port. The creation of a new WFP filter is triggered in 
OvsInitVxlanTunnel function and the removal of the WFP filter in 
OvsCleanupVxlanTunnel function.
But the latter functions are running at IRQL = DISPATCH_LEVEL, due to the NDIS 
RW lock acquisition, and all WFP calls must be running at IRQL = PASSIVE_LEVEL. 
This is why I have created a system thread which records all filter 
addition/removal requests into a list for later processing by the system 
thread. The ThreadStart routine processes all received requests at IRQL = 
PASSIVE_LEVEL, which is the required IRQL for the necessary WFP calls for 
adding/removal of the WFP filters.

The WFP filter for the default VXLAN port 4789 is not added anymore at filter 
attach. All WFP filters for the tunnel ports are added when the tunnel ports 
are initialized and are removed at cleanup.

It is necessary that OvsTunnelFilterUninitialize function is called after 
OvsClearAllSwitchVports in order to allow for the added WFP filters to be 
removed. OvsTunnelFilterUninitialize function closes the global engine handle 
used by most of the WFP calls, including filter removal.

Signed-off-by: Sorin Vinturis <[email protected]>
Reported-by: Alin Gabriel Serdean <[email protected]>
Reported-at: 
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_openvswitch_ovs-2Dissues_issues_66&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=VmREdmxxsERc3TdRTLuqj-tDd42IJUEuvcXW-vWM5Mc&s=M_OrcxSLPFtZNI5KVfqaF7oSnM_vU3_Sj2E0GAESvqc&e=
---
 datapath-windows/ovsext/Switch.c       |   2 +-
 datapath-windows/ovsext/Tunnel.h       |   6 -
 datapath-windows/ovsext/TunnelFilter.c | 484 ++++++++++++++++++++++++++++-----
 datapath-windows/ovsext/TunnelIntf.h   |   4 +
 datapath-windows/ovsext/Vport.c        |  13 +-
 datapath-windows/ovsext/Vxlan.c        |  53 +++-
 datapath-windows/ovsext/Vxlan.h        |   2 +-
 7 files changed, 473 insertions(+), 91 deletions(-)

diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c
index a228d8e..cf5e3c4 100644
--- a/datapath-windows/ovsext/Switch.c
+++ b/datapath-windows/ovsext/Switch.c
@@ -261,8 +261,8 @@ OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext)
     if (switchContext)
     {
         dpNo = switchContext->dpNo;
-        OvsTunnelFilterUninitialize(gOvsExtDriverObject);
         OvsClearAllSwitchVports(switchContext);
+        OvsTunnelFilterUninitialize(gOvsExtDriverObject);
         OvsUninitSwitchContext(switchContext);
         OvsFreeMemory(switchContext);
     }
diff --git a/datapath-windows/ovsext/Tunnel.h b/datapath-windows/ovsext/Tunnel.h
index 2978bb3..2c45e35 100644
--- a/datapath-windows/ovsext/Tunnel.h
+++ b/datapath-windows/ovsext/Tunnel.h
@@ -32,12 +32,6 @@ typedef struct OVS_TUNNEL_PENDED_PACKET_
    FWPS_CLASSIFY_OUT *classifyOut;
 } OVS_TUNNEL_PENDED_PACKET;
 
-/* Shared global data. */
-
-extern UINT16 configNewDestPort;
-
-extern UINT32 gCalloutIdV4;
-
 //
 // Shared function prototypes
 //
diff --git a/datapath-windows/ovsext/TunnelFilter.c 
b/datapath-windows/ovsext/TunnelFilter.c
index e0adc37..b4289e6 100644
--- a/datapath-windows/ovsext/TunnelFilter.c
+++ b/datapath-windows/ovsext/TunnelFilter.c
@@ -63,9 +63,6 @@
 /* The session name isn't required but it's useful for diagnostics. */
 #define OVS_TUNNEL_SESSION_NAME         L"OVS tunnel session"
 
-/* Configurable parameters (addresses and ports are in host order) */
-UINT16   configNewDestPort = VXLAN_UDP_PORT;
-
 /*
  * Callout and sublayer GUIDs
  */
@@ -105,14 +102,57 @@ DEFINE_GUID(
     0xa5, 0x36, 0x1e, 0xed, 0xb9, 0xe9, 0xba, 0x6a
     );
 
+KSTART_ROUTINE  OvsTunnelFilterThreadProc;
+NTSTATUS        OvsTunnelFilterThreadInit();
+VOID            OvsTunnelFilterThreadStop();
+VOID            OvsTunnelFilterThreadCleanup();
+
 /*
- * Callout driver global variables
+ * Callout driver type definitions
  */
-PDEVICE_OBJECT gDeviceObject;
-
-HANDLE gEngineHandle = NULL;
-UINT32 gCalloutIdV4;
+typedef enum _OVS_TUNFLT_OPERATION {
+    OVS_TUN_FILTER_CREATE = 0,
+    OVS_TUN_FILTER_DELETE
+} OVS_TUNFLT_OPERATION;
+
+typedef struct _OVS_TUNFLT_REQUEST {
+    LIST_ENTRY              entry;
+    /* Tunnel filter destination port. */
+    UINT16                  port;
+    /* Tunnel filter identification. */
+    UINT64                  ID;
+    /* Requested operation to be performed. */
+    OVS_TUNFLT_OPERATION    operation;
+    /* Context used to return filter ID to the caller. */
+    PVOID                   context;
+} OVS_TUNFLT_REQUEST, *POVS_TUNFLT_REQUEST;
+
+typedef struct _OVS_TUNFLT_REQUEST_LIST {
+    /* SpinLock for syncronizing access to the requests list. */
+    NDIS_SPIN_LOCK  spinlock;
+    /* Head of the requests list. */
+    LIST_ENTRY      head;
+    /* Number of OVS_TUNFLT_REQUEST entries in the list. */
+    UINT64          numEntries;
+} OVS_TUNFLT_REQUEST_LIST, *POVS_TUNFLT_REQUEST_LIST;
+
+typedef struct _OVS_TUNFLT_THREAD_CONTEXT {
+    /* Reference of the thread object. */
+    PVOID   threadObject;
+    /* Event signaling that there are requests to process. */
+    KEVENT  requestEvent;
+    /* Event for stopping thread execution. */
+    KEVENT  stopEvent;
+} OVS_TUNFLT_THREAD_CONTEXT, *POVS_TUNFLT_THREAD_CONTEXT;
 
+/*
+ * Callout driver global variables
+ */
+PDEVICE_OBJECT              gDeviceObject = NULL;
+HANDLE                      gEngineHandle = NULL;
+UINT32                      gCalloutIdV4 = 0;
+OVS_TUNFLT_REQUEST_LIST     gTunnelRequestList = { 0 };
+OVS_TUNFLT_THREAD_CONTEXT   gTunnelThreadCtx = { 0 };
 
 /* Callout driver implementation */
 
@@ -239,7 +279,8 @@ OvsTunnelAddFilter(PWSTR filterName,
                    UINT64 context,
                    const GUID *filterKey,
                    const GUID *layerKey,
-                   const GUID *calloutKey)
+                   const GUID *calloutKey,
+                   UINT64 *filterID)
 {
     NTSTATUS status = STATUS_SUCCESS;
     FWPM_FILTER filter = {0};
@@ -249,7 +290,9 @@ OvsTunnelAddFilter(PWSTR filterName,
     UNREFERENCED_PARAMETER(remotePort);
     UNREFERENCED_PARAMETER(direction);
 
-    filter.filterKey = *filterKey;
+    if (filterKey) {
+        filter.filterKey = *filterKey;
+    }
     filter.layerKey = *layerKey;
     filter.displayData.name = (wchar_t*)filterName;
     filter.displayData.description = (wchar_t*)filterDesc; @@ -282,54 +325,8 
@@ OvsTunnelAddFilter(PWSTR filterName,
     status = FwpmFilterAdd(gEngineHandle,
                            &filter,
                            NULL,
-                           NULL);
-
-    return status;
-}
-
-NTSTATUS
-OvsTunnelRemoveFilter(const GUID *filterKey,
-                      const GUID *sublayerKey)
-{
-    NTSTATUS status = STATUS_SUCCESS;
-    BOOLEAN inTransaction = FALSE;
-
-    do {
-        status = FwpmTransactionBegin(gEngineHandle, 0);
-        if (!NT_SUCCESS(status)) {
-            break;
-        }
+                           filterID);
 
-        inTransaction = TRUE;
-
-        /*
-         * We have to delete the filter first since it references the
-         * sublayer. If we tried to delete the sublayer first, it would fail
-         * with FWP_ERR_IN_USE.
-         */
-        status = FwpmFilterDeleteByKey(gEngineHandle,
-                                       filterKey);
-        if (!NT_SUCCESS(status)) {
-            break;
-        }
-
-        status = FwpmSubLayerDeleteByKey(gEngineHandle,
-                                         sublayerKey);
-        if (!NT_SUCCESS(status)) {
-            break;
-        }
-
-        status = FwpmTransactionCommit(gEngineHandle);
-        if (!NT_SUCCESS(status)){
-            break;
-        }
-
-        inTransaction = FALSE;
-    } while (inTransaction);
-
-    if (inTransaction) {
-        FwpmTransactionAbort(gEngineHandle);
-    }
     return status;
 }
 
@@ -388,15 +385,6 @@ OvsTunnelRegisterDatagramDataCallouts(const GUID *layerKey,
         goto Exit;
     }
 
-    status = OvsTunnelAddFilter(L"Datagram-Data OVS Filter (Inbound)",
-                                L"address/port for UDP",
-                                configNewDestPort,
-                                FWP_DIRECTION_INBOUND,
-                                0,
-                                &OVS_TUNNEL_FILTER_KEY,
-                                layerKey,
-                                calloutKey);
-
 Exit:
 
     if (!NT_SUCCESS(status)){
@@ -487,8 +475,8 @@ Exit:
 VOID
 OvsTunnelUnregisterCallouts(VOID)
 {
-    OvsTunnelRemoveFilter(&OVS_TUNNEL_FILTER_KEY,
-                          &OVS_TUNNEL_SUBLAYER);
+    FwpmSubLayerDeleteByKey(gEngineHandle,
+                            &OVS_TUNNEL_SUBLAYER);
     FwpsCalloutUnregisterById(gCalloutIdV4);
     FwpmCalloutDeleteById(gEngineHandle, gCalloutIdV4);
     OvsTunnelEngineClose(&gEngineHandle);
@@ -499,6 +487,7 @@ OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject)  {
     UNREFERENCED_PARAMETER(driverObject);
 
+    OvsTunnelFilterThreadStop();
     OvsTunnelUnregisterCallouts();
     IoDeleteDevice(gDeviceObject);
 }
@@ -525,6 +514,11 @@ OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject)
         goto Exit;
     }
 
+    status = OvsTunnelFilterThreadInit();
+    if (!NT_SUCCESS(status)){
+        goto Exit;
+    }
+
     status = OvsTunnelRegisterCallouts(gDeviceObject);
 
 Exit:
@@ -541,3 +535,357 @@ Exit:
 
     return status;
 }
+
+NTSTATUS
+OvsTunnelAddFilterEx(UINT32 filterPort,
+                     UINT64 *filterID)
+{
+    return OvsTunnelAddFilter(L"Datagram-Data OVS Filter (Inbound)",
+                              L"address/port for UDP",
+                              (USHORT)filterPort,
+                              FWP_DIRECTION_INBOUND,
+                              0,
+                              NULL,
+                              &FWPM_LAYER_DATAGRAM_DATA_V4,
+                              &OVS_TUNNEL_CALLOUT_V4,
+                              filterID); }
+
+NTSTATUS
+OvsTunnelRemoveFilterEx(UINT64 filterID) {
+    NTSTATUS status = STATUS_SUCCESS;
+    BOOLEAN  error = TRUE;
+
+    do {
+        if (0 == filterID) {
+            OVS_LOG_INFO("No tunnel filter to remove.");
+            break;
+        }
+
+        status = FwpmFilterDeleteById(gEngineHandle, filterID);
+        if (!NT_SUCCESS(status)) {
+            OVS_LOG_ERROR("Failed to remove tunnel filter with ID: %x.",
+                status);
+            break;
+        }
+
+        error = FALSE;
+    } while (error);
+
+    return status;
+}
+
+NTSTATUS
+OvsTunnelFilterExecuteAction(POVS_TUNFLT_REQUEST request) {
+    NTSTATUS status = STATUS_SUCCESS;
+
+    switch (request->operation)
+    {
+    case OVS_TUN_FILTER_CREATE:
+        status = OvsTunnelAddFilterEx(request->port,
+                                      (UINT64*)request->context);
+        break;
+    case OVS_TUN_FILTER_DELETE:
+        status = OvsTunnelRemoveFilterEx(request->ID);
+        break;
+    default:
+        break;
+    }
+
+    return status;
+}
+
+POVS_TUNFLT_REQUEST
+OvsTunnelFilterRequestPop()
+{
+    POVS_TUNFLT_REQUEST request = NULL;
+
+    NdisAcquireSpinLock(&gTunnelRequestList.spinlock);
+
+    if (!IsListEmpty(&gTunnelRequestList.head)) {
+        request = (POVS_TUNFLT_REQUEST)
+            RemoveHeadList(&gTunnelRequestList.head);
+
+        gTunnelRequestList.numEntries--;
+    }
+
+    NdisReleaseSpinLock(&gTunnelRequestList.spinlock);
+
+    return request;
+}
+
+VOID
+OvsTunnelFilterRequestPush(POVS_TUNFLT_REQUEST request) {
+    NdisAcquireSpinLock(&gTunnelRequestList.spinlock);
+
+    InsertTailList(&gTunnelRequestList.head,
+                   &(request->entry));
+
+    gTunnelRequestList.numEntries++;
+
+    NdisReleaseSpinLock(&gTunnelRequestList.spinlock);
+}
+
+VOID
+OvsTunnelFilterRequestListCleanup()
+{
[EITAN]
No need to initialize.
Also, should we take the lock here?
[EITAN]
+    POVS_TUNFLT_REQUEST request = NULL;
+
+    while (NULL != (request = OvsTunnelFilterRequestPop())) {
+        OvsFreeMemory(request);
+        request = NULL;
+    }
+}
+
+NTSTATUS
+OvsTunnelFilterRequestListProcess()
+{
+    NTSTATUS            status = STATUS_SUCCESS;
+    POVS_TUNFLT_REQUEST request = NULL;
+    BOOLEAN             inTransaction = FALSE;
+
+    do
+    {
+        status = FwpmTransactionBegin(gEngineHandle, 0);
+        if (!NT_SUCCESS(status)) {
+            OVS_LOG_ERROR("Failed to start transaction, status: %x.", status);
+            break;
+        }
+        inTransaction = TRUE;
+
+        while (NULL != (request = OvsTunnelFilterRequestPop())) {
+            status = OvsTunnelFilterExecuteAction(request);
+
+            OvsFreeMemory(request);
+
+            if (!NT_SUCCESS(status)) {
+                break;
+            }
+        }
+        if (!NT_SUCCESS(status)) {
+            break;
+        }
+
+        status = FwpmTransactionCommit(gEngineHandle);
+        if (!NT_SUCCESS(status)){
+            OVS_LOG_ERROR("Failed to commit transaction, status: %x.", status);
+            break;
+        }
+
+        inTransaction = FALSE;
+    } while (inTransaction);
+
+    if (inTransaction) {
+        FwpmTransactionAbort(gEngineHandle);
+    }
+
+    return status;
+}
+
+/*
+ 
+*----------------------------------------------------------------------
+------
+ *  System thread routine that handles tunnel filter create/delete requests.
+ 
+*----------------------------------------------------------------------
+------
+ */
+_Use_decl_annotations_
+VOID
+OvsTunnelFilterThreadProc(PVOID context) {
+    NTSTATUS                   status = STATUS_SUCCESS;
+    POVS_TUNFLT_THREAD_CONTEXT threadCtx =
+        (POVS_TUNFLT_THREAD_CONTEXT)context;
+    BOOLEAN                    exit = FALSE;
+    PKEVENT                    eventArray[2] = { 0 };
+    ULONG                      count = 0;
+
+    OVS_LOG_INFO("Starting OVS Tunnel system thread.");
+
+    eventArray[0] = &threadCtx->stopEvent;
+    eventArray[1] = &threadCtx->requestEvent;
+    count = ARRAY_SIZE(eventArray);
+
+    do
+    {
+        status = KeWaitForMultipleObjects(count,
+                                          (PVOID)eventArray,
+                                          WaitAny,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          NULL,
+                                          NULL);
+        switch (status)
+        {
+        case STATUS_WAIT_1:
+        {
+            status = OvsTunnelFilterRequestListProcess();
+            if (!NT_SUCCESS(status)) {
+                exit = TRUE;
+            }
+            break;
+        }
+        default:
+            exit = TRUE;
+            break;
+        }
+    } while (!exit);
+
+    OvsTunnelFilterThreadCleanup();
+
+    OVS_LOG_INFO("Terminating OVS Tunnel system thread.");
+
+    PsTerminateSystemThread(STATUS_SUCCESS);
+};
+
+NTSTATUS
+OvsTunnelFilterThreadInit()
+{
+    NTSTATUS    status = STATUS_SUCCESS;
+    HANDLE      threadHandle = NULL;
+    BOOLEAN     error = TRUE;
+
+    do {
+        InitializeListHead(&gTunnelRequestList.head);
+        NdisAllocateSpinLock(&gTunnelRequestList.spinlock);
+        gTunnelRequestList.numEntries = 0;
+
+        KeInitializeEvent(&gTunnelThreadCtx.stopEvent,
+                          NotificationEvent,
+                          FALSE);
+        KeInitializeEvent(&gTunnelThreadCtx.requestEvent,
+                          SynchronizationEvent,
+                          FALSE);
+
+        status = PsCreateSystemThread(&threadHandle,
+                                      SYNCHRONIZE,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      OvsTunnelFilterThreadProc,
+                                      &gTunnelThreadCtx);
[EITAN]
CAN WE USE !NT_SUCCESS(status) HERE?
[EITAN]
+        if (status) {
+            OVS_LOG_ERROR("Failed to create tunnel thread, status: %x.",
+                          status);
+            break;
+        }
+
+        ObReferenceObjectByHandle(threadHandle,
+                                  SYNCHRONIZE,
+                                  NULL,
+                                  KernelMode,
+                                  &gTunnelThreadCtx.threadObject,
+                                  NULL);
+        ZwClose(threadHandle);
+        threadHandle = NULL;
+
+        error = FALSE;
+    } while (error);
+
+    if (error) {
+        NdisFreeSpinLock(&gTunnelRequestList.spinlock);
+    }
+
+    return status;
+}
+
+VOID
+OvsTunnelFilterThreadCleanup()
+{
+    OvsTunnelFilterRequestListCleanup();
+    NdisFreeSpinLock(&gTunnelRequestList.spinlock);
+}
+
+VOID
+OvsTunnelFilterThreadStop()
+{
+    /* Signal stop thread event. */
+    KeSetEvent(&gTunnelThreadCtx.stopEvent, IO_NO_INCREMENT, FALSE);
+
+    /* Wait for the tunnel thread to finish. */
+    KeWaitForSingleObject(gTunnelThreadCtx.threadObject,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    ObDereferenceObject(gTunnelThreadCtx.threadObject);
+}
+
+VOID
+OvsTunnelFilterQueueRequest(UINT16 remotePort,
+                            UINT64 *filterID,
+                            OVS_TUNFLT_OPERATION operation) {
+    POVS_TUNFLT_REQUEST request = NULL;
+    BOOLEAN             error = TRUE;
+
+    do {
+        if (NULL == filterID) {
+            OVS_LOG_ERROR("Invalid request.");
+            break;
+        }
+
+        request = (POVS_TUNFLT_REQUEST)OvsAllocateMemory(sizeof(*request));
+        if (NULL == request) {
+            OVS_LOG_ERROR("Failed to allocate list item.");
+            break;
+        }
+
+        request->port = remotePort;
+        request->operation = operation;
+        request->ID = *filterID;
+        request->context = (PVOID)filterID;
+
+        OvsTunnelFilterRequestPush(request);
+
+        KeSetEvent(&gTunnelThreadCtx.requestEvent, IO_NO_INCREMENT, 
+ FALSE);
+
+        error = FALSE;
+    } while (error);
+
+    if (error) {
+        if (request) {
+            OvsFreeMemory(request);
+            request = NULL;
+        }
+    }
+}
+
+/*
+ *
+-----------------------------------------------------------------------
+---
+ *  This function adds a new WFP filter for the received port and 
+returns the
+ *  ID of the created WFP filter.
+ *
+ *  Note:
+ *  All necessary calls to the WFP filtering engine must be running at 
+IRQL =
+ *  PASSIVE_LEVEL. Because the function is called at IRQL = 
+DISPATCH_LEVEL,
+ *  we register an OVS_TUN_FILTER_CREATE request that will be processed 
+by
+ *  the thread routine at IRQL = PASSIVE_LEVEL.
+ *
+-----------------------------------------------------------------------
+---
+ */
+VOID
+OvsTunelFilterCreate(UINT16 filterPort,
+                     UINT64 *filterID)
+{
+    OvsTunnelFilterQueueRequest(filterPort, filterID, 
+OVS_TUN_FILTER_CREATE); }
+
+/*
+ *
+-----------------------------------------------------------------------
+---
+ *  This function removes a WFP filter using the received filter ID.
+ *
+ *  Note:
+ *  All necessary calls to the WFP filtering engine must be running at 
+IRQL =
+ *  PASSIVE_LEVEL. Because the function is called at IRQL = 
+DISPATCH_LEVEL,
+ *  we register an OVS_TUN_FILTER_DELETE request that will be processed 
+by
+ *  the thread routine at IRQL = PASSIVE_LEVEL.
+ *
+-----------------------------------------------------------------------
+---
+ */
+VOID
+OvsTunelFilterDelete(UINT64 filterID)
+{
+    OvsTunnelFilterQueueRequest(0, &filterID, OVS_TUN_FILTER_DELETE); }
\ No newline at end of file
diff --git a/datapath-windows/ovsext/TunnelIntf.h 
b/datapath-windows/ovsext/TunnelIntf.h
index b2bba30..d304f49 100644
--- a/datapath-windows/ovsext/TunnelIntf.h
+++ b/datapath-windows/ovsext/TunnelIntf.h
@@ -30,4 +30,8 @@ VOID OvsTunnelAddSystemProvider(HANDLE handle);
 
 VOID OvsTunnelRemoveSystemProvider(HANDLE handle);
 
+VOID OvsTunelFilterCreate(UINT16 filterPort, UINT64 *filterID);
+
+VOID OvsTunelFilterDelete(UINT64 filterID);
+
 #endif /* __TUNNEL_INTF_H_ */
diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c 
index c9dfaea..968c112 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -1011,7 +1011,7 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
 
     switch(vport->ovsType) {
     case OVS_VPORT_TYPE_VXLAN:
-        ASSERT(switchContext->vxlanVport == NULL);
+        //ASSERT(switchContext->vxlanVport == NULL);
         switchContext->vxlanVport = vport;
         switchContext->numNonHvVports++;
         break;
@@ -1908,7 +1908,7 @@ Cleanup:
 
 /*
  * --------------------------------------------------------------------------
- *  Command Handler for 'OVS_VPORT_CMD_NEW'.
+ *  Command Handler for 'OVS_VPORT_CMD_GET'.
  *
  *  The function handles the initial call to setup the dump state, as well as
  *  subsequent calls to continue dumping data.
@@ -2033,8 +2033,8 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT 
usrParamsCtx,
     } else {
         ASSERT(OvsIsTunnelVportType(portType) ||
                (portType == OVS_VPORT_TYPE_INTERNAL && isBridgeInternal));
-        ASSERT(OvsGetTunnelVport(gOvsSwitchContext, portType) == NULL ||
-               !OvsIsTunnelVportType(portType));
+        //ASSERT(OvsGetTunnelVport(gOvsSwitchContext, portType) == NULL ||
+        //       !OvsIsTunnelVportType(portType));
 
         vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
         if (vport == NULL) {
@@ -2044,7 +2044,10 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT 
usrParamsCtx,
         vportAllocated = TRUE;
 
         if (OvsIsTunnelVportType(portType)) {
-            status = OvsInitTunnelVport(vport, portType, VXLAN_UDP_PORT);
+            PNL_ATTR attr = 
NlAttrFindNested(vportAttrs[OVS_VPORT_ATTR_OPTIONS],
+                                             OVS_TUNNEL_ATTR_DST_PORT);
+            UINT16 udpPortDest = NlAttrGetU16(attr);
+            status = OvsInitTunnelVport(vport, portType, udpPortDest);
             nlError = NlMapStatusToNlErr(status);
         } else {
             OvsInitBridgeInternalVport(vport);
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c 
index 1ce5af2..8981bf5 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -49,6 +49,39 @@
 /* Move to a header file */
 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
 
+BOOLEAN
+OvsIsTunnelFilterCreated(POVS_SWITCH_CONTEXT switchContext,
+                         UINT16 udpPortDest) {
+    for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {
+        PLIST_ENTRY head, link, next;
+
+        head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
+        LIST_FORALL_SAFE(head, link, next) {
+            POVS_VPORT_ENTRY vport = NULL;
+            POVS_VXLAN_VPORT vxlanPort = NULL;
+            vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
+            vxlanPort = (POVS_VXLAN_VPORT)vport->priv;
+            if (vxlanPort) {
+                if ((udpPortDest == vxlanPort->dstPort) &&
+                    (0 != vxlanPort->filterID)) {
+                    /*
+                     * VXLAN destination port matching is not enough to decide
+                     * if the WFP filter was created or not, because the newly
+                     * allocated VXLAN vport is already added to the
+                     * portNoHashArray in InitOvsVportCommon function. If the
+                     * filterID of the VXLAN vport is zero it means that the
+                     * WFP filter is not created yet.
+                     */
+                    return TRUE;
+                }
+            }
+        }
+    }
+
+    return FALSE;
+}
+
 /*
  * udpDestPort: the vxlan is set as payload to a udp frame. If the destination
  * port of an udp frame is udpDestPort, we understand it to be vxlan.
@@ -57,7 +90,7 @@ NTSTATUS
 OvsInitVxlanTunnel(POVS_VPORT_ENTRY vport,
                    UINT16 udpDestPort)
 {
-    POVS_VXLAN_VPORT vxlanPort;
+    POVS_VXLAN_VPORT vxlanPort = NULL;
 
     vxlanPort = OvsAllocateMemory(sizeof (*vxlanPort));
     if (vxlanPort == NULL) {
@@ -66,14 +99,12 @@ OvsInitVxlanTunnel(POVS_VPORT_ENTRY vport,
 
     RtlZeroMemory(vxlanPort, sizeof(*vxlanPort));
     vxlanPort->dstPort = udpDestPort;
-    /*
-     * since we are installing the WFP filter before the port is created
-     * We need to check if it is the same number
-     * XXX should be removed later
-     */
-    ASSERT(vxlanPort->dstPort == VXLAN_UDP_PORT);
     vport->priv = (PVOID)vxlanPort;
 
+    if (!OvsIsTunnelFilterCreated(gOvsSwitchContext, udpDestPort)) {
+        OvsTunelFilterCreate(udpDestPort, &vxlanPort->filterID);
+    }
+
     return STATUS_SUCCESS;
 }
 
@@ -81,11 +112,16 @@ OvsInitVxlanTunnel(POVS_VPORT_ENTRY vport,  VOID  
OvsCleanupVxlanTunnel(POVS_VPORT_ENTRY vport)  {
+    POVS_VXLAN_VPORT vxlanPort = NULL;
+
     if (vport->ovsType != OVS_VPORT_TYPE_VXLAN ||
         vport->priv == NULL) {
         return;
     }
 
+    vxlanPort = (POVS_VXLAN_VPORT)vport->priv;
+    OvsTunelFilterDelete(vxlanPort->filterID);
+
     OvsFreeMemory(vport->priv);
     vport->priv = NULL;
 }
@@ -474,9 +510,6 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet,
             break;
         }
 
-        /* XXX Should be tested against the dynamic port # in the VXLAN vport 
*/
-        ASSERT(udp->dest == RtlUshortByteSwap(VXLAN_UDP_PORT));
-
         VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet,
                                                     sizeof(*VxlanHeader),
                                                     layers.l7Offset, diff 
--git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h index 
d84796d..ade6b0c 100644
--- a/datapath-windows/ovsext/Vxlan.h
+++ b/datapath-windows/ovsext/Vxlan.h
@@ -24,6 +24,7 @@ typedef struct _OVS_VXLAN_VPORT {
     UINT64 outPkts;
     UINT64 slowInPkts;
     UINT64 slowOutPkts;
+    UINT64 filterID;
     /*
      * To be filled
      */
@@ -75,7 +76,6 @@ OvsGetVxlanTunHdrSize(VOID)
            sizeof (VXLANHdr);
 }
 
-#define VXLAN_UDP_PORT 4789
 #define VXLAN_UDP_PORT_NBO 0xB512
 
 #endif /* __VXLAN_H_ */
--
1.9.0.msysgit.0
_______________________________________________
dev mailing list
[email protected]
https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailman_listinfo_dev&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=VmREdmxxsERc3TdRTLuqj-tDd42IJUEuvcXW-vWM5Mc&s=6BDEpe4n5fGyUqywRmbJBS4fqL991fUnz_TLwPPFSts&e=
 
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to