hi Sorin/Alin,
I suppose this is a patch that helps with supporting multiple hyper-v switches 
in one datapath.

We had spoken about this a couple of weeks ago during the IRC meeting. I was 
proposing a solution involves writing a teaming driver that can connect to 
multiple physical adapters. In order to support multiple internal adapters, we 
can write another driver similar to a TUN/TAP driver that allows us to create 
as many virtual adapters as we want. On the backend these virtual adapters can 
inject packets directly into the hyper-v switch.

We had signed off by saying we’ll writeup the proposal that talks about the 
workflow end-to-end, and take it from there. Would it be possible to send out 
the proposal before we make heavy duty changes?

Some concerns I have with supporting multiple switches are:

1. I am not sure how sound/great it is to forward packets from one hyper-v 
switch to another. Would it be possible to get a technical clarification from 
MSFT about this? I’ll ask around if we have any contacts.

2. How would compute provisioning work? With the current workflow we have, we 
pick a particular hyper-v switch (Eg. Overlay Switch) and connect all of the 
VMs to that switch, and OVS would take care of networking them up. If we 
support multiple Hyper-V switches, what would be the basis for connecting VMs 
to different Hyper-V switches?

3. It does not take away the need for a teaming driver.

thanks,
-- Nithin


> On Sep 3, 2015, at 4:54 AM, Sorin Vinturis <svintu...@cloudbasesolutions.com> 
> wrote:
> 
> Added support for multiple internal adapter instances to the IpHelper
> module.
> 
> Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com>
> Reported-by: Sorin Vinturis <svintu...@cloudbasesolutions.com>
> Reported-at: 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_openvswitch_ovs-2Dissues_issues_101&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pNHQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=qGum5o5AOAacL3zQu_AHdhnVXoD8hib7nyXXg1JuQr8&s=iXoc-btgG4cPIdPKi_vFiw9g6JJS-Beqf0HUA6_dz2o&e=
>  
> ---
> 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;
>         }
> -- 
> 1.9.0.msysgit.0
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailman_listinfo_dev&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pNHQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=qGum5o5AOAacL3zQu_AHdhnVXoD8hib7nyXXg1JuQr8&s=Fe2_m9sZZzPkihUJPIQXx4AGUwFZ8bnPCv6X0nh0Lfg&e=
>  

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to