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://github.com/openvswitch/ovs-issues/issues/66 --- 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() +{ + 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); + 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] http://openvswitch.org/mailman/listinfo/dev
