This patch was enforced by the WHCK logo testing. In order to pass the Windows Filtering Platform tests we need to add a persistent system provider.
Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> Reported-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> Reported-at: https://github.com/openvswitch/ovs-issues/issues/65 Acked-by: Nithin Raju <nit...@vmware.com> --- datapath-windows/ovsext/Datapath.c | 16 +++ datapath-windows/ovsext/Debug.h | 1 + datapath-windows/ovsext/Switch.c | 1 - datapath-windows/ovsext/Switch.h | 1 + datapath-windows/ovsext/TunnelFilter.c | 173 ++++++++++++++++++++++++++++++--- datapath-windows/ovsext/TunnelIntf.h | 8 ++ 6 files changed, 183 insertions(+), 17 deletions(-) diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c index a818ab9..13bc20c 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -353,19 +353,35 @@ PNDIS_SPIN_LOCK gOvsCtrlLock; VOID OvsInit() { + HANDLE handle = NULL; + gOvsCtrlLock = &ovsCtrlLockObj; NdisAllocateSpinLock(gOvsCtrlLock); OvsInitEventQueue(); + + OvsTunnelEngineOpen(&handle); + if (handle) { + OvsTunnelAddSystemProvider(handle); + } + OvsTunnelEngineClose(&handle); } VOID OvsCleanup() { + HANDLE handle = NULL; + OvsCleanupEventQueue(); if (gOvsCtrlLock) { NdisFreeSpinLock(gOvsCtrlLock); gOvsCtrlLock = NULL; } + + OvsTunnelEngineOpen(&handle); + if (handle) { + OvsTunnelRemoveSystemProvider(handle); + } + OvsTunnelEngineClose(&handle); } VOID diff --git a/datapath-windows/ovsext/Debug.h b/datapath-windows/ovsext/Debug.h index cc9787a..a0da5eb 100644 --- a/datapath-windows/ovsext/Debug.h +++ b/datapath-windows/ovsext/Debug.h @@ -39,6 +39,7 @@ #define OVS_DBG_BUFMGMT BIT32(19) #define OVS_DBG_OTHERS BIT32(21) #define OVS_DBG_NETLINK BIT32(22) +#define OVS_DBG_TUNFLT BIT32(23) #define OVS_DBG_RESERVED BIT32(31) //Please add above OVS_DBG_RESERVED. diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c index 2b68037..a228d8e 100644 --- a/datapath-windows/ovsext/Switch.c +++ b/datapath-windows/ovsext/Switch.c @@ -26,7 +26,6 @@ #include "Event.h" #include "Flow.h" #include "IpHelper.h" -#include "TunnelIntf.h" #include "Oid.h" #ifdef OVS_DBG_MOD diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h index 61f74c4..7960072 100644 --- a/datapath-windows/ovsext/Switch.h +++ b/datapath-windows/ovsext/Switch.h @@ -23,6 +23,7 @@ #include "NetProto.h" #include "BufferMgmt.h" +#include "TunnelIntf.h" #define OVS_MAX_VPORT_ARRAY_SIZE 1024 #define OVS_MAX_PID_ARRAY_SIZE 1024 diff --git a/datapath-windows/ovsext/TunnelFilter.c b/datapath-windows/ovsext/TunnelFilter.c index 7250c24..e0adc37 100644 --- a/datapath-windows/ovsext/TunnelFilter.c +++ b/datapath-windows/ovsext/TunnelFilter.c @@ -18,6 +18,11 @@ #pragma warning(push) #pragma warning(disable:4201) // unnamed struct/union +#ifdef OVS_DBG_MOD +#undef OVS_DBG_MOD +#endif +#define OVS_DBG_MOD OVS_DBG_TUNFLT +#include "Debug.h" #include <fwpsk.h> @@ -40,6 +45,23 @@ #define INITGUID #include <guiddef.h> +/* Infinite timeout */ +#define INFINITE 0xFFFFFFFF + +/* + * The provider name should always match the provider string from the install + * file. + */ +#define OVS_TUNNEL_PROVIDER_NAME L"Open vSwitch" + +/* + * The provider description should always contain the OVS service description + * string from the install file. + */ +#define OVS_TUNNEL_PROVIDER_DESC L"Open vSwitch Extension tunnel provider" + +/* 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; @@ -65,6 +87,15 @@ DEFINE_GUID( 0x94, 0xc9, 0xf0, 0xd5, 0x25, 0xbb, 0xc1, 0x69 ); +/* 6fc957d7-14e7-47c7-812b-4668be994ba1 */ +DEFINE_GUID( + OVS_TUNNEL_PROVIDER_KEY, + 0x6fc957d7, + 0x14e7, + 0x47c7, + 0x81, 0x2b, 0x46, 0x68, 0xbe, 0x99, 0x4b, 0xa1 + ); + /* bfd4814c-9650-4de3-a536-1eedb9e9ba6a */ DEFINE_GUID( OVS_TUNNEL_FILTER_KEY, @@ -79,13 +110,128 @@ DEFINE_GUID( */ PDEVICE_OBJECT gDeviceObject; -HANDLE gEngineHandle; +HANDLE gEngineHandle = NULL; UINT32 gCalloutIdV4; /* Callout driver implementation */ NTSTATUS +OvsTunnelEngineOpen(HANDLE *handle) +{ + NTSTATUS status = STATUS_SUCCESS; + FWPM_SESSION session = { 0 }; + + /* The session name isn't required but may be useful for diagnostics. */ + session.displayData.name = OVS_TUNNEL_SESSION_NAME; + /* + * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT + * errors while waiting to acquire the transaction lock. + */ + session.txnWaitTimeoutInMSec = INFINITE; + session.flags = FWPM_SESSION_FLAG_DYNAMIC; + + /* The authentication service should always be RPC_C_AUTHN_DEFAULT. */ + status = FwpmEngineOpen(NULL, + RPC_C_AUTHN_DEFAULT, + NULL, + &session, + handle); + if (!NT_SUCCESS(status)) { + OVS_LOG_ERROR("Fail to open filtering engine session, status: %x.", + status); + } + + return status; +} + +VOID +OvsTunnelEngineClose(HANDLE *handle) +{ + if (*handle) { + FwpmEngineClose(*handle); + *handle = NULL; + } +} + +VOID +OvsTunnelAddSystemProvider(HANDLE handle) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN inTransaction = FALSE; + FWPM_PROVIDER provider = { 0 }; + + do { + status = FwpmTransactionBegin(handle, 0); + if (!NT_SUCCESS(status)) { + break; + } + inTransaction = TRUE; + + memset(&provider, 0, sizeof(provider)); + provider.providerKey = OVS_TUNNEL_PROVIDER_KEY; + provider.displayData.name = OVS_TUNNEL_PROVIDER_NAME; + provider.displayData.description = OVS_TUNNEL_PROVIDER_DESC; + /* + * Since we always want the provider to be present, it's easiest to add + * it as persistent object during driver load. + */ + provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT; + + status = FwpmProviderAdd(handle, + &provider, + NULL); + if (!NT_SUCCESS(status)) { + OVS_LOG_ERROR("Fail to add WFP provider, status: %x.", status); + break; + } + + status = FwpmTransactionCommit(handle); + if (!NT_SUCCESS(status)) { + break; + } + + inTransaction = FALSE; + } while (inTransaction); + + if (inTransaction){ + FwpmTransactionAbort(handle); + } +} + +VOID +OvsTunnelRemoveSystemProvider(HANDLE handle) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN inTransaction = FALSE; + + do { + status = FwpmTransactionBegin(handle, 0); + if (!NT_SUCCESS(status)) { + break; + } + inTransaction = TRUE; + + status = FwpmProviderDeleteByKey(handle, + &OVS_TUNNEL_PROVIDER_KEY); + if (!NT_SUCCESS(status)) { + break; + } + + status = FwpmTransactionCommit(handle); + if (!NT_SUCCESS(status)) { + break; + } + + inTransaction = FALSE; + } while (inTransaction); + + if (inTransaction){ + FwpmTransactionAbort(handle); + } +} + +NTSTATUS OvsTunnelAddFilter(PWSTR filterName, const PWSTR filterDesc, USHORT remotePort, @@ -278,16 +424,7 @@ OvsTunnelRegisterCallouts(VOID *deviceObject) BOOLEAN engineOpened = FALSE; BOOLEAN inTransaction = FALSE; - FWPM_SESSION session = {0}; - - session.flags = FWPM_SESSION_FLAG_DYNAMIC; - - status = FwpmEngineOpen(NULL, - RPC_C_AUTHN_WINNT, - NULL, - &session, - &gEngineHandle); - + status = OvsTunnelEngineOpen(&gEngineHandle); if (!NT_SUCCESS(status)) { goto Exit; } @@ -307,13 +444,18 @@ OvsTunnelRegisterCallouts(VOID *deviceObject) L"Sub-Layer for use by Datagram-Data OVS callouts"; OvsTunnelSubLayer.flags = 0; OvsTunnelSubLayer.weight = FWP_EMPTY; /* auto-weight */ + /* + * Link all objects to the tunnel provider. When multiple providers are + * installed on a computer, this makes it easy to determine who added what. + */ + OvsTunnelSubLayer.providerKey = (GUID*) &OVS_TUNNEL_PROVIDER_KEY; status = FwpmSubLayerAdd(gEngineHandle, &OvsTunnelSubLayer, NULL); if (!NT_SUCCESS(status)) { goto Exit; } - // In order to use this callout a socket must be opened + /* In order to use this callout a socket must be opened. */ status = OvsTunnelRegisterDatagramDataCallouts(&FWPM_LAYER_DATAGRAM_DATA_V4, &OVS_TUNNEL_CALLOUT_V4, deviceObject, @@ -335,8 +477,7 @@ Exit: FwpmTransactionAbort(gEngineHandle); } if (engineOpened) { - FwpmEngineClose(gEngineHandle); - gEngineHandle = NULL; + OvsTunnelEngineClose(&gEngineHandle); } } @@ -348,9 +489,9 @@ OvsTunnelUnregisterCallouts(VOID) { OvsTunnelRemoveFilter(&OVS_TUNNEL_FILTER_KEY, &OVS_TUNNEL_SUBLAYER); - FwpmEngineClose(gEngineHandle); - gEngineHandle = NULL; FwpsCalloutUnregisterById(gCalloutIdV4); + FwpmCalloutDeleteById(gEngineHandle, gCalloutIdV4); + OvsTunnelEngineClose(&gEngineHandle); } VOID diff --git a/datapath-windows/ovsext/TunnelIntf.h b/datapath-windows/ovsext/TunnelIntf.h index c622720..b2bba30 100644 --- a/datapath-windows/ovsext/TunnelIntf.h +++ b/datapath-windows/ovsext/TunnelIntf.h @@ -22,4 +22,12 @@ NTSTATUS OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject); VOID OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject); +NTSTATUS OvsTunnelEngineOpen(HANDLE *handle); + +VOID OvsTunnelEngineClose(HANDLE *handle); + +VOID OvsTunnelAddSystemProvider(HANDLE handle); + +VOID OvsTunnelRemoveSystemProvider(HANDLE handle); + #endif /* __TUNNEL_INTF_H_ */ -- 1.9.0.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev