Acked-by: Paul Boca <[email protected]>
> -----Original Message----- > From: dev [mailto:[email protected]] On Behalf Of Alin Serdean > Sent: Tuesday, July 26, 2016 6:47 PM > To: [email protected] > Subject: [ovs-dev] [PATCH v2 2/4] datapath-windows: Add multiple switch > internal ports > > 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 <[email protected]> > Co-authored-by: Sorin Vinturis <[email protected]> > --- > v2: Rebase > --- > datapath-windows/ovsext/Actions.c | 41 +- > datapath-windows/ovsext/Geneve.c | 5 +- > datapath-windows/ovsext/Geneve.h | 6 +- > datapath-windows/ovsext/Gre.c | 5 +- > datapath-windows/ovsext/Gre.h | 8 +- > datapath-windows/ovsext/IpHelper.c | 917 > ++++++++++++++++++++++++++++--------- > datapath-windows/ovsext/IpHelper.h | 20 +- > datapath-windows/ovsext/Stt.c | 5 +- > datapath-windows/ovsext/Stt.h | 7 +- > datapath-windows/ovsext/Switch.h | 8 +- > datapath-windows/ovsext/Vport.c | 56 +-- > datapath-windows/ovsext/Vport.h | 83 ++-- > datapath-windows/ovsext/Vxlan.c | 8 +- > datapath-windows/ovsext/Vxlan.h | 10 +- > 14 files changed, 845 insertions(+), 334 deletions(-) > > diff --git a/datapath-windows/ovsext/Actions.c b/datapath- > windows/ovsext/Actions.c > index 722a2a8..9905a68 100644 > --- a/datapath-windows/ovsext/Actions.c > +++ b/datapath-windows/ovsext/Actions.c > @@ -301,7 +301,6 @@ OvsDetectTunnelPkt(OvsForwardingContext > *ovsFwdCtx, > return TRUE; > } > } else if (OvsIsTunnelVportType(dstVport->ovsType)) { > - ASSERT(ovsFwdCtx->tunnelTxNic == NULL); > ASSERT(ovsFwdCtx->tunnelRxNic == NULL); > > /* > @@ -667,41 +666,36 @@ 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; > > - /* Do the encap. Encap function does not consume the NBL. */ > + OVS_FWD_INFO switchFwdInfo = { 0 }; > + /* Do the encapsulation. The encapsulation will 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; > case OVS_VPORT_TYPE_GENEVE: > status = OvsEncapGeneve(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, > &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, > - &ovsFwdCtx->layers, &newNbl); > + &ovsFwdCtx->layers, &newNbl, &switchFwdInfo); > break; > default: > ASSERT(! "Tx: Unhandled tunnel type"); > @@ -710,16 +704,19 @@ 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"); > + L"Complete after cloning NBL for encapsulation"); > ovsFwdCtx->curNbl = newNbl; > status = OvsDoFlowLookupOutput(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, > @@ -955,12 +952,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; > @@ -970,7 +966,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), > @@ -1060,7 +1056,7 @@ OvsOutputBeforeSetAction(OvsForwardingContext > *ovsFwdCtx) > * -------------------------------------------------------------------------- > * OvsPopFieldInPacketBuf -- > * Function to pop a specified field of length 'shiftLength' located at > - * 'shiftOffset' from the ethernet header. The data on the left of the > + * 'shiftOffset' from the Ethernet header. The data on the left of the > * 'shiftOffset' is right shifted. > * > * Returns a pointer to the new start in 'bufferData'. > @@ -1114,6 +1110,9 @@ OvsPopFieldInPacketBuf(OvsForwardingContext > *ovsFwdCtx, > /* Bail out if L2 + shiftLength is not contiguous in the first buffer. */ > if (MIN(packetLen, mdlLen) < sizeof(EthHdr) + shiftLength) { > ASSERT(FALSE); > + OvsCompleteNBLForwardingCtx(ovsFwdCtx, > + L"Dropped due to the buffer is not" > + L"contiguous"); > return NDIS_STATUS_FAILURE; > } > bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > diff --git a/datapath-windows/ovsext/Geneve.c b/datapath- > windows/ovsext/Geneve.c > index 5712e4d..4140a40 100644 > --- a/datapath-windows/ovsext/Geneve.c > +++ b/datapath-windows/ovsext/Geneve.c > @@ -72,7 +72,8 @@ NDIS_STATUS OvsEncapGeneve(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; > @@ -104,6 +105,8 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY > vport, > return NDIS_STATUS_FAILURE; > } > > + RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof > fwdInfo.value); > + > curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > diff --git a/datapath-windows/ovsext/Geneve.h b/datapath- > windows/ovsext/Geneve.h > index 057f80a..be8a834 100644 > --- a/datapath-windows/ovsext/Geneve.h > +++ b/datapath-windows/ovsext/Geneve.h > @@ -19,6 +19,9 @@ > #define __GENEVE_H_ 1 > > #include "NetProto.h" > + > +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; > + > typedef struct _OVS_GENEVE_VPORT { > UINT16 dstPort; > UINT64 filterID; > @@ -87,7 +90,8 @@ NDIS_STATUS OvsEncapGeneve(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 OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, > PNET_BUFFER_LIST curNbl, > diff --git a/datapath-windows/ovsext/Gre.c b/datapath- > windows/ovsext/Gre.c > index 1976b08..cb8c792 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; > diff --git a/datapath-windows/ovsext/Gre.h b/datapath- > windows/ovsext/Gre.h > index 7e20ced..c45df8f 100644 > --- a/datapath-windows/ovsext/Gre.h > +++ b/datapath-windows/ovsext/Gre.h > @@ -17,8 +17,11 @@ > #ifndef __GRE_H_ > #define __GRE_H_ 1 > > -#include "NetProto.h" > #include "Flow.h" > +#include "IpHelper.h" > +#include "NetProto.h" > + > +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; > > typedef struct _OVS_GRE_VPORT { > UINT64 ipId; > @@ -66,7 +69,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 d747e8c..cf10560 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,70 @@ 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) { > + status = STATUS_SUCCESS; > + size_t len = 0; > + minMetric = crtRoute.Metric; > + LOCK_STATE_EX lockState; > + > + 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); > + > + if (gOvsSwitchContext != NULL) { > + NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, > + &lockState, 0); > + *vport = OvsFindVportByHvNameW(gOvsSwitchContext, > + interfaceName, > + len); > + NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, > &lockState); > + } > + } > + ExReleaseResourceLite(&crtInstance->lock); > } > + ExReleaseResourceLite(&ovsInstanceListLock); > > OvsDumpRoute(sourceAddress, destinationAddress, route); > + > return status; > } > > @@ -358,8 +420,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 +483,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 +492,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 +501,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 +510,245 @@ 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)) { > + > + instance->isIpConfigured = FALSE; > + ExReleaseResourceLite(&instance->lock); > + > + 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; > + LOCK_STATE_EX lockState; > + > + 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); > + if (gOvsSwitchContext == NULL) { > + goto error; > + } > + NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, > &lockState, 0); > + POVS_VPORT_ENTRY vport = > OvsFindVportByHvNameW(gOvsSwitchContext, > + interfaceName, > + sizeof(WCHAR) * > + > wcslen(interfaceName)); > + > + if (vport != NULL) { > + RtlCopyMemory(&instance->netCfgId, > + &vport->netCfgInstanceId, > + sizeof(instance->netCfgId)); > + instance->portNo = vport->portNo; > + } > + NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); > + 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; > + } > > - OvsCleanupIpHelperRequestList(); > + status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid, > + &instance->internalIPRow); > > - OvsCleanupFwdTable(); > + 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]); > + } > + > + 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 +780,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 +821,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 +853,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."); > @@ -651,7 +972,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 +980,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 +1003,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 +1031,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX > prefix) > { > > PLIST_ENTRY link; > - POVS_IPFORWARD_ENTRY ipfEntry; > UINT32 hash; > ASSERT(prefix->Prefix.si_family == AF_INET); > > @@ -720,6 +1041,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 +1058,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 +1083,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 +1093,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 +1114,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 +1123,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 > ipNeigh) > static POVS_IPFORWARD_ENTRY > OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute) > { > - > POVS_IPFORWARD_ENTRY entry; > > ASSERT(ipRoute); > @@ -876,12 +1200,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 +1221,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); > } > @@ -919,10 +1245,10 @@ static VOID > OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn) > { > PLIST_ENTRY link; > - POVS_IPNEIGH_ENTRY entry; > > if (!IsListEmpty(&ovsSortedIPNeighList)) { > link = ovsSortedIPNeighList.Blink; > + POVS_IPNEIGH_ENTRY entry; > entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); > if (entry->timeout > ipn->timeout) { > ipn->timeout++; > @@ -973,11 +1299,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,16 +1318,17 @@ 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) { > - ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); > - OvsRemoveIPNeighEntry(ipn); > - } > + LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) { > + POVS_IPNEIGH_ENTRY ipn; > + > + ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); > + OvsRemoveIPNeighEntry(ipn); > + } > } > for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) { > ASSERT(IsListEmpty(&ovsFwdHashTable[i])); > @@ -1017,20 +1345,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 +1380,40 @@ OvsWakeupIPHelper(VOID) > } > > VOID > -OvsInternalAdapterDown(VOID) > +OvsInternalAdapterDown(UINT32 portNo, > + GUID netCfgInstanceId) > { > - NdisAcquireSpinLock(&ovsIpHelperLock); > - ovsInternalAdapterUp = FALSE; > - ovsInternalIPConfigured = FALSE; > - NdisReleaseSpinLock(&ovsIpHelperLock); > + POVS_IP_HELPER_REQUEST request; > > - OvsCleanupIpHelperRequestList(); > + request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag( > + sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG); > + if (request == NULL) { > + OVS_LOG_ERROR("Fail to initialize Internal Adapter"); > + return; > + } > + RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST)); > + RtlCopyMemory(&request->instanceReq.netCfgInstanceId, > + &netCfgInstanceId, > + sizeof(netCfgInstanceId)); > + request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN; > + request->instanceReq.portNo = portNo; > > - OvsCleanupFwdTable(); > + NdisAcquireSpinLock(&ovsIpHelperLock); > + InsertHeadList(&ovsIpHelperRequestList, &request->link); > + ovsNumIpHelperRequests++; > + if (ovsNumIpHelperRequests == 1) { > + OvsWakeupIPHelper(); > + } > + NdisReleaseSpinLock(&ovsIpHelperLock); > } > > > 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 +1421,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 +1437,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) > { > + UNREFERENCED_PARAMETER(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_ERROR("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]); > + } > > - 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 +1573,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) { > @@ -1212,7 +1625,7 @@ > OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request) > NTSTATUS status; > MIB_IPFORWARD_ROW2 ipRoute; > MIB_IPNET_ROW2 ipNeigh; > - OVS_FWD_INFO fwdInfo; > + OVS_FWD_INFO fwdInfo = { 0 }; > UINT32 ipAddr; > UINT32 srcAddr; > POVS_FWD_ENTRY fwdEntry = NULL; > @@ -1222,6 +1635,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 +1650,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); > - if (status != STATUS_SUCCESS) { > + status = OvsGetRoute(&dst, &ipRoute, &src, &instance, &fwdInfo.vport); > + if (status != STATUS_SUCCESS || instance == NULL) { > + 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 +1672,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 +1697,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 +1715,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,22 +1732,26 @@ 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; > } > newFWD = TRUE; > - /* > - * Cache the result > - */ > - OvsAddIPFwdCache(fwdEntry, ipf, ipn); > - NdisReleaseRWLock(ovsTableLock, &lockState); > + if (status == STATUS_SUCCESS) { > + /* > + * Cache the result > + */ > + OvsAddIPFwdCache(fwdEntry, ipf, ipn); > + NdisReleaseRWLock(ovsTableLock, &lockState); > + ExReleaseResourceLite(&instance->lock); > + } > > fwd_handle_nbl: > > @@ -1389,7 +1818,6 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr, > (const PVOID)ipNeigh->PhysicalAddress, > (size_t)ETH_ADDR_LEN)) { > PLIST_ENTRY link; > - POVS_FWD_ENTRY fwdEntry; > NdisReleaseRWLock(ovsTableLock, &lockState); > /* > * need update, release and acquire write lock > @@ -1405,6 +1833,7 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr, > } > > LIST_FORALL(&ipn->fwdList, link) { > + POVS_FWD_ENTRY fwdEntry; > fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink); > RtlCopyMemory(fwdEntry->info.dstMacAddr, > ipNeigh->PhysicalAddress, ETH_ADDR_LEN); > @@ -1423,28 +1852,15 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr, > NdisReleaseRWLock(ovsTableLock, &lockState); > } > > - > -static VOID > -OvsHandleIPNeighTimeout(UINT32 ipAddr) > -{ > - MIB_IPNET_ROW2 ipNeigh; > - NTSTATUS status; > - > - status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh); > - > - OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); > -} > - > - > /* > > *---------------------------------------------------------------------------- > - * 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 +1870,16 @@ 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; > + KeQuerySystemTime((LARGE_INTEGER *)&timeout); > + timeout += OVS_IPNEIGH_TIMEOUT; > while (!IsListEmpty(&ovsIpHelperRequestList)) { > + ovsNumIpHelperRequests--; > if (context->exit) { > goto ip_helper_wait; > } > @@ -1474,6 +1891,45 @@ OvsStartIpHelper(PVOID data) > case OVS_IP_HELPER_INTERNAL_ADAPTER_UP: > OvsHandleInternalAdapterUp(req); > break; > + case OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN: > + { > + PLIST_ENTRY head, link, next; > + UINT32 portNo = req->instanceReq.portNo; > + GUID netCfgInstanceId = req->instanceReq.netCfgInstanceId; > + > + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); > + head = &ovsInstanceList; > + LIST_FORALL_SAFE(head, link, next) { > + POVS_IPHELPER_INSTANCE instance = NULL; > + LOCK_STATE_EX lockState; > + > + instance = CONTAINING_RECORD(link, > OVS_IPHELPER_INSTANCE, link); > + > + ExAcquireResourceExclusiveLite(&instance->lock, TRUE); > + if (instance->portNo == portNo && > + IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) > { > + > + NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); > + OvsRemoveAllFwdEntriesWithSrc(instance->ipAddress); > + NdisReleaseRWLock(ovsTableLock, &lockState); > + > + RemoveEntryList(&instance->link); > + > + ExReleaseResourceLite(&instance->lock); > + > + OvsIpHelperDeleteInstance(instance); > + break; > + } > + ExReleaseResourceLite(&instance->lock); > + } > + > + if (IsListEmpty(&ovsInstanceList)) { > + OvsCleanupIpHelperRequestList(); > + > + OvsCleanupFwdTable(); > + } > + ExReleaseResourceLite(&ovsInstanceListLock); > + } > case OVS_IP_HELPER_FWD_REQUEST: > OvsHandleFwdRequest(req); > break; > @@ -1500,10 +1956,18 @@ OvsStartIpHelper(PVOID data) > break; > } > ipAddr = ipn->ipAddr; > - > + MIB_IPNET_ROW2 ipNeigh; > + NTSTATUS status; > + POVS_IPHELPER_INSTANCE instance = > (POVS_IPHELPER_INSTANCE)ipn->context; > + MIB_IF_ROW2 internalRow = instance->internalRow; > NdisReleaseSpinLock(&ovsIpHelperLock); > + ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE); > + > + status = OvsGetOrResolveIPNeigh(internalRow, > + ipAddr, &ipNeigh); > + OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); > > - OvsHandleIPNeighTimeout(ipAddr); > + ExReleaseResourceLite(&ovsInstanceListLock); > > NdisAcquireSpinLock(&ovsIpHelperLock); > } > @@ -1526,7 +1990,6 @@ ip_helper_wait: > NdisReleaseSpinLock(&ovsIpHelperLock); > OvsCleanupFwdTable(); > OvsCleanupIpHelperRequestList(); > - > OVS_LOG_INFO("Terminating the OVS IP Helper system thread"); > > PsTerminateSystemThread(STATUS_SUCCESS); > @@ -1536,7 +1999,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 +2013,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 +2024,9 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) > ipRouteNotificationHandle = NULL; > unicastIPNotificationHandle = NULL; > > + ExInitializeResourceLite(&ovsInstanceListLock); > + InitializeListHead(&ovsInstanceList); > + > if (ovsFwdHashTable == NULL || > ovsRouteHashTable == NULL || > ovsNeighHashTable == NULL || > @@ -1625,6 +2086,7 @@ init_cleanup: > NdisFreeRWLock(ovsTableLock); > ovsTableLock = NULL; > } > + ExDeleteResourceLite(&ovsInstanceListLock); > NdisFreeSpinLock(&ovsIpHelperLock); > } > return STATUS_SUCCESS; > @@ -1651,6 +2113,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..fb695b8 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 { > @@ -51,15 +53,16 @@ typedef struct _OVS_IPFORWARD_ENTRY { > LIST_ENTRY fwdList; > } OVS_IPFORWARD_ENTRY, *POVS_IPFORWARD_ENTRY; > > -typedef union _OVS_FWD_INFO { > +typedef union _OVS_FWD_INFO { > struct { > UINT32 dstIpAddr; > UINT32 srcIpAddr; > 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 { > @@ -74,6 +77,7 @@ typedef struct _OVS_FWD_ENTRY { > > enum { > OVS_IP_HELPER_INTERNAL_ADAPTER_UP, > + OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN, > OVS_IP_HELPER_FWD_REQUEST, > }; > > @@ -94,13 +98,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 +122,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/Stt.c b/datapath-windows/ovsext/Stt.c > index ad322d2..5019e3f 100644 > --- a/datapath-windows/ovsext/Stt.c > +++ b/datapath-windows/ovsext/Stt.c > @@ -107,7 +107,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; > @@ -123,6 +124,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 1b7e797..988a1c1 100644 > --- a/datapath-windows/ovsext/Stt.h > +++ b/datapath-windows/ovsext/Stt.h > @@ -17,6 +17,10 @@ > #ifndef __OVS_STT_H_ > #define __OVS_STT_H_ 1 > > +#include "IpHelper.h" > + > +typedef union _OVS_FWD_INFO *POVS_FWD_INFO; > + > #define STT_TCP_PORT 7471 > #define STT_TCP_PORT_NBO 0x2f1d > > @@ -91,7 +95,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..b008431 100644 > --- a/datapath-windows/ovsext/Switch.h > +++ b/datapath-windows/ovsext/Switch.h > @@ -103,7 +103,7 @@ typedef struct _OVS_SWITCH_CONTEXT > * > * The "real" physical external NIC has 'NicIndex' > 0. For each > * external interface, virtual or physical, NDIS gives an NIC level > - * OID callback. Note that, even though there are multile "NICs", > + * OID callback. Note that, even though there are multiple "NICs", > * there's only one underlying Hyper-V port. Thus, we get a single > * NDIS port-level callback, but multiple NDIS NIC-level callbacks. > * > @@ -128,8 +128,10 @@ typedef struct _OVS_SWITCH_CONTEXT > */ > 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 22741db..efb4b08 100644 > --- a/datapath-windows/ovsext/Vport.c > +++ b/datapath-windows/ovsext/Vport.c > @@ -82,8 +82,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, > @@ -97,7 +95,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); > > /* > @@ -340,7 +338,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); > @@ -434,7 +432,7 @@ HvConnectNic(POVS_SWITCH_CONTEXT > switchContext, > NdisReleaseRWLock(switchContext->dispatchLock, &lockState); > > if (nicParam->NicType == NdisSwitchNicTypeInternal) { > - OvsInternalAdapterUp(&nicParam->NetCfgInstanceId); > + OvsInternalAdapterUp(vport->portNo, &vport->netCfgInstanceId); > } > > done: > @@ -471,7 +469,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; > } > > @@ -608,13 +606,15 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT > switchContext, > * point, userspace should not be able to access this port. > */ > if (OvsIsRealExternalVport(vport)) { > - OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE); > + OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE); > OvsPostEvent(&event); > } > NdisReleaseRWLock(switchContext->dispatchLock, &lockState); > > if (isInternalPort) { > - OvsInternalAdapterDown(); > + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); > + OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE); > + OvsPostEvent(&event); > } > > done: > @@ -870,10 +870,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; > @@ -980,6 +976,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)); > @@ -1106,19 +1104,26 @@ > 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; > + NTSTATUS status = STATUS_SUCCESS; > WCHAR interfaceName[IF_MAX_STRING_SIZE + 1]; > NET_LUID interfaceLuid; > size_t len; > > - 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) { > /* > @@ -1174,7 +1179,7 @@ > UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext, > case NdisSwitchPortTypeInternal: > ASSERT(vport->isBridgeInternal == FALSE); > switchContext->internalPortId = vport->portId; > - switchContext->internalVport = vport; > + switchContext->countInternalVports++; > break; > case NdisSwitchPortTypeSynthetic: > case NdisSwitchPortTypeEmulated: > @@ -1292,8 +1297,9 @@ OvsRemoveAndDeleteVport(PVOID > usrParamsContext, > 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; > } > @@ -1564,7 +1570,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT > switchContext) > } > > ASSERT(switchContext->virtualExternalVport == NULL); > - ASSERT(switchContext->internalVport == NULL); > + ASSERT(switchContext->countInternalVports == 0); > } > > > @@ -2246,12 +2252,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) { > @@ -2315,8 +2321,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 1f4968e..a7141d7 100644 > --- a/datapath-windows/ovsext/Vport.h > +++ b/datapath-windows/ovsext/Vport.h > @@ -26,7 +26,7 @@ > #define OVS_MAX_DPPORTS MAXUINT16 > #define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS > /* > - * The local port (0) is a reserved port, that is not allowed to be be > + * The local port (0) is a reserved port, that is not allowed to be > * created by the netlink command vport add. On linux, this port is created > * at netlink command datapath new. However, on windows, we do not > need to > * create it, and more, we shouldn't. The userspace attempts to create two > @@ -80,38 +80,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 > @@ -126,12 +127,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; > @@ -143,6 +144,8 @@ 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); > @@ -261,7 +264,7 @@ GetPortFromPriv(POVS_VPORT_ENTRY vport) > UINT16 dstPort = 0; > PVOID vportPriv = GetOvsVportPriv(vport); > > - /* XXX would better to have a commom tunnel "parent" structure */ > + /* XXX would better to have a common tunnel "parent" structure */ > ASSERT(vportPriv); > switch(vport->ovsType) { > case OVS_VPORT_TYPE_GRE: > @@ -273,7 +276,7 @@ GetPortFromPriv(POVS_VPORT_ENTRY vport) > dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort; > break; > case OVS_VPORT_TYPE_GENEVE: > - dstPort = ((POVS_GENEVE_VPORT) vportPriv)->dstPort; > + dstPort = ((POVS_GENEVE_VPORT)vportPriv)->dstPort; > break; > default: > ASSERT(! "Port is not a tunnel port"); > diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath- > windows/ovsext/Vxlan.c > index ddd8d8e..82d0abe 100644 > --- a/datapath-windows/ovsext/Vxlan.c > +++ b/datapath-windows/ovsext/Vxlan.c > @@ -334,7 +334,7 @@ ret_error: > > *---------------------------------------------------------------------------- > * OvsEncapVxlan -- > * Encapsulates the packet if L2/L3 for destination resolves. Otherwise, > - * enqueues a callback that does encapsulatation after resolution. > + * enqueues a callback that does encapsulation after resolution. > > *---------------------------------------------------------------------------- > */ > NDIS_STATUS > @@ -343,7 +343,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; > @@ -351,7 +352,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. > @@ -362,6 +362,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..f4a8bce 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; > @@ -31,7 +35,8 @@ typedef struct _OVS_VXLAN_VPORT { > typedef struct VXLANHdr { > /* Flags. */ > UINT32 flags1:2; > - /* Packet needs replication to multicast group (used for multicast > proxy). > */ > + /* Packet needs replication to multicast group (used for multicast > proxy). > + */ > UINT32 locallyReplicate:1; > /* Instance ID flag, must be set to 1. */ > UINT32 instanceID:1; > @@ -64,7 +69,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 > [email protected] > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
