This patch adds multiple internal ports support to the windows datapath. All tunnels types have been updated to accommodate this new functionality.
Signed-off-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> Co-authored-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> --- datapath-windows/ovsext/Actions.c | 32 +- datapath-windows/ovsext/Gre.c | 7 +- datapath-windows/ovsext/Gre.h | 5 +- datapath-windows/ovsext/IpHelper.c | 833 ++++++++++++++++++++++++++++--------- datapath-windows/ovsext/IpHelper.h | 17 +- datapath-windows/ovsext/PacketIO.h | 3 +- datapath-windows/ovsext/Stt.c | 5 +- datapath-windows/ovsext/Stt.h | 6 +- datapath-windows/ovsext/Switch.h | 7 +- datapath-windows/ovsext/Vport.c | 56 +-- datapath-windows/ovsext/Vport.h | 78 ++-- datapath-windows/ovsext/Vxlan.c | 8 +- datapath-windows/ovsext/Vxlan.h | 7 +- 13 files changed, 759 insertions(+), 305 deletions(-) diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index 5a04541..c7e1f22 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -240,7 +240,6 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx, // We might get tunnel packets even before the tunnel gets initialized. if (tunnelVport) { - ASSERT(ovsFwdCtx->tunnelRxNic == NULL); ovsFwdCtx->tunnelRxNic = tunnelVport; return TRUE; } @@ -284,7 +283,6 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, NDIS_SWITCH_DEFAULT_PORT_ID); if (validSrcPort && OvsDetectTunnelRxPkt(ovsFwdCtx, flowKey)) { - ASSERT(ovsFwdCtx->tunnelTxNic == NULL); ASSERT(ovsFwdCtx->tunnelRxNic != NULL); return TRUE; } @@ -650,36 +648,31 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) * Setup the source port to be the internal port to as to facilitate the * second OvsLookupFlow. */ - if (ovsFwdCtx->switchContext->internalVport == NULL || + if (ovsFwdCtx->switchContext->countInternalVports <= 0 || ovsFwdCtx->switchContext->virtualExternalVport == NULL) { OvsClearTunTxCtx(ovsFwdCtx); OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped since either internal or external port is absent"); return NDIS_STATUS_FAILURE; } - ovsFwdCtx->srcVportNo = - ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->portNo; - - ovsFwdCtx->fwdDetail->SourcePortId = ovsFwdCtx->switchContext->internalPortId; - ovsFwdCtx->fwdDetail->SourceNicIndex = - ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->nicIndex; + OVS_FWD_INFO switchFwdInfo = { 0 }; /* Do the encap. Encap function does not consume the NBL. */ switch(ovsFwdCtx->tunnelTxNic->ovsType) { case OVS_VPORT_TYPE_GRE: status = OvsEncapGre(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, - &ovsFwdCtx->layers, &newNbl); + &ovsFwdCtx->layers, &newNbl, &switchFwdInfo); break; case OVS_VPORT_TYPE_VXLAN: status = OvsEncapVxlan(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, - &ovsFwdCtx->layers, &newNbl); + &ovsFwdCtx->layers, &newNbl, &switchFwdInfo); break; case OVS_VPORT_TYPE_STT: status = OvsEncapStt(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, - &ovsFwdCtx->layers, &newNbl); + &ovsFwdCtx->layers, &newNbl, &switchFwdInfo); break; default: ASSERT(! "Tx: Unhandled tunnel type"); @@ -688,8 +681,11 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) /* Reset the tunnel context so that it doesn't get used after this point. */ OvsClearTunTxCtx(ovsFwdCtx); - if (status == NDIS_STATUS_SUCCESS) { + if (status == NDIS_STATUS_SUCCESS && switchFwdInfo.vport != NULL) { ASSERT(newNbl); + ovsFwdCtx->srcVportNo = switchFwdInfo.vport->portNo; + ovsFwdCtx->fwdDetail->SourcePortId = switchFwdInfo.vport->portId; + ovsFwdCtx->fwdDetail->SourceNicIndex = switchFwdInfo.vport->nicIndex; OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"Complete after cloning NBL for encapsulation"); ovsFwdCtx->curNbl = newNbl; @@ -697,7 +693,7 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) ASSERT(ovsFwdCtx->curNbl == NULL); } else { /* - * XXX: Temporary freeing of the packet until we register a + * XXX: Temporary freeing of the packet until we register a * callback to IP helper. */ OvsCompleteNBLForwardingCtx(ovsFwdCtx, @@ -929,13 +925,11 @@ dropit: VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext, VOID *compList, - PNET_BUFFER_LIST curNbl) + PNET_BUFFER_LIST curNbl, + POVS_VPORT_ENTRY internalVport) { NDIS_STATUS status; OvsForwardingContext ovsFwdCtx; - POVS_VPORT_ENTRY internalVport = - (POVS_VPORT_ENTRY)switchContext->internalVport; - /* XXX: make sure comp list was not a stack variable previously. */ OvsCompletionList *completionList = (OvsCompletionList *)compList; @@ -944,7 +938,7 @@ OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext, * It could, but will we get this callback from IP helper in that case. Need * to check. */ - ASSERT(switchContext->internalVport); + ASSERT(switchContext->countInternalVports >= 0); status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl, internalVport->portNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl), diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c index cb41593..3933c60 100644 --- a/datapath-windows/ovsext/Gre.c +++ b/datapath-windows/ovsext/Gre.c @@ -96,7 +96,8 @@ OvsEncapGre(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl) + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo) { OVS_FWD_INFO fwdInfo; NDIS_STATUS status; @@ -107,6 +108,8 @@ OvsEncapGre(POVS_VPORT_ENTRY vport, return NDIS_STATUS_FAILURE; } + RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value); + status = OvsDoEncapGre(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); return status; @@ -236,8 +239,6 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport, IP_DF_NBO : 0; ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64; ipHdr->protocol = IPPROTO_GRE; - ASSERT(tunKey->dst == fwdInfo->dstIpAddr); - ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0); ipHdr->saddr = fwdInfo->srcIpAddr; ipHdr->daddr = fwdInfo->dstIpAddr; diff --git a/datapath-windows/ovsext/Gre.h b/datapath-windows/ovsext/Gre.h index d2472d9..54f6541 100644 --- a/datapath-windows/ovsext/Gre.h +++ b/datapath-windows/ovsext/Gre.h @@ -20,6 +20,8 @@ #include "NetProto.h" #include "Flow.h" +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; + typedef struct _OVS_GRE_VPORT { UINT64 ipId; /* @@ -64,7 +66,8 @@ NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl); + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo); NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c index 8126222..3cf077d 100644 --- a/datapath-windows/ovsext/IpHelper.c +++ b/datapath-windows/ovsext/IpHelper.c @@ -19,6 +19,8 @@ #include "Switch.h" #include "Jhash.h" +extern POVS_SWITCH_CONTEXT gOvsSwitchContext; + #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif @@ -26,28 +28,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 BOOLEAN ovsInternalAdapterUp; -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 +104,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 +347,65 @@ 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, + POVS_VPORT_ENTRY* vport) { - 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); + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + ULONG minMetric = MAXULONG; + SOCKADDR_INET crtSrcAddr = { 0 }; + MIB_IPFORWARD_ROW2 crtRoute = { 0 }; + POVS_IPHELPER_INSTANCE crtInstance = NULL; + WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 }; - 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); + + ExAcquireResourceExclusiveLite(&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) { + size_t len = 0; + minMetric = crtRoute.Metric; + + RtlCopyMemory(sourceAddress, &crtSrcAddr, sizeof(*sourceAddress)); + RtlCopyMemory(route, &crtRoute, sizeof(*route)); + *instance = crtInstance; + + ConvertInterfaceLuidToAlias(&crtInstance->internalRow.InterfaceLuid, + interfaceName, IF_MAX_STRING_SIZE + 1); + RtlStringCbLengthW(interfaceName, IF_MAX_STRING_SIZE, &len); + + *vport = OvsFindVportByHvNameW(gOvsSwitchContext, + interfaceName, + len); + + status = STATUS_SUCCESS; + } + ExReleaseResourceLite(&crtInstance->lock); } + ExReleaseResourceLite(&ovsInstanceListLock); OvsDumpRoute(sourceAddress, destinationAddress, route); + return status; } @@ -358,8 +415,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 +478,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 +487,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 +496,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); @@ -447,57 +505,241 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr, return status; } +static __inline BOOLEAN +OvsCheckInstanceRow(PMIB_IF_ROW2 instanceRow, + PNET_LUID netLuid, + NET_IFINDEX ifIndex) +{ + return (instanceRow->InterfaceLuid.Info.NetLuidIndex == + netLuid->Info.NetLuidIndex && + instanceRow->InterfaceLuid.Info.IfType == + netLuid->Info.IfType && + instanceRow->InterfaceIndex == + ifIndex); +} static VOID -OvsChangeCallbackIpInterface(PVOID context, - PMIB_IPINTERFACE_ROW ipRow, - MIB_NOTIFICATION_TYPE notificationType) +OvsUpdateIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow) { - UNREFERENCED_PARAMETER(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) { + PLIST_ENTRY head, link, next; + + ExAcquireResourceExclusiveLite(&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 (OvsCheckInstanceRow(&instance->internalRow, + &ipRow->InterfaceLuid, + ipRow->InterfaceIndex) + ) { + /* * Update the IP Interface Row */ - NdisAcquireSpinLock(&ovsIpHelperLock); - RtlCopyMemory(&ovsInternalIPRow, ipRow, - sizeof (PMIB_IPINTERFACE_ROW)); - ovsInternalIPConfigured = TRUE; - NdisReleaseSpinLock(&ovsIpHelperLock); + 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, + "modified"); + + ExReleaseResourceLite(&instance->lock); + break; } - OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s", - ipRow->InterfaceLuid.Info.NetLuidIndex, - ipRow->InterfaceLuid.Info.IfType, - notificationType == MibAddInstance ? "added" : "modified"); - 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) { + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalIPConfigured = FALSE; - NdisReleaseSpinLock(&ovsIpHelperLock); + return; +} + +static VOID +OvsAddIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow) +{ + PLIST_ENTRY head, link, next; + BOOLEAN found = FALSE; + + ExAcquireResourceExclusiveLite(&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 (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid, + ipRow->InterfaceIndex)) { - OvsCleanupIpHelperRequestList(); + instance->isIpConfigured = FALSE; + ExReleaseResourceLite(&instance->lock); - OvsCleanupFwdTable(); + found = TRUE; + + break; } + ExReleaseResourceLite(&instance->lock); + } + ExReleaseResourceLite(&ovsInstanceListLock); + + if (found != TRUE) { + NTSTATUS status; + POVS_IPHELPER_INSTANCE instance = NULL; + MIB_UNICASTIPADDRESS_ROW ipEntry; + BOOLEAN error = TRUE; + instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag( + sizeof(*instance), OVS_IPHELPER_POOL_TAG); + if (instance == NULL) { + goto error; + } + RtlZeroMemory(instance, sizeof(*instance)); + + InitializeListHead(&instance->link); + ExInitializeResourceLite(&instance->lock); + WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 }; + status = ConvertInterfaceLuidToAlias(&ipRow->InterfaceLuid, + interfaceName, + IF_MAX_STRING_SIZE + 1); + POVS_VPORT_ENTRY vport = OvsFindVportByHvNameW(gOvsSwitchContext, + interfaceName, + sizeof(WCHAR) * + wcslen(interfaceName)); + + if (vport == NULL) { + goto error; + } + RtlCopyMemory(&instance->netCfgId, + &vport->netCfgInstanceId, + sizeof(instance->netCfgId)); + instance->portNo = vport->portNo; + RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2)); + RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW)); + status = OvsGetIfEntry(&instance->netCfgId, + &instance->internalRow); + + 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]); + goto error; + } + + status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid, + &instance->internalIPRow); + + if (status == STATUS_SUCCESS) { + instance->isIpConfigured = TRUE; + } + else { + goto error; + } + + 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]); + goto error; + } + + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + InsertHeadList(&ovsInstanceList, &instance->link); + ExReleaseResourceLite(&ovsInstanceListLock); + + error = FALSE; + +error: + if (error) { + OvsIpHelperDeleteInstance(instance); + } + } + + return; +} + +static VOID +OvsRemoveIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow) +{ + PLIST_ENTRY head, link, next; + + ExAcquireResourceExclusiveLite(&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 (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid, + ipRow->InterfaceIndex)) { + + instance->isIpConfigured = FALSE; + RemoveEntryList(&instance->link); + + ExReleaseResourceLite(&instance->lock); + 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(); + } + + return; +} + +static VOID +OvsChangeCallbackIpInterface(PVOID context, + PMIB_IPINTERFACE_ROW ipRow, + MIB_NOTIFICATION_TYPE notificationType) +{ + UNREFERENCED_PARAMETER(context); + switch (notificationType) { + case MibParameterNotification: + OvsUpdateIpInterfaceNotification(ipRow); + break; + case MibAddInstance: + OvsAddIpInterfaceNotification(ipRow); + break; + + case MibDeleteInstance: + OvsRemoveIpInterfaceNotification(ipRow); 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 +771,38 @@ 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"); + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + head = &(ovsInstanceList); + LIST_FORALL_SAFE(head, link, next) { + POVS_IPHELPER_INSTANCE instance = NULL; + + instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link); - if (ipRoute->InterfaceLuid.Info.NetLuidIndex == - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && - ipRoute->InterfaceLuid.Info.IfType == - ovsInternalRow.InterfaceLuid.Info.IfType && - ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) { + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + if (instance->isIpConfigured && + OvsCheckInstanceRow(&instance->internalRow, + &ipRoute->InterfaceLuid, + 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 +812,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 +844,87 @@ 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; + + ExAcquireResourceExclusiveLite(&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 && + OvsCheckInstanceRow(&instance->internalRow, + &unicastRow->InterfaceLuid, + 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; + ExAcquireResourceExclusiveLite(&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 && + OvsCheckInstanceRow(&instance->internalRow, + &unicastRow->InterfaceLuid, + 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."); @@ -643,7 +955,7 @@ OvsCancelChangeNotification() static NTSTATUS OvsRegisterChangeNotification() { - NTSTATUS status; + NTSTATUS status = NDIS_STATUS_SUCCESS; status = NotifyIpInterfaceChange(AF_INET, OvsChangeCallbackIpInterface, @@ -651,7 +963,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 +971,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 +994,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 +1022,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) { PLIST_ENTRY link; - POVS_IPFORWARD_ENTRY ipfEntry; UINT32 hash; ASSERT(prefix->Prefix.si_family == AF_INET); @@ -720,6 +1032,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 +1049,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; @@ -759,9 +1074,8 @@ OvsLookupIPFwdInfo(UINT32 dstIp, NdisAcquireRWLockRead(ovsTableLock, &lockState, 0); entry = OvsLookupIPFwdEntry(dstIp); if (entry) { - info->value[0] = entry->info.value[0]; - info->value[1] = entry->info.value[1]; - info->value[2] = entry->info.value[2]; + RtlCopyMemory(info->value, entry->info.value, + sizeof entry->info.value); status = STATUS_SUCCESS; } NdisReleaseRWLock(ovsTableLock, &lockState); @@ -770,7 +1084,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 +1105,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 +1114,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) static POVS_IPFORWARD_ENTRY OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute) { - POVS_IPFORWARD_ENTRY entry; ASSERT(ipRoute); @@ -876,12 +1191,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 +1212,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 +1290,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 +1309,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,20 +1336,16 @@ OvsCleanupIpHelperRequestList(VOID) { LIST_ENTRY list; PLIST_ENTRY next, link; - POVS_IP_HELPER_REQUEST request; NdisAcquireSpinLock(&ovsIpHelperLock); - if (ovsNumIpHelperRequests == 0) { - NdisReleaseSpinLock(&ovsIpHelperLock); - return; - } - InitializeListHead(&list); - OvsAppendList(&list, &ovsIpHelperRequestList); + OvsAppendList(&list, &ovsIpHelperRequestList); ovsNumIpHelperRequests = 0; 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,27 +1371,47 @@ OvsWakeupIPHelper(VOID) } VOID -OvsInternalAdapterDown(VOID) +OvsInternalAdapterDown(UINT32 portNo, + GUID netCfgInstanceId) { - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalAdapterUp = FALSE; - 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(); + } } VOID -OvsInternalAdapterUp(GUID *netCfgInstanceId) +OvsInternalAdapterUp(UINT32 portNo, + GUID *netCfgInstanceId) { 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) { @@ -1084,10 +1419,13 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId) 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); - ovsInternalAdapterUp = TRUE; InsertHeadList(&ovsIpHelperRequestList, &request->link); ovsNumIpHelperRequests++; if (ovsNumIpHelperRequests == 1) { @@ -1097,58 +1435,135 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId) } +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; + RemoveEntryList(&instance->link); + + ExReleaseResourceLite(&instance->lock); + + OvsIpHelperDeleteInstance(instance); + } + } + 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; + } + RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2)); + RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW)); + status = OvsGetIfEntry(&instance->netCfgId, + &instance->internalRow); - status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow); + 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; + } - 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; - } + status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid, + &instance->internalIPRow); - status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid, - &ovsInternalIPRow); + if (status == STATUS_SUCCESS) { + instance->isIpConfigured = TRUE; + } else { + break; + } - if (status == STATUS_SUCCESS) { - NdisAcquireSpinLock(&ovsIpHelperLock); - ovsInternalIPConfigured = TRUE; - NdisReleaseSpinLock(&ovsIpHelperLock); - } else { - return; - } + 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; + } - 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]); + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); + InsertHeadList(&ovsInstanceList, &instance->link); + ExReleaseResourceLite(&ovsInstanceListLock); + + error = FALSE; + } while (error); + + OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); + if (error) { + OvsIpHelperDeleteInstance(instance); } } @@ -1156,15 +1571,11 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request) static NTSTATUS OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request) { - - NdisAcquireSpinLock(&ovsIpHelperLock); - - if (ovsInternalAdapterUp == FALSE || - 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) { @@ -1222,6 +1633,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); @@ -1236,10 +1648,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, &fwdInfo.vport); 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; } + + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); srcAddr = src.Ipv4.sin_addr.s_addr; /* find IPNeigh */ @@ -1252,13 +1670,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; } @@ -1274,6 +1695,7 @@ fwd_request_done: ipf = OvsCreateIPForwardEntry(&ipRoute); if (ipf == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } @@ -1291,9 +1713,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; } @@ -1307,13 +1730,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; } @@ -1323,6 +1747,7 @@ fwd_request_done: */ OvsAddIPFwdCache(fwdEntry, ipf, ipn); NdisReleaseRWLock(ovsTableLock, &lockState); + ExReleaseResourceLite(&instance->lock); fwd_handle_nbl: @@ -1425,12 +1850,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); + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); + status = OvsGetOrResolveIPNeigh(instance->internalRow, + ipAddr, &ipNeigh); + ExReleaseResourceLite(&instance->lock); OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); } @@ -1438,13 +1868,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 @@ -1454,15 +1884,15 @@ 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); NdisAcquireSpinLock(&ovsIpHelperLock); while (!context->exit) { - timeout = 0; while (!IsListEmpty(&ovsIpHelperRequestList)) { + ovsNumIpHelperRequests--; if (context->exit) { goto ip_helper_wait; } @@ -1503,7 +1933,7 @@ OvsStartIpHelper(PVOID data) NdisReleaseSpinLock(&ovsIpHelperLock); - OvsHandleIPNeighTimeout(ipAddr); + OvsHandleIPNeighTimeout(ipAddr, ipn->context); NdisAcquireSpinLock(&ovsIpHelperLock); } @@ -1526,7 +1956,6 @@ ip_helper_wait: NdisReleaseSpinLock(&ovsIpHelperLock); OvsCleanupFwdTable(); OvsCleanupIpHelperRequestList(); - OVS_LOG_INFO("Terminating the OVS IP Helper system thread"); PsTerminateSystemThread(STATUS_SUCCESS); @@ -1536,7 +1965,8 @@ ip_helper_wait: NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) { - NTSTATUS status; + UNREFERENCED_PARAMETER(ndisFilterHandle); + NTSTATUS status = NDIS_STATUS_SUCCESS; HANDLE threadHandle; UINT32 i; @@ -1549,12 +1979,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; - - ovsInternalAdapterUp = FALSE; - InitializeListHead(&ovsSortedIPNeighList); ovsTableLock = NdisAllocateRWLock(ndisFilterHandle); @@ -1566,6 +1990,9 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) ipRouteNotificationHandle = NULL; unicastIPNotificationHandle = NULL; + ExInitializeResourceLite(&ovsInstanceListLock); + InitializeListHead(&ovsInstanceList); + if (ovsFwdHashTable == NULL || ovsRouteHashTable == NULL || ovsNeighHashTable == NULL || @@ -1625,6 +2052,7 @@ init_cleanup: NdisFreeRWLock(ovsTableLock); ovsTableLock = NULL; } + ExDeleteResourceLite(&ovsInstanceListLock); NdisFreeSpinLock(&ovsIpHelperLock); } return STATUS_SUCCESS; @@ -1651,6 +2079,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 8562f86..095bd05 100644 --- a/datapath-windows/ovsext/IpHelper.h +++ b/datapath-windows/ovsext/IpHelper.h @@ -19,6 +19,7 @@ #include <ntddk.h> #include <netioapi.h> +#include <Vport.h> #define OVS_FWD_HASH_TABLE_SIZE ((UINT32)1 << 10) #define OVS_FWD_HASH_TABLE_MASK (OVS_FWD_HASH_TABLE_SIZE - 1) @@ -41,6 +42,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 { @@ -58,8 +60,9 @@ typedef union _OVS_FWD_INFO { UINT8 dstMacAddr[ETH_ADDR_LEN]; UINT8 srcMacAddr[ETH_ADDR_LEN]; UINT32 srcPortNo; + POVS_VPORT_ENTRY vport; }; - UINT64 value[3]; + UINT64 value[4]; } OVS_FWD_INFO, *POVS_FWD_INFO; typedef struct _OVS_FWD_ENTRY { @@ -94,13 +97,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; @@ -114,8 +121,8 @@ typedef struct _OVS_IP_HELPER_THREAD_CONTEXT { NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle); VOID OvsCleanupIpHelper(VOID); -VOID OvsInternalAdapterUp(GUID *netCfgInstanceId); -VOID OvsInternalAdapterDown(VOID); +VOID OvsInternalAdapterUp(UINT32 portNo, GUID *netCfgInstanceId); +VOID OvsInternalAdapterDown(UINT32 portNo, GUID netCfgInstanceId); NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort, const PVOID tunnelKey, diff --git a/datapath-windows/ovsext/PacketIO.h b/datapath-windows/ovsext/PacketIO.h index 7247869..b204167 100644 --- a/datapath-windows/ovsext/PacketIO.h +++ b/datapath-windows/ovsext/PacketIO.h @@ -56,6 +56,7 @@ NDIS_STATUS OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext, const PNL_ATTR actions, int actionsLen); VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext, - VOID *compList, PNET_BUFFER_LIST curNbl); + VOID *compList, PNET_BUFFER_LIST curNbl, + POVS_VPORT_ENTRY internalVport); #endif /* __PACKETIO_H_ */ diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c index dd7bf92..47d9a8d 100644 --- a/datapath-windows/ovsext/Stt.c +++ b/datapath-windows/ovsext/Stt.c @@ -105,7 +105,8 @@ OvsEncapStt(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl) + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo) { OVS_FWD_INFO fwdInfo; NDIS_STATUS status; @@ -121,6 +122,8 @@ OvsEncapStt(POVS_VPORT_ENTRY vport, return NDIS_STATUS_FAILURE; } + RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value); + status = OvsDoEncapStt(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); return status; diff --git a/datapath-windows/ovsext/Stt.h b/datapath-windows/ovsext/Stt.h index a3e3915..f64654c 100644 --- a/datapath-windows/ovsext/Stt.h +++ b/datapath-windows/ovsext/Stt.h @@ -40,6 +40,9 @@ #define STT_CLEANUP_INTERVAL 300000000 // 30s #define STT_ETH_PAD 2 + +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; + typedef struct SttHdr { UINT8 version; UINT8 flags; @@ -89,7 +92,8 @@ NDIS_STATUS OvsEncapStt(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl); + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo); NDIS_STATUS OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h index 001335a..7b8712d 100644 --- a/datapath-windows/ovsext/Switch.h +++ b/datapath-windows/ovsext/Switch.h @@ -127,9 +127,10 @@ typedef struct _OVS_SWITCH_CONTEXT * 'numPhysicalNics'. */ NDIS_SWITCH_PORT_ID virtualExternalPortId; - NDIS_SWITCH_PORT_ID internalPortId; - POVS_VPORT_ENTRY virtualExternalVport; // the virtual adapter vport - POVS_VPORT_ENTRY internalVport; + POVS_VPORT_ENTRY virtualExternalVport; /* the virtual adapter + * vport */ + INT32 countInternalVports; /* the number of internal + * vports */ /* * 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch, diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c index 7b0103d..fad0350 100644 --- a/datapath-windows/ovsext/Vport.c +++ b/datapath-windows/ovsext/Vport.c @@ -81,8 +81,6 @@ static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info, PVOID outBuffer, UINT32 outBufLen, int dpIfIndex); -static POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext, - PWSTR wsName, SIZE_T wstrSize); static VOID UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN newPort); static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx, @@ -96,7 +94,7 @@ static VOID OvsTunnelVportPendingInit(PVOID context, static VOID OvsTunnelVportPendingRemove(PVOID context, NTSTATUS status, UINT32 *replyLen); -static NTSTATUS GetNICAlias(GUID *netCfgInstanceId, +static NTSTATUS GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam, IF_COUNTED_STRING *portFriendlyName); /* @@ -331,7 +329,7 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext, if (OvsIsInternalNIC(nicParam->NicType) || OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { - GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName); + GetNICAlias(nicParam, &portFriendlyName); } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); @@ -427,7 +425,7 @@ HvConnectNic(POVS_SWITCH_CONTEXT switchContext, NdisReleaseRWLock(switchContext->dispatchLock, &lockState); if (nicParam->NicType == NdisSwitchNicTypeInternal) { - OvsInternalAdapterUp(&nicParam->NetCfgInstanceId); + OvsInternalAdapterUp(vport->portNo, &nicParam->NetCfgInstanceId); } done: @@ -464,7 +462,7 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext, /* GetNICAlias() must be called outside of a lock. */ if (nicParam->NicType == NdisSwitchNicTypeInternal || OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { - GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName); + GetNICAlias(nicParam, &portFriendlyName); aliasLookup = TRUE; } @@ -607,7 +605,7 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext, NdisReleaseRWLock(switchContext->dispatchLock, &lockState); if (isInternalPort) { - OvsInternalAdapterDown(); + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); } done: @@ -827,10 +825,6 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext, portId == switchContext->virtualExternalPortId && index == switchContext->virtualExternalVport->nicIndex) { return (POVS_VPORT_ENTRY)switchContext->virtualExternalVport; - } else if (switchContext->internalVport && - portId == switchContext->internalPortId && - index == switchContext->internalVport->nicIndex) { - return (POVS_VPORT_ENTRY)switchContext->internalVport; } else { PLIST_ENTRY head, link; POVS_VPORT_ENTRY vport; @@ -937,6 +931,8 @@ OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext, } else { RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId, sizeof (nicParam->NetCfgInstanceId)); + RtlCopyMemory(&vport->nicFriendlyName, &nicParam->NicFriendlyName, + sizeof (nicParam->NicFriendlyName)); } RtlCopyMemory(&vport->nicName, &nicParam->NicName, sizeof (nicParam->NicName)); @@ -1060,11 +1056,12 @@ OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport) /* * -------------------------------------------------------------------------- * For external and internal vports 'portFriendlyName' parameter, provided by - * Hyper-V, is overwritten with the interface alias name. + * Hyper-V, is overwritten with the interface alias name and nic friendly name + * equivalent. * -------------------------------------------------------------------------- */ static NTSTATUS -GetNICAlias(GUID *netCfgInstanceId, +GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam, IF_COUNTED_STRING *portFriendlyName) { NTSTATUS status = STATUS_SUCCESS; @@ -1072,7 +1069,13 @@ GetNICAlias(GUID *netCfgInstanceId, NET_LUID interfaceLuid = { 0 }; size_t len = 0; - status = ConvertInterfaceGuidToLuid(netCfgInstanceId, + if (nicParam->NicType == NdisSwitchNicTypeInternal) { + RtlCopyMemory(portFriendlyName, &nicParam->NicFriendlyName, + sizeof nicParam->NicFriendlyName); + return status; + } + + status = ConvertInterfaceGuidToLuid(&nicParam->NetCfgInstanceId, &interfaceLuid); if (status == STATUS_SUCCESS) { /* @@ -1083,9 +1086,9 @@ GetNICAlias(GUID *netCfgInstanceId, IF_MAX_STRING_SIZE + 1); if (status == STATUS_SUCCESS) { RtlStringCbPrintfW(portFriendlyName->String, - IF_MAX_STRING_SIZE, L"%s", interfaceName); + IF_MAX_STRING_SIZE, L"%s", interfaceName); RtlStringCbLengthW(portFriendlyName->String, IF_MAX_STRING_SIZE, - &len); + &len); portFriendlyName->Length = (USHORT)len; } else { OVS_LOG_ERROR("Fail to convert interface LUID to alias, status: %x", @@ -1127,8 +1130,7 @@ UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext, break; case NdisSwitchPortTypeInternal: ASSERT(vport->isBridgeInternal == FALSE); - switchContext->internalPortId = vport->portId; - switchContext->internalVport = vport; + switchContext->countInternalVports++; break; case NdisSwitchPortTypeSynthetic: case NdisSwitchPortTypeEmulated: @@ -1244,9 +1246,9 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext, case OVS_VPORT_TYPE_INTERNAL: if (!vport->isBridgeInternal) { if (hvDelete && vport->isAbsentOnHv == FALSE) { - switchContext->internalPortId = 0; - switchContext->internalVport = NULL; - OvsInternalAdapterDown(); + switchContext->countInternalVports--; + ASSERT(switchContext->countInternalVports >= 0); + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); } hvSwitchPort = TRUE; } @@ -1516,7 +1518,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext) } ASSERT(switchContext->virtualExternalVport == NULL); - ASSERT(switchContext->internalVport == NULL); + ASSERT(switchContext->countInternalVports == 0); } @@ -2196,12 +2198,12 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, goto Cleanup; } - if (portType == OVS_VPORT_TYPE_NETDEV) { - /* External ports can also be looked up like VIF ports. */ + if (portType == OVS_VPORT_TYPE_NETDEV || + portType == OVS_VPORT_TYPE_INTERNAL) { + /* External and internal ports can also be looked up like VIF ports. */ vport = OvsFindVportByHvNameA(gOvsSwitchContext, portName); } else { - ASSERT(OvsIsTunnelVportType(portType) || - portType == OVS_VPORT_TYPE_INTERNAL); + ASSERT(OvsIsTunnelVportType(portType)); vport = (POVS_VPORT_ENTRY)OvsAllocateVport(); if (vport == NULL) { @@ -2241,8 +2243,6 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, transportPortDest); nlError = NlMapStatusToNlErr(status); - } else { - OvsInitBridgeInternalVport(vport); } vportInitialized = TRUE; diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h index 373896d..00bd931 100644 --- a/datapath-windows/ovsext/Vport.h +++ b/datapath-windows/ovsext/Vport.h @@ -79,38 +79,39 @@ typedef struct _OVS_VPORT_FULL_STATS { * tunnel type, such as vxlan, gre */ typedef struct _OVS_VPORT_ENTRY { - LIST_ENTRY ovsNameLink; - LIST_ENTRY portIdLink; - LIST_ENTRY portNoLink; - LIST_ENTRY tunnelVportLink; - - OVS_VPORT_STATE ovsState; - OVS_VPORT_TYPE ovsType; - OVS_VPORT_STATS stats; - OVS_VPORT_ERR_STATS errStats; - UINT32 portNo; - UINT32 mtu; + LIST_ENTRY ovsNameLink; + LIST_ENTRY portIdLink; + LIST_ENTRY portNoLink; + LIST_ENTRY tunnelVportLink; + + OVS_VPORT_STATE ovsState; + OVS_VPORT_TYPE ovsType; + OVS_VPORT_STATS stats; + OVS_VPORT_ERR_STATS errStats; + UINT32 portNo; + UINT32 mtu; /* ovsName is the ovs (datapath) port name - it is null terminated. */ - CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH]; - - PVOID priv; - NDIS_SWITCH_PORT_ID portId; - NDIS_SWITCH_NIC_INDEX nicIndex; - NDIS_SWITCH_NIC_TYPE nicType; - UINT16 numaNodeId; - NDIS_SWITCH_PORT_STATE portState; - NDIS_SWITCH_NIC_STATE nicState; - NDIS_SWITCH_PORT_TYPE portType; - - UINT8 permMacAddress[ETH_ADDR_LEN]; - UINT8 currMacAddress[ETH_ADDR_LEN]; - UINT8 vmMacAddress[ETH_ADDR_LEN]; - - NDIS_SWITCH_PORT_NAME hvPortName; - IF_COUNTED_STRING portFriendlyName; - NDIS_SWITCH_NIC_NAME nicName; - NDIS_VM_NAME vmName; - GUID netCfgInstanceId; + CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH]; + + PVOID priv; + NDIS_SWITCH_PORT_ID portId; + NDIS_SWITCH_NIC_INDEX nicIndex; + NDIS_SWITCH_NIC_TYPE nicType; + UINT16 numaNodeId; + NDIS_SWITCH_PORT_STATE portState; + NDIS_SWITCH_NIC_STATE nicState; + NDIS_SWITCH_PORT_TYPE portType; + + UINT8 permMacAddress[ETH_ADDR_LEN]; + UINT8 currMacAddress[ETH_ADDR_LEN]; + UINT8 vmMacAddress[ETH_ADDR_LEN]; + + NDIS_SWITCH_PORT_NAME hvPortName; + IF_COUNTED_STRING portFriendlyName; + NDIS_SWITCH_NIC_NAME nicName; + NDIS_SWITCH_NIC_FRIENDLYNAME nicFriendlyName; + NDIS_VM_NAME vmName; + GUID netCfgInstanceId; /* * OVS userpace has a notion of bridges which basically defines an * L2-domain. Each "bridge" has an "internal" port of type @@ -125,12 +126,12 @@ typedef struct _OVS_VPORT_ENTRY { * If a flow actions specifies the output port to be a bridge-internal port, * the port is silently ignored. */ - BOOLEAN isBridgeInternal; - BOOLEAN isExternal; - UINT32 upcallPid; /* netlink upcall port id */ - PNL_ATTR portOptions; - BOOLEAN isAbsentOnHv; /* Is this port present on the - Hyper-V switch? */ + BOOLEAN isBridgeInternal; + BOOLEAN isExternal; + UINT32 upcallPid; /* netlink upcall port id */ + PNL_ATTR portOptions; + BOOLEAN isAbsentOnHv; /* Is this port present on the + Hyper-V switch? */ } OVS_VPORT_ENTRY, *POVS_VPORT_ENTRY; struct _OVS_SWITCH_CONTEXT; @@ -142,6 +143,9 @@ POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext, PSTR name); POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext, PSTR name); +POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext, + PWSTR wsName, + SIZE_T wstrSize); POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext, NDIS_SWITCH_PORT_ID portId, NDIS_SWITCH_NIC_INDEX index); diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c index b89c032..3ac919a 100644 --- a/datapath-windows/ovsext/Vxlan.c +++ b/datapath-windows/ovsext/Vxlan.c @@ -282,8 +282,6 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, IP_DF_NBO : 0; ipHdr->ttl = tunKey->ttl ? tunKey->ttl : VXLAN_DEFAULT_TTL; ipHdr->protocol = IPPROTO_UDP; - ASSERT(tunKey->dst == fwdInfo->dstIpAddr); - ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0); ipHdr->saddr = fwdInfo->srcIpAddr; ipHdr->daddr = fwdInfo->dstIpAddr; @@ -332,7 +330,8 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl) + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo) { NTSTATUS status; OVS_FWD_INFO fwdInfo; @@ -340,7 +339,6 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport, status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); if (status != STATUS_SUCCESS) { OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); - // return NDIS_STATUS_PENDING; /* * XXX: Don't know if the completionList will make any sense when * accessed in the callback. Make sure the caveats are known. @@ -351,6 +349,8 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport, return NDIS_STATUS_FAILURE; } + RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value); + return OvsDoEncapVxlan(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); } diff --git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h index b9462f0..9a41bbe 100644 --- a/datapath-windows/ovsext/Vxlan.h +++ b/datapath-windows/ovsext/Vxlan.h @@ -17,7 +17,11 @@ #ifndef __VXLAN_H_ #define __VXLAN_H_ 1 +#include "IpHelper.h" #include "NetProto.h" + +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; + typedef struct _OVS_VXLAN_VPORT { UINT16 dstPort; UINT64 filterID; @@ -64,7 +68,8 @@ NDIS_STATUS OvsEncapVxlan(POVS_VPORT_ENTRY vport, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, - PNET_BUFFER_LIST *newNbl); + PNET_BUFFER_LIST *newNbl, + POVS_FWD_INFO switchFwdInfo); NDIS_STATUS OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, -- 1.9.5.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev