datapath-windows: Updated WFP system provider handling
authorSorin Vinturis <svinturis@cloudbasesolutions.com>
Tue, 24 Mar 2015 14:53:11 +0000 (14:53 +0000)
committerBen Pfaff <blp@nicira.com>
Tue, 24 Mar 2015 15:37:27 +0000 (08:37 -0700)
If the Base Filtering Engine (BFE) is not started, the WFP system
provider failed to be added because no session to the engine could
be acquired.

The solution for this was to registered a BFE notification callback
that is called whenever the BFE's state changes. Only if the BFE's
state is running the WFP system provider is added.

Signed-off-by: Sorin Vinturis <svinturis@cloudbasesolutions.com>
Reported-by: Sorin Vinturis <svinturis@cloudbasesolutions.com>
Reported-at: https://github.com/openvswitch/ovs-issues/issues/65
Acked-by: Eitan Eliahu <eliahue@vmware.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
datapath-windows/ovsext/Datapath.c
datapath-windows/ovsext/TunnelFilter.c
datapath-windows/ovsext/TunnelIntf.h

index 8eb13f1..c6fe89e 100644 (file)
@@ -353,35 +353,19 @@ 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
@@ -448,6 +432,8 @@ OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle)
         if (ovsExt) {
             ovsExt->numberOpenInstance = 0;
         }
+    } else {
+        OvsRegisterSystemProvider((PVOID)gOvsDeviceObject);
     }
 
     OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject);
@@ -471,6 +457,8 @@ OvsDeleteDeviceObject()
         NdisDeregisterDeviceEx(gOvsDeviceHandle);
         gOvsDeviceHandle = NULL;
         gOvsDeviceObject = NULL;
+
+        OvsUnregisterSystemProvider();
     }
 }
 
index e0adc37..4b879c0 100644 (file)
@@ -111,6 +111,7 @@ DEFINE_GUID(
 PDEVICE_OBJECT gDeviceObject;
 
 HANDLE gEngineHandle = NULL;
+HANDLE gBfeSubscriptionHandle = NULL;
 UINT32 gCalloutIdV4;
 
 
@@ -173,17 +174,20 @@ OvsTunnelAddSystemProvider(HANDLE handle)
         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.
-        */
+         * 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;
+            if (STATUS_FWP_ALREADY_EXISTS != status) {
+                OVS_LOG_ERROR("Failed to add WFP provider, status: %x.",
+                              status);
+                break;
+            }
         }
 
         status = FwpmTransactionCommit(handle);
@@ -541,3 +545,88 @@ Exit:
 
     return status;
 }
+
+VOID NTAPI
+OvsBfeStateChangeCallback(PVOID context,
+                          FWPM_SERVICE_STATE bfeState)
+{
+    HANDLE handle = NULL;
+
+    DBG_UNREFERENCED_PARAMETER(context);
+
+    if (FWPM_SERVICE_RUNNING == bfeState) {
+        OvsTunnelEngineOpen(&handle);
+        if (handle) {
+            OvsTunnelAddSystemProvider(handle);
+        }
+        OvsTunnelEngineClose(&handle);
+    }
+}
+
+NTSTATUS
+OvsSubscribeBfeStateChanges(PVOID deviceObject)
+{
+    NTSTATUS status = STATUS_SUCCESS;
+
+    if (!gBfeSubscriptionHandle) {
+        status = FwpmBfeStateSubscribeChanges(deviceObject,
+                                              OvsBfeStateChangeCallback,
+                                              NULL,
+                                              &gBfeSubscriptionHandle);
+        if (!NT_SUCCESS(status)) {
+            OVS_LOG_ERROR(
+                "Failed to open subscribe BFE state change callback, status: %x.",
+                status);
+        }
+    }
+
+    return status;
+}
+
+VOID
+OvsUnsubscribeBfeStateChanges()
+{
+    NTSTATUS status = STATUS_SUCCESS;
+
+    if (gBfeSubscriptionHandle) {
+        status = FwpmBfeStateUnsubscribeChanges(gBfeSubscriptionHandle);
+        if (!NT_SUCCESS(status)) {
+            OVS_LOG_ERROR(
+                "Failed to open unsubscribe BFE state change callback, status: %x.",
+                status);
+        }
+        gBfeSubscriptionHandle = NULL;
+    }
+}
+
+VOID OvsRegisterSystemProvider(PVOID deviceObject)
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    HANDLE handle = NULL;
+
+    status = OvsSubscribeBfeStateChanges(deviceObject);
+    if (NT_SUCCESS(status)) {
+        if (FWPM_SERVICE_RUNNING == FwpmBfeStateGet()) {
+            OvsTunnelEngineOpen(&handle);
+            if (handle) {
+                OvsTunnelAddSystemProvider(handle);
+            }
+            OvsTunnelEngineClose(&handle);
+
+            OvsUnsubscribeBfeStateChanges();
+        }
+    }
+}
+
+VOID OvsUnregisterSystemProvider()
+{
+    HANDLE handle = NULL;
+
+    OvsTunnelEngineOpen(&handle);
+    if (handle) {
+        OvsTunnelRemoveSystemProvider(handle);
+    }
+    OvsTunnelEngineClose(&handle);
+
+    OvsUnsubscribeBfeStateChanges();
+}
index b2bba30..728a53f 100644 (file)
@@ -22,12 +22,8 @@ NTSTATUS OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject);
 
 VOID OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject);
 
-NTSTATUS OvsTunnelEngineOpen(HANDLE *handle);
+VOID OvsRegisterSystemProvider(PVOID deviceObject);
 
-VOID OvsTunnelEngineClose(HANDLE *handle);
-
-VOID OvsTunnelAddSystemProvider(HANDLE handle);
-
-VOID OvsTunnelRemoveSystemProvider(HANDLE handle);
+VOID OvsUnregisterSystemProvider();
 
 #endif /* __TUNNEL_INTF_H_ */