From patchwork Thu Sep 3 11:54:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sorin Vinturis X-Patchwork-Id: 514012 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 5048014028F for ; Thu, 3 Sep 2015 21:55:31 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 48E9A10AF9; Thu, 3 Sep 2015 04:55:30 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 222D910AF7 for ; Thu, 3 Sep 2015 04:55:28 -0700 (PDT) Received: from bar4.cudamail.com (bar2 [192.168.15.2]) by mx3v1.cudamail.com (Postfix) with ESMTP id 826D761932A for ; Thu, 3 Sep 2015 05:55:27 -0600 (MDT) X-ASG-Debug-ID: 1441281322-03dc211ad646aa60001-byXFYA Received: from mx3-pf2.cudamail.com ([192.168.14.1]) by bar4.cudamail.com with ESMTP id xaENpZMuaneDz74G (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 03 Sep 2015 05:55:22 -0600 (MDT) X-Barracuda-Envelope-From: svinturis@cloudbasesolutions.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.1 Received: from unknown (HELO cbssmtp1.cloudbase.local) (91.232.152.5) by mx3-pf2.cudamail.com with SMTP; 3 Sep 2015 11:55:20 -0000 Received-SPF: pass (mx3-pf2.cudamail.com: SPF record at cloudbasesolutions.com designates 91.232.152.5 as permitted sender) X-Barracuda-Apparent-Source-IP: 91.232.152.5 X-Barracuda-RBL-IP: 91.232.152.5 Received: from localhost (localhost [127.0.0.1]) by cbssmtp1.cloudbase.local (Postfix) with ESMTP id A71744245A for ; Thu, 3 Sep 2015 14:55:19 +0300 (EEST) X-Virus-Scanned: amavisd-new at cloudbasesolutions.com Received: from cbssmtp1.cloudbase.local ([127.0.0.1]) by localhost (cbssmtp1.cloudbase.local [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ju9DUCp_SMoa for ; Thu, 3 Sep 2015 14:54:48 +0300 (EEST) Received: from CBSEX1.cloudbase.local (unknown [10.77.78.3]) by cbssmtp1.cloudbase.local (Postfix) with ESMTP id AD1F742458 for ; Thu, 3 Sep 2015 14:54:48 +0300 (EEST) Received: from CBSEX1.cloudbase.local ([10.77.78.3]) by CBSEX1.cloudbase.local ([10.77.78.3]) with mapi id 14.03.0224.002; Thu, 3 Sep 2015 13:54:48 +0200 X-CudaMail-Envelope-Sender: svinturis@cloudbasesolutions.com From: Sorin Vinturis To: "dev@openvswitch.org" X-CudaMail-MID: CM-V2-902006687 X-CudaMail-DTE: 090315 X-CudaMail-Originating-IP: 91.232.152.5 Thread-Topic: [PATCH] datapath-windows: IpHelper support for multiple adapter instances X-ASG-Orig-Subj: [##CM-V2-902006687##][PATCH] datapath-windows: IpHelper support for multiple adapter instances Thread-Index: AQHQ5j9VNP5OoccC2UiFHLKqR7kOGQ== Date: Thu, 3 Sep 2015 11:54:48 +0000 Message-ID: <1441115375-11520-1-git-send-email-svinturis@cloudbasesolutions.com> Accept-Language: en-US, it-IT Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.77.78.1] MIME-Version: 1.0 X-GBUdb-Analysis: 0, 91.232.152.5, Ugly c=0.237282 p=-0.4 Source Normal X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.14.1] X-Barracuda-Start-Time: 1441281322 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=3.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=3.0 tests=RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.22188 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS Subject: [ovs-dev] [PATCH] datapath-windows: IpHelper support for multiple adapter instances X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@openvswitch.org Sender: "dev" Added support for multiple internal adapter instances to the IpHelper module. Signed-off-by: Sorin Vinturis Reported-by: Sorin Vinturis Reported-at: https://github.com/openvswitch/ovs-issues/issues/101 --- datapath-windows/ovsext/IpHelper.c | 648 ++++++++++++++++++++++++++----------- datapath-windows/ovsext/IpHelper.h | 11 +- datapath-windows/ovsext/Vport.c | 4 +- 3 files changed, 477 insertions(+), 186 deletions(-) diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c index de0d457..964b675 100644 --- a/datapath-windows/ovsext/IpHelper.c +++ b/datapath-windows/ovsext/IpHelper.c @@ -26,28 +26,45 @@ #include "Debug.h" /* - * Fow now, we assume only one internal adapter + * IpHelper supports multiple internal adapters. */ KSTART_ROUTINE OvsStartIpHelper; +/* Contains the entries of internal adapter objects. */ +static LIST_ENTRY ovsInstanceList; + +/* Passive-level lock used to protect the internal adapter object list. */ +static ERESOURCE ovsInstanceListLock; + /* + * This structure is used to define each adapter instance. + * + * Note: * Only when the internal IP is configured and virtual * internal port is connected, the IP helper request can be * queued. + * + * We only keep internal IP for reference, it will not be used for determining + * SRC IP of the Tunnel. + * + * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the + * route manipulation functions, i.e. GetBestRoute, to work. */ -static BOOLEAN ovsInternalIPConfigured; -static UINT32 ovsInternalPortNo; -static GUID ovsInternalNetCfgId; -static MIB_IF_ROW2 ovsInternalRow; -static MIB_IPINTERFACE_ROW ovsInternalIPRow; - -/* we only keep one internal IP for reference, it will not be used for - * determining SRC IP of Tunnel - */ -static UINT32 ovsInternalIP; +typedef struct _OVS_IPHELPER_INSTANCE +{ + LIST_ENTRY link; + + BOOLEAN isIpConfigured; + UINT32 portNo; + GUID netCfgId; + MIB_IF_ROW2 internalRow; + MIB_IPINTERFACE_ROW internalIPRow; + UINT32 ipAddress; + ERESOURCE lock; +} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE; /* * FWD_ENTRY --------> IPFORWARD_ENTRY @@ -85,6 +102,9 @@ static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr); static VOID OvsCleanupIpHelperRequestList(VOID); static VOID OvsCleanupFwdTable(VOID); static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn); +static POVS_IPHELPER_INSTANCE OvsIpHelperAllocateInstance( + POVS_IP_HELPER_REQUEST request); +static VOID OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance); static VOID OvsDumpIfRow(PMIB_IF_ROW2 ifRow) @@ -325,30 +345,53 @@ OvsDumpRoute(const SOCKADDR_INET *sourceAddress, NTSTATUS -OvsGetRoute(NET_LUID interfaceLuid, - const SOCKADDR_INET *destinationAddress, +OvsGetRoute(SOCKADDR_INET *destinationAddress, PMIB_IPFORWARD_ROW2 route, - SOCKADDR_INET *sourceAddress) + SOCKADDR_INET *sourceAddress, + POVS_IPHELPER_INSTANCE *instance) { - NTSTATUS status; + NTSTATUS status = STATUS_NETWORK_UNREACHABLE; + NTSTATUS result = STATUS_SUCCESS; + PLIST_ENTRY head, link, next; if (destinationAddress == NULL || route == NULL) { return STATUS_INVALID_PARAMETER; } - status = GetBestRoute2(&interfaceLuid, 0, - NULL, destinationAddress, - 0, route, sourceAddress); + ExAcquireResourceSharedLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + ULONG minMetric = (ULONG)-1; + SOCKADDR_INET crtSrcAddr = { 0 }; + MIB_IPFORWARD_ROW2 crtRoute = { 0 }; + POVS_IPHELPER_INSTANCE crtInstance = NULL; - if (status != STATUS_SUCCESS) { - UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr; - OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x", - ipAddr & 0xff, (ipAddr >> 8) & 0xff, - (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); - return status; + crtInstance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceSharedLite(&crtInstance->lock, TRUE); + result = GetBestRoute2(&crtInstance->internalRow.InterfaceLuid, 0, + NULL, destinationAddress, 0, &crtRoute, + &crtSrcAddr); + if (result != STATUS_SUCCESS) { + ExReleaseResourceLite(&crtInstance->lock); + continue; + } + + if (minMetric > crtRoute.Metric) { + minMetric = crtRoute.Metric; + + RtlCopyMemory(sourceAddress, &crtSrcAddr, sizeof(*sourceAddress)); + RtlCopyMemory(route, &crtRoute, sizeof(*route)); + *instance = crtInstance; + + status = STATUS_SUCCESS; + } + ExReleaseResourceLite(&crtInstance->lock); } + ExReleaseResourceLite(&ovsInstanceListLock); OvsDumpRoute(sourceAddress, destinationAddress, route); + return status; } @@ -358,8 +401,8 @@ OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh) UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Neigh: %d.%d.%d.%d", - ipAddr & 0xff, (ipAddr >> 8) & 0xff, - (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); + ipAddr & 0xff, (ipAddr >> 8) & 0xff, + (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", ipNeigh->PhysicalAddress[0], ipNeigh->PhysicalAddress[1], @@ -421,7 +464,8 @@ OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) NTSTATUS -OvsGetOrResolveIPNeigh(UINT32 ipAddr, +OvsGetOrResolveIPNeigh(MIB_IF_ROW2 ipRow, + UINT32 ipAddr, PMIB_IPNET_ROW2 ipNeigh) { NTSTATUS status; @@ -429,8 +473,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr, ASSERT(ipNeigh); RtlZeroMemory(ipNeigh, sizeof (*ipNeigh)); - ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; - ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex; + ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value; + ipNeigh->InterfaceIndex = ipRow.InterfaceIndex; ipNeigh->Address.si_family = AF_INET; ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr; @@ -438,8 +482,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr, if (status != STATUS_SUCCESS) { RtlZeroMemory(ipNeigh, sizeof (*ipNeigh)); - ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; - ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex; + ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value; + ipNeigh->InterfaceIndex = ipRow.InterfaceIndex; ipNeigh->Address.si_family = AF_INET; ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr; status = OvsResolveIPNeighEntry(ipNeigh); @@ -457,47 +501,91 @@ OvsChangeCallbackIpInterface(PVOID context, switch (notificationType) { case MibParameterNotification: case MibAddInstance: - if (ipRow->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - ipRow->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { - /* - * Update the IP Interface Row - */ - NdisAcquireSpinLock(&ovsIpHelperLock); - RtlCopyMemory(&ovsInternalIPRow, ipRow, - sizeof (PMIB_IPINTERFACE_ROW)); - ovsInternalIPConfigured = TRUE; - NdisReleaseSpinLock(&ovsIpHelperLock); + { + PLIST_ENTRY head, link, next; + + ExAcquireResourceSharedLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; + + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + if (instance->internalRow.InterfaceLuid.Info.NetLuidIndex == + ipRow->InterfaceLuid.Info.NetLuidIndex && + instance->internalRow.InterfaceLuid.Info.IfType == + ipRow->InterfaceLuid.Info.IfType && + instance->internalRow.InterfaceIndex == + ipRow->InterfaceIndex) { + + /* + * Update the IP Interface Row + */ + RtlCopyMemory(&instance->internalIPRow, ipRow, + sizeof(PMIB_IPINTERFACE_ROW)); + instance->isIpConfigured = TRUE; + + OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s", + ipRow->InterfaceLuid.Info.NetLuidIndex, + ipRow->InterfaceLuid.Info.IfType, + notificationType == MibAddInstance ? + "added" : "modified"); + + ExReleaseResourceLite(&instance->lock); + break; + } + ExReleaseResourceLite(&instance->lock); } - OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s", - ipRow->InterfaceLuid.Info.NetLuidIndex, - ipRow->InterfaceLuid.Info.IfType, - notificationType == MibAddInstance ? "added" : "modified"); + ExReleaseResourceLite(&ovsInstanceListLock); + break; + } + case MibDeleteInstance: - OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d, deleted", - ipRow->InterfaceLuid.Info.NetLuidIndex, - ipRow->InterfaceLuid.Info.IfType); - if (ipRow->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - ipRow->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { + { + PLIST_ENTRY head, link, next; - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalIPConfigured = FALSE; - NdisReleaseSpinLock(&ovsIpHelperLock); + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; - OvsCleanupIpHelperRequestList(); + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + if (instance->internalRow.InterfaceLuid.Info.NetLuidIndex == + ipRow->InterfaceLuid.Info.NetLuidIndex && + instance->internalRow.InterfaceLuid.Info.IfType == + ipRow->InterfaceLuid.Info.IfType && + instance->internalRow.InterfaceIndex == + ipRow->InterfaceIndex) { + + instance->isIpConfigured = FALSE; + ExReleaseResourceLite(&instance->lock); + + RemoveEntryList(&instance->link); + OvsIpHelperDeleteInstance(instance); + + OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is deleted", + ipRow->InterfaceLuid.Info.NetLuidIndex, + ipRow->InterfaceLuid.Info.IfType); + break; + } + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); + + if (IsListEmpty(&ovsInstanceList)) { + OvsCleanupIpHelperRequestList(); OvsCleanupFwdTable(); } break; + } case MibInitialNotification: - OVS_LOG_INFO("Get Initial notification for IP Interface change."); + OVS_LOG_INFO("Got Initial notification for IP Interface change."); default: return; } @@ -529,25 +617,40 @@ OvsChangeCallbackIpRoute(PVOID context, case MibParameterNotification: case MibDeleteInstance: + { + PLIST_ENTRY head, link, next; + BOOLEAN found = FALSE; + ASSERT(ipRoute); ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr; nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr; - OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.", - ipAddr & 0xff, (ipAddr >> 8) & 0xff, - (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, - ipRoute->DestinationPrefix.PrefixLength, - nextHop & 0xff, (nextHop >> 8) & 0xff, - (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff, - notificationType == MibDeleteInstance ? "deleted" : - "modified"); + ExAcquireResourceSharedLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; - if (ipRoute->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - ipRoute->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) { + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceSharedLite(&instance->lock, TRUE); + if (instance->isIpConfigured && + instance->internalRow.InterfaceLuid.Info.NetLuidIndex == + ipRoute->InterfaceLuid.Info.NetLuidIndex && + instance->internalRow.InterfaceLuid.Info.IfType == + ipRoute->InterfaceLuid.Info.IfType && + instance->internalRow.InterfaceIndex == + ipRoute->InterfaceIndex) { + + found = TRUE; + + ExReleaseResourceLite(&instance->lock); + break; + } + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); + if (found) { POVS_IPFORWARD_ENTRY ipf; LOCK_STATE_EX lockState; @@ -557,8 +660,18 @@ OvsChangeCallbackIpRoute(PVOID context, OvsRemoveIPForwardEntry(ipf); } NdisReleaseRWLock(ovsTableLock, &lockState); + + OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.", + ipAddr & 0xff, (ipAddr >> 8) & 0xff, + (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, + ipRoute->DestinationPrefix.PrefixLength, + nextHop & 0xff, (nextHop >> 8) & 0xff, + (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff, + notificationType == MibDeleteInstance ? "deleted" : + "modified"); } break; + } case MibInitialNotification: OVS_LOG_INFO("Get Initial notification for IP Route change."); @@ -579,40 +692,91 @@ OvsChangeCallbackUnicastIpAddress(PVOID context, switch (notificationType) { case MibParameterNotification: case MibAddInstance: + { + PLIST_ENTRY head, link, next; + ASSERT(unicastRow); ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr; - if (unicastRow->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - unicastRow->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { - ovsInternalIP = ipAddr; + + ExAcquireResourceSharedLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; + + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + if (instance->isIpConfigured && + instance->internalRow.InterfaceLuid.Info.NetLuidIndex == + unicastRow->InterfaceLuid.Info.NetLuidIndex && + instance->internalRow.InterfaceLuid.Info.IfType == + unicastRow->InterfaceLuid.Info.IfType && + instance->internalRow.InterfaceIndex == + unicastRow->InterfaceIndex) { + + instance->ipAddress = ipAddr; + + OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s", + ipAddr & 0xff, (ipAddr >> 8) & 0xff, + (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, + notificationType == MibAddInstance ? "added": "modified"); + + ExReleaseResourceLite(&instance->lock); + break; + } + ExReleaseResourceLite(&instance->lock); } - OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s", - ipAddr & 0xff, (ipAddr >> 8) & 0xff, - (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, - notificationType == MibAddInstance ? "added": "modified"); + ExReleaseResourceLite(&ovsInstanceListLock); + break; + } case MibDeleteInstance: + { + PLIST_ENTRY head, link, next; + LOCK_STATE_EX lockState; + BOOLEAN found = FALSE; + ASSERT(unicastRow); ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr; - OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d", - ipAddr & 0xff, (ipAddr >> 8) & 0xff, - (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); - if (unicastRow->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - unicastRow->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { - LOCK_STATE_EX lockState; + ExAcquireResourceSharedLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; + + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceSharedLite(&instance->lock, TRUE); + if (instance->isIpConfigured && + instance->internalRow.InterfaceLuid.Info.NetLuidIndex == + unicastRow->InterfaceLuid.Info.NetLuidIndex && + instance->internalRow.InterfaceLuid.Info.IfType == + unicastRow->InterfaceLuid.Info.IfType && + instance->internalRow.InterfaceIndex == + unicastRow->InterfaceIndex) { + + found = TRUE; + + ExReleaseResourceLite(&instance->lock); + break; + } + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); + + if (found) { NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); OvsRemoveAllFwdEntriesWithSrc(ipAddr); NdisReleaseRWLock(ovsTableLock, &lockState); + OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d", + ipAddr & 0xff, (ipAddr >> 8) & 0xff, + (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); } + break; + } case MibInitialNotification: OVS_LOG_INFO("Get Initial notification for Unicast IP Address change."); @@ -651,7 +815,7 @@ OvsRegisterChangeNotification() &ipInterfaceNotificationHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.", - status); + status); return status; } @@ -659,7 +823,7 @@ OvsRegisterChangeNotification() TRUE, &ipRouteNotificationHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.", - status); + status); goto register_cleanup; } status = NotifyUnicastIpAddressChange(AF_INET, @@ -682,10 +846,11 @@ static POVS_IPNEIGH_ENTRY OvsLookupIPNeighEntry(UINT32 ipAddr) { PLIST_ENTRY link; - POVS_IPNEIGH_ENTRY entry; UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS); LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) { + POVS_IPNEIGH_ENTRY entry; + entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link); if (entry->ipAddr == ipAddr) { return entry; @@ -709,7 +874,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) { PLIST_ENTRY link; - POVS_IPFORWARD_ENTRY ipfEntry; UINT32 hash; ASSERT(prefix->Prefix.si_family == AF_INET); @@ -720,6 +884,8 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) hash = OvsHashIPPrefix(prefix); LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) { + POVS_IPFORWARD_ENTRY ipfEntry; + ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link); if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength && ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr == @@ -735,10 +901,11 @@ static POVS_FWD_ENTRY OvsLookupIPFwdEntry(UINT32 dstIp) { PLIST_ENTRY link; - POVS_FWD_ENTRY entry; UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS); LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) { + POVS_FWD_ENTRY entry; + entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link); if (entry->info.dstIpAddr == dstIp) { return entry; @@ -770,7 +937,8 @@ OvsLookupIPFwdInfo(UINT32 dstIp, static POVS_IPNEIGH_ENTRY -OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) +OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh, + POVS_IPHELPER_INSTANCE instance) { POVS_IPNEIGH_ENTRY entry; @@ -790,6 +958,7 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress, ETH_ADDR_LEN); InitializeListHead(&entry->fwdList); + entry->context = (PVOID)instance; return entry; } @@ -798,7 +967,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) static POVS_IPFORWARD_ENTRY OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute) { - POVS_IPFORWARD_ENTRY entry; ASSERT(ipRoute); @@ -876,12 +1044,13 @@ OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry) static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf) { - POVS_FWD_ENTRY fwdEntry; PLIST_ENTRY link, next; ipf->refCount++; LIST_FORALL_SAFE(&ipf->fwdList, link, next) { + POVS_FWD_ENTRY fwdEntry; + fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink); OvsRemoveFwdEntry(fwdEntry); } @@ -896,11 +1065,12 @@ static VOID OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn) { PLIST_ENTRY link, next; - POVS_FWD_ENTRY fwdEntry; ipn->refCount++; LIST_FORALL_SAFE(&ipn->fwdList, link, next) { + POVS_FWD_ENTRY fwdEntry; + fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink); OvsRemoveFwdEntry(fwdEntry); } @@ -973,11 +1143,12 @@ static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr) { UINT32 i; - POVS_FWD_ENTRY fwdEntry; PLIST_ENTRY link, next; for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) { LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) { + POVS_FWD_ENTRY fwdEntry; + fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link); if (fwdEntry->info.srcIpAddr == ipAddr) { OvsRemoveFwdEntry(fwdEntry); @@ -991,13 +1162,14 @@ static VOID OvsCleanupFwdTable(VOID) { PLIST_ENTRY link, next; - POVS_IPNEIGH_ENTRY ipn; UINT32 i; LOCK_STATE_EX lockState; NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); if (ovsNumFwdEntries) { LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) { + POVS_IPNEIGH_ENTRY ipn; + ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); OvsRemoveIPNeighEntry(ipn); } @@ -1017,7 +1189,6 @@ OvsCleanupIpHelperRequestList(VOID) { LIST_ENTRY list; PLIST_ENTRY next, link; - POVS_IP_HELPER_REQUEST request; NdisAcquireSpinLock(&ovsIpHelperLock); if (ovsNumIpHelperRequests == 0) { @@ -1031,6 +1202,8 @@ OvsCleanupIpHelperRequestList(VOID) NdisReleaseSpinLock(&ovsIpHelperLock); LIST_FORALL_SAFE(&list, link, next) { + POVS_IP_HELPER_REQUEST request; + request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link); if (request->command == OVS_IP_HELPER_FWD_REQUEST && @@ -1056,16 +1229,38 @@ OvsWakeupIPHelper(VOID) } VOID -OvsInternalAdapterDown(VOID) +OvsInternalAdapterDown(UINT32 portNo, + GUID netCfgInstanceId) { - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalPortNo = OVS_DEFAULT_PORT_NO; - ovsInternalIPConfigured = FALSE; - NdisReleaseSpinLock(&ovsIpHelperLock); + PLIST_ENTRY head, link, next; - OvsCleanupIpHelperRequestList(); + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + head = &ovsInstanceList; + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; - OvsCleanupFwdTable(); + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + if (instance->portNo == portNo && + IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) { + + RemoveEntryList(&instance->link); + + ExReleaseResourceLite(&instance->lock); + + OvsIpHelperDeleteInstance(instance); + break; + } + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); + + if (IsListEmpty(&ovsInstanceList)) { + OvsCleanupIpHelperRequestList(); + + OvsCleanupFwdTable(); + } } @@ -1075,9 +1270,6 @@ OvsInternalAdapterUp(UINT32 portNo, { POVS_IP_HELPER_REQUEST request; - RtlCopyMemory(&ovsInternalNetCfgId, netCfgInstanceId, sizeof (GUID)); - RtlZeroMemory(&ovsInternalRow, sizeof (MIB_IF_ROW2)); - request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag( sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG); if (request == NULL) { @@ -1085,10 +1277,13 @@ OvsInternalAdapterUp(UINT32 portNo, return; } RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST)); + RtlCopyMemory(&request->instanceReq.netCfgInstanceId, + netCfgInstanceId, + sizeof(*netCfgInstanceId)); request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP; + request->instanceReq.portNo = portNo; NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalPortNo = portNo; InsertHeadList(&ovsIpHelperRequestList, &request->link); ovsNumIpHelperRequests++; if (ovsNumIpHelperRequests == 1) { @@ -1098,58 +1293,134 @@ OvsInternalAdapterUp(UINT32 portNo, } +static POVS_IPHELPER_INSTANCE +OvsIpHelperAllocateInstance(POVS_IP_HELPER_REQUEST request) +{ + POVS_IPHELPER_INSTANCE instance = NULL; + + instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag( + sizeof(*instance), OVS_IPHELPER_POOL_TAG); + if (instance) { + RtlZeroMemory(instance, sizeof(*instance)); + + RtlCopyMemory(&instance->netCfgId, + &request->instanceReq.netCfgInstanceId, + sizeof(instance->netCfgId)); + instance->portNo = request->instanceReq.portNo; + + InitializeListHead(&instance->link); + ExInitializeResourceLite(&instance->lock); + } + + return instance; +} + + +static VOID +OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance) +{ + if (instance) { + ExDeleteResourceLite(&instance->lock); + OvsFreeMemoryWithTag(instance, OVS_IPHELPER_POOL_TAG); + } +} + + +static VOID +OvsIpHelperDeleteAllInstances() +{ + PLIST_ENTRY head, link, next; + + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + head = &ovsInstanceList; + if (!IsListEmpty(head)) { + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + instance->isIpConfigured = FALSE; + ExReleaseResourceLite(&instance->lock); + + RemoveEntryList(&instance->link); + + OvsIpHelperDeleteInstance(instance); + instance = NULL; + } + } + ExReleaseResourceLite(&ovsInstanceListLock); +} + + static VOID OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request) { NTSTATUS status; + POVS_IPHELPER_INSTANCE instance = NULL; MIB_UNICASTIPADDRESS_ROW ipEntry; - GUID *netCfgInstanceId = &ovsInternalNetCfgId; + BOOLEAN error = TRUE; - OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); + do { + instance = OvsIpHelperAllocateInstance(request); + if (instance == NULL) { + break; + } - status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow); + status = OvsGetIfEntry(&instance->netCfgId, + &instance->internalRow); - if (status != STATUS_SUCCESS) { - OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID" - " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", - netCfgInstanceId->Data1, - netCfgInstanceId->Data2, - netCfgInstanceId->Data3, - *(UINT16 *)netCfgInstanceId->Data4, - netCfgInstanceId->Data4[2], - netCfgInstanceId->Data4[3], - netCfgInstanceId->Data4[4], - netCfgInstanceId->Data4[5], - netCfgInstanceId->Data4[6], - netCfgInstanceId->Data4[7]); - return; - } + if (status != STATUS_SUCCESS) { + OVS_LOG_ERROR("Fail to get IF entry for internal port with GUID" + " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", + instance->netCfgId.Data1, + instance->netCfgId.Data2, + instance->netCfgId.Data3, + *(UINT16 *)instance->netCfgId.Data4, + instance->netCfgId.Data4[2], + instance->netCfgId.Data4[3], + instance->netCfgId.Data4[4], + instance->netCfgId.Data4[5], + instance->netCfgId.Data4[6], + instance->netCfgId.Data4[7]); + break; + } - status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid, - &ovsInternalIPRow); + status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid, + &instance->internalIPRow); - if (status == STATUS_SUCCESS) { - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalIPConfigured = TRUE; - NdisReleaseSpinLock(&ovsIpHelperLock); - } else { - return; - } + if (status == STATUS_SUCCESS) { + instance->isIpConfigured = TRUE; + } else { + break; + } - status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry); - if (status != STATUS_SUCCESS) { - OVS_LOG_INFO("Fali to get IP entry for internal port with GUID" - " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", - netCfgInstanceId->Data1, - netCfgInstanceId->Data2, - netCfgInstanceId->Data3, - *(UINT16 *)netCfgInstanceId->Data4, - netCfgInstanceId->Data4[2], - netCfgInstanceId->Data4[3], - netCfgInstanceId->Data4[4], - netCfgInstanceId->Data4[5], - netCfgInstanceId->Data4[6], - netCfgInstanceId->Data4[7]); + status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry); + if (status != STATUS_SUCCESS) { + OVS_LOG_INFO("Fail to get IP entry for internal port with GUID" + " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", + instance->netCfgId.Data1, + instance->netCfgId.Data2, + instance->netCfgId.Data3, + *(UINT16 *)instance->netCfgId.Data4, + instance->netCfgId.Data4[2], + instance->netCfgId.Data4[3], + instance->netCfgId.Data4[4], + instance->netCfgId.Data4[5], + instance->netCfgId.Data4[6], + instance->netCfgId.Data4[7]); + break; + } + + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + InsertHeadList(&ovsInstanceList, &instance->link); + ExReleaseResourceLite(&ovsInstanceListLock); + + error = FALSE; + } while (error); + + OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); + if (error) { + OvsIpHelperDeleteInstance(instance); } } @@ -1157,15 +1428,11 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request) static NTSTATUS OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request) { - - NdisAcquireSpinLock(&ovsIpHelperLock); - - if (ovsInternalPortNo == OVS_DEFAULT_PORT_NO || - ovsInternalIPConfigured == FALSE) { - NdisReleaseSpinLock(&ovsIpHelperLock); + if (IsListEmpty(&ovsInstanceList)) { OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); return STATUS_NDIS_ADAPTER_NOT_READY; } else { + NdisAcquireSpinLock(&ovsIpHelperLock); InsertHeadList(&ovsIpHelperRequestList, &request->link); ovsNumIpHelperRequests++; if (ovsNumIpHelperRequests == 1) { @@ -1223,6 +1490,7 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request) BOOLEAN newIPF = FALSE; BOOLEAN newIPN = FALSE; BOOLEAN newFWD = FALSE; + POVS_IPHELPER_INSTANCE instance = NULL; status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.dst, &fwdInfo); @@ -1237,10 +1505,16 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request) dst.si_family = AF_INET; dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst; - status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src); + status = OvsGetRoute(&dst, &ipRoute, &src, &instance); if (status != STATUS_SUCCESS) { + UINT32 ipAddr = dst.Ipv4.sin_addr.s_addr; + OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x", + ipAddr & 0xff, (ipAddr >> 8) & 0xff, + (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); goto fwd_handle_nbl; } + + ExAcquireResourceSharedLite(&instance->lock, TRUE); srcAddr = src.Ipv4.sin_addr.s_addr; /* find IPNeigh */ @@ -1253,13 +1527,16 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request) } NdisReleaseRWLock(ovsTableLock, &lockState); } + RtlZeroMemory(&ipNeigh, sizeof (ipNeigh)); - ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; + ipNeigh.InterfaceLuid.Value = instance->internalRow.InterfaceLuid.Value; if (ipAddr == 0) { ipAddr = request->fwdReq.tunnelKey.dst; } - status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh); + status = OvsGetOrResolveIPNeigh(instance->internalRow, + ipAddr, &ipNeigh); if (status != STATUS_SUCCESS) { + ExReleaseResourceLite(&instance->lock); goto fwd_handle_nbl; } @@ -1275,6 +1552,7 @@ fwd_request_done: ipf = OvsCreateIPForwardEntry(&ipRoute); if (ipf == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } @@ -1292,9 +1570,10 @@ fwd_request_done: if (ipn == NULL) { ipn = OvsLookupIPNeighEntry(ipAddr); if (ipn == NULL) { - ipn = OvsCreateIPNeighEntry(&ipNeigh); + ipn = OvsCreateIPNeighEntry(&ipNeigh, instance); if (ipn == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } @@ -1308,13 +1587,14 @@ fwd_request_done: fwdInfo.dstIpAddr = request->fwdReq.tunnelKey.dst; fwdInfo.srcIpAddr = srcAddr; RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, ETH_ADDR_LEN); - RtlCopyMemory(fwdInfo.srcMacAddr, ovsInternalRow.PhysicalAddress, + RtlCopyMemory(fwdInfo.srcMacAddr, instance->internalRow.PhysicalAddress, ETH_ADDR_LEN); fwdInfo.srcPortNo = request->fwdReq.inPort; fwdEntry = OvsCreateFwdEntry(&fwdInfo); if (fwdEntry == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } @@ -1324,6 +1604,7 @@ fwd_request_done: */ OvsAddIPFwdCache(fwdEntry, ipf, ipn); NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); fwd_handle_nbl: @@ -1426,12 +1707,17 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr, static VOID -OvsHandleIPNeighTimeout(UINT32 ipAddr) +OvsHandleIPNeighTimeout(UINT32 ipAddr, + PVOID context) { MIB_IPNET_ROW2 ipNeigh; NTSTATUS status; + POVS_IPHELPER_INSTANCE instance = (POVS_IPHELPER_INSTANCE)context; - status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh); + ExAcquireResourceSharedLite(&instance->lock, TRUE); + status = OvsGetOrResolveIPNeigh(instance->internalRow, + ipAddr, &ipNeigh); + ExReleaseResourceLite(&instance->lock); OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); } @@ -1439,13 +1725,13 @@ OvsHandleIPNeighTimeout(UINT32 ipAddr) /* *---------------------------------------------------------------------------- - * IP Helper system threash handle following request + * IP Helper system thread handles the following requests: * 1. Intialize Internal port row when internal port is connected * 2. Handle FWD request * 3. Handle IP Neigh timeout * * IP Interface, unicast address, and IP route change will be handled - * by the revelant callback. + * by the revelant callbacks. *---------------------------------------------------------------------------- */ VOID @@ -1455,7 +1741,7 @@ OvsStartIpHelper(PVOID data) POVS_IP_HELPER_REQUEST req; POVS_IPNEIGH_ENTRY ipn; PLIST_ENTRY link; - UINT64 timeVal, timeout; + UINT64 timeVal, timeout; OVS_LOG_INFO("Start the IP Helper Thread, context: %p", context); @@ -1504,7 +1790,7 @@ OvsStartIpHelper(PVOID data) NdisReleaseSpinLock(&ovsIpHelperLock); - OvsHandleIPNeighTimeout(ipAddr); + OvsHandleIPNeighTimeout(ipAddr, ipn->context); NdisAcquireSpinLock(&ovsIpHelperLock); } @@ -1550,12 +1836,6 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) ovsNeighHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_NEIGH_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG); - RtlZeroMemory(&ovsInternalRow, sizeof(MIB_IF_ROW2)); - RtlZeroMemory(&ovsInternalIPRow, sizeof (MIB_IPINTERFACE_ROW)); - ovsInternalIP = 0; - - ovsInternalPortNo = OVS_DEFAULT_PORT_NO; - InitializeListHead(&ovsSortedIPNeighList); ovsTableLock = NdisAllocateRWLock(ndisFilterHandle); @@ -1567,6 +1847,9 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) ipRouteNotificationHandle = NULL; unicastIPNotificationHandle = NULL; + ExInitializeResourceLite(&ovsInstanceListLock); + InitializeListHead(&ovsInstanceList); + if (ovsFwdHashTable == NULL || ovsRouteHashTable == NULL || ovsNeighHashTable == NULL || @@ -1587,7 +1870,6 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) InitializeListHead(&ovsNeighHashTable[i]); } - KeInitializeEvent(&ovsIpHelperThreadContext.event, NotificationEvent, FALSE); status = OvsRegisterChangeNotification(); @@ -1626,6 +1908,7 @@ init_cleanup: NdisFreeRWLock(ovsTableLock); ovsTableLock = NULL; } + ExDeleteResourceLite(&ovsInstanceListLock); NdisFreeSpinLock(&ovsIpHelperLock); } return STATUS_SUCCESS; @@ -1652,6 +1935,9 @@ OvsCleanupIpHelper(VOID) NdisFreeRWLock(ovsTableLock); NdisFreeSpinLock(&ovsIpHelperLock); + + OvsIpHelperDeleteAllInstances(); + ExDeleteResourceLite(&ovsInstanceListLock); } VOID diff --git a/datapath-windows/ovsext/IpHelper.h b/datapath-windows/ovsext/IpHelper.h index 19702a2..4d8d034 100644 --- a/datapath-windows/ovsext/IpHelper.h +++ b/datapath-windows/ovsext/IpHelper.h @@ -41,6 +41,7 @@ typedef struct _OVS_IPNEIGH_ENTRY { LIST_ENTRY link; LIST_ENTRY slink; LIST_ENTRY fwdList; + PVOID context; } OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY; typedef struct _OVS_IPFORWARD_ENTRY { @@ -94,13 +95,17 @@ typedef struct _OVS_FWD_REQUEST_INFO { PVOID cbData2; } OVS_FWD_REQUEST_INFO, *POVS_FWD_REQUEST_INFO; +typedef struct _OVS_INSTANCE_REQUEST_INFO { + GUID netCfgInstanceId; + UINT32 portNo; +} OVS_INSTANCE_REQUEST_INFO, *POVS_INSTANCE_REQUEST_INFO; typedef struct _OVS_IP_HELPER_REQUEST { LIST_ENTRY link; UINT32 command; union { - OVS_FWD_REQUEST_INFO fwdReq; - UINT32 dummy; + OVS_FWD_REQUEST_INFO fwdReq; + OVS_INSTANCE_REQUEST_INFO instanceReq; }; } OVS_IP_HELPER_REQUEST, *POVS_IP_HELPER_REQUEST; @@ -115,7 +120,7 @@ NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle); VOID OvsCleanupIpHelper(VOID); VOID OvsInternalAdapterUp(UINT32 portNo, GUID *netCfgInstanceId); -VOID OvsInternalAdapterDown(VOID); +VOID OvsInternalAdapterDown(UINT32 portNo, GUID netCfgInstanceId); NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort, const PVOID tunnelKey, diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c index 65a4134..dbd9a50 100644 --- a/datapath-windows/ovsext/Vport.c +++ b/datapath-windows/ovsext/Vport.c @@ -525,7 +525,7 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext, OvsPostEvent(portNo, OVS_EVENT_LINK_DOWN); if (isInternalPort) { - OvsInternalAdapterDown(); + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); } done: @@ -1160,7 +1160,7 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext, if (hvDelete && vport->isAbsentOnHv == FALSE) { switchContext->internalPortId = 0; switchContext->internalVport = NULL; - OvsInternalAdapterDown(); + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); } hvSwitchPort = TRUE; }