On 15 December 2016 at 11:39, Alin Serdean <aserd...@cloudbasesolutions.com> wrote:
> > 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> > This needs a Signed-off-by from Sorin > Acked-by: Paul Boca <pb...@cloudbasesolutions.com> > I get a conflict with this patch. Please rebase. > --- > v7: Rebase > v6: Rebase > v5: Rebase > v4: Address comments (fix aligment, switch goto labels) > v3: Add acked > v2: Rebase > --- > datapath-windows/ovsext/Actions.c | 42 +- > datapath-windows/ovsext/Geneve.c | 7 +- > datapath-windows/ovsext/Geneve.h | 6 +- > datapath-windows/ovsext/Gre.c | 7 +- > datapath-windows/ovsext/Gre.h | 8 +- > datapath-windows/ovsext/IpHelper.c | 919 +++++++++++++++++++++++++++--- > ------- > datapath-windows/ovsext/IpHelper.h | 22 +- > datapath-windows/ovsext/Stt.c | 7 +- > datapath-windows/ovsext/Stt.h | 7 +- > datapath-windows/ovsext/Switch.h | 9 +- > datapath-windows/ovsext/Vport.c | 131 +++--- > datapath-windows/ovsext/Vport.h | 104 ++--- > datapath-windows/ovsext/Vxlan.c | 10 +- > datapath-windows/ovsext/Vxlan.h | 10 +- > 14 files changed, 864 insertions(+), 425 deletions(-) > > diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/ > Actions.c > index 9a58fbd..8ba977f 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); > > /* > @@ -322,7 +321,7 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, > > if (!vport || > (vport->ovsType != OVS_VPORT_TYPE_NETDEV && > - !OvsIsBridgeInternalVport(vport) && > + vport->ovsType != OVS_VPORT_TYPE_INTERNAL && > !OvsIsTunnelVportType(vport->ovsType))) { > ovsFwdCtx->tunKey.dst = 0; > } > @@ -403,10 +402,6 @@ OvsAddPorts(OvsForwardingContext *ovsFwdCtx, > vport->stats.txBytes += > NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB( > ovsFwdCtx->curNbl)); > > - if (OvsIsBridgeInternalVport(vport)) { > - return NDIS_STATUS_SUCCESS; > - } > - > if (OvsDetectTunnelPkt(ovsFwdCtx, vport, flowKey)) { > return NDIS_STATUS_SUCCESS; > } > @@ -668,41 +663,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 }; > + /* Apply 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"); > @@ -711,8 +701,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; > @@ -720,7 +713,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, > @@ -956,12 +949,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; > @@ -971,7 +963,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), > @@ -1061,7 +1053,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'. > diff --git a/datapath-windows/ovsext/Geneve.c b/datapath-windows/ovsext/ > Geneve.c > index efdf9f7..d38a656 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; > @@ -90,7 +91,7 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport, > ULONG mss = 0; > NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > > - status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > + status = OvsLookupIPFwdInfo(tunKey->src, tunKey->dst, &fwdInfo); > if (status != STATUS_SUCCESS) { > OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); > // return NDIS_STATUS_PENDING; > @@ -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 7d6c0a2..c5da064 100644 > --- a/datapath-windows/ovsext/Gre.c > +++ b/datapath-windows/ovsext/Gre.c > @@ -96,17 +96,20 @@ 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; > > - status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > + status = OvsLookupIPFwdInfo(tunKey->src, tunKey->dst, &fwdInfo); > if (status != STATUS_SUCCESS) { > OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); > 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 636cf95..0220572 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,44 @@ > #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 > @@ -82,9 +100,22 @@ static OVS_IP_HELPER_THREAD_CONTEXT > ovsIpHelperThreadContext; > static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX > prefix); > static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf); > static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr); > +static VOID OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo); > 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 > +OvsDumpMessageWithGuid(char* message, GUID guid) > +{ > + OVS_LOG_INFO(message, guid.Data1, guid.Data2, guid.Data3, > + *(UINT16 *)guid.Data4, guid.Data4[2], guid.Data4[3], > + guid.Data4[4], guid.Data4[5], guid.Data4[6], > guid.Data4[7]); > +} > > static VOID > OvsDumpIfRow(PMIB_IF_ROW2 ifRow) > @@ -94,17 +125,9 @@ OvsDumpIfRow(PMIB_IF_ROW2 ifRow) > ifRow->InterfaceLuid.Info.IfType); > OVS_LOG_INFO("InterfaceIndex: %d", ifRow->InterfaceIndex); > > - OVS_LOG_INFO("Interface GUID: %08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > - ifRow->InterfaceGuid.Data1, > - ifRow->InterfaceGuid.Data2, > - ifRow->InterfaceGuid.Data3, > - *(UINT16 *)ifRow->InterfaceGuid.Data4, > - ifRow->InterfaceGuid.Data4[2], > - ifRow->InterfaceGuid.Data4[3], > - ifRow->InterfaceGuid.Data4[4], > - ifRow->InterfaceGuid.Data4[5], > - ifRow->InterfaceGuid.Data4[6], > - ifRow->InterfaceGuid.Data4[7]); > + OvsDumpMessageWithGuid("Interface GUID: " > + "%08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > + ifRow->InterfaceGuid); > OVS_LOG_INFO("Perm MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", > ifRow->PermanentPhysicalAddress[0], > ifRow->PermanentPhysicalAddress[1], > @@ -114,7 +137,6 @@ OvsDumpIfRow(PMIB_IF_ROW2 ifRow) > ifRow->PermanentPhysicalAddress[5]); > } > > - > static VOID > OvsDumpIfTable(PMIB_IF_TABLE2 ifTable) > { > @@ -325,30 +347,72 @@ 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, > + UINT32 srcIp) > { > - NTSTATUS status; > + NTSTATUS status = STATUS_NETWORK_UNREACHABLE; > + NTSTATUS result = STATUS_SUCCESS; > + PLIST_ENTRY head, link, next; > + ULONG minMetric = MAXULONG; > > 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) { > + 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 && > + (!srcIp || srcIp == crtSrcAddr.Ipv4.sin_addr.S_un.S_addr)) { > + 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 +422,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 +485,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 +494,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 +503,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 +512,225 @@ 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); > > - OvsCleanupIpHelperRequestList(); > + if (found != TRUE) { > + NTSTATUS status; > + POVS_IPHELPER_INSTANCE instance = NULL; > + MIB_UNICASTIPADDRESS_ROW ipEntry; > + BOOLEAN error = TRUE; > + LOCK_STATE_EX lockState; > > - OvsCleanupFwdTable(); > + 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) { > + OvsDumpMessageWithGuid("Fail to get IF entry for internal > port with GUID" > + " %08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > + instance->netCfgId); > + 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) { > + OvsDumpMessageWithGuid("Failed to get IP entry for internal > port with GUID" > + " %08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > + instance->netCfgId); > + } > + > + 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,10 +762,21 @@ OvsChangeCallbackIpRoute(PVOID context, > > case MibParameterNotification: > case MibDeleteInstance: > + { > ASSERT(ipRoute); > ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr; > nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr; > > + POVS_IPFORWARD_ENTRY ipf; > + LOCK_STATE_EX lockState; > + > + NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); > + ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix); > + if (ipf != NULL) { > + 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, > @@ -541,24 +785,8 @@ OvsChangeCallbackIpRoute(PVOID context, > (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff, > notificationType == MibDeleteInstance ? "deleted" : > "modified"); > - > - if (ipRoute->InterfaceLuid.Info.NetLuidIndex == > - ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && > - ipRoute->InterfaceLuid.Info.IfType == > - ovsInternalRow.InterfaceLuid.Info.IfType && > - ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) { > - > - POVS_IPFORWARD_ENTRY ipf; > - LOCK_STATE_EX lockState; > - > - NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); > - ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix); > - if (ipf != NULL) { > - OvsRemoveIPForwardEntry(ipf); > - } > - NdisReleaseRWLock(ovsTableLock, &lockState); > - } > break; > + } > > case MibInitialNotification: > OVS_LOG_INFO("Get Initial notification for IP Route change."); > @@ -579,40 +807,85 @@ 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 +924,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 +932,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 +955,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 +983,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) > { > > PLIST_ENTRY link; > - POVS_IPFORWARD_ENTRY ipfEntry; > UINT32 hash; > ASSERT(prefix->Prefix.si_family == AF_INET); > > @@ -720,6 +993,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 == > @@ -732,15 +1007,17 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) > > > static POVS_FWD_ENTRY > -OvsLookupIPFwdEntry(UINT32 dstIp) > +OvsLookupIPFwdEntry(UINT32 srcIp, 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) { > + if (entry->info.dstIpAddr == dstIp && > + (!srcIp || entry->info.srcIpAddr == srcIp)) { > return entry; > } > } > @@ -749,7 +1026,8 @@ OvsLookupIPFwdEntry(UINT32 dstIp) > > > NTSTATUS > -OvsLookupIPFwdInfo(UINT32 dstIp, > +OvsLookupIPFwdInfo(UINT32 srcIp, > + UINT32 dstIp, > POVS_FWD_INFO info) > { > POVS_FWD_ENTRY entry; > @@ -757,11 +1035,10 @@ OvsLookupIPFwdInfo(UINT32 dstIp, > NTSTATUS status = STATUS_NOT_FOUND; > > NdisAcquireRWLockRead(ovsTableLock, &lockState, 0); > - entry = OvsLookupIPFwdEntry(dstIp); > + entry = OvsLookupIPFwdEntry(srcIp, 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 +1047,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 +1068,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 +1077,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) > static POVS_IPFORWARD_ENTRY > OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute) > { > - > POVS_IPFORWARD_ENTRY entry; > > ASSERT(ipRoute); > @@ -876,12 +1154,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 +1175,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 +1199,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 +1253,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); > @@ -988,19 +1269,38 @@ OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr) > > > static VOID > +OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo) > +{ > + UINT32 i; > + 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.srcPortNo == portNo) { > + OvsRemoveFwdEntry(fwdEntry); > + } > + } > + } > +} > + > +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 +1317,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 +1352,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 +1393,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) { > @@ -1099,58 +1411,116 @@ 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) { > + OvsDumpMessageWithGuid("Fail to get IF entry for internal > port with GUID" > + " %08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > + instance->netCfgId); > + 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) { > + OvsDumpMessageWithGuid("Fail to get IP entry for internal > port with GUID" > + " %08x-%04x-%04x-%04x-%02x%02x% > 02x%02x%02x%02x", > + instance->netCfgId); > + } > > - 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); > } > } > > @@ -1158,15 +1528,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) { > @@ -1214,7 +1580,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; > @@ -1224,8 +1590,10 @@ 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, > + status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.src, > + request->fwdReq.tunnelKey.dst, > &fwdInfo); > if (status == STATUS_SUCCESS) { > goto fwd_handle_nbl; > @@ -1238,10 +1606,23 @@ 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, > request->fwdReq.tunnelKey.src); > + if (request->fwdReq.tunnelKey.src && request->fwdReq.tunnelKey.src != > src.Ipv4.sin_addr.s_addr) { > + 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; > + } > + 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 */ > @@ -1254,13 +1635,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; > } > > @@ -1276,6 +1660,7 @@ fwd_request_done: > ipf = OvsCreateIPForwardEntry(&ipRoute); > if (ipf == NULL) { > NdisReleaseRWLock(ovsTableLock, &lockState); > + ExReleaseResourceLite(&instance->lock); > status = STATUS_INSUFFICIENT_RESOURCES; > goto fwd_handle_nbl; > } > @@ -1284,6 +1669,13 @@ fwd_request_done: > PLIST_ENTRY link; > link = ipf->fwdList.Flink; > fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink); > + if (fwdEntry->info.srcIpAddr != srcAddr) { > + OvsRemoveFwdEntry(fwdEntry); > + NdisReleaseRWLock(ovsTableLock, &lockState); > + ExReleaseResourceLite(&instance->lock); > + status = STATUS_INSUFFICIENT_RESOURCES; > + goto fwd_handle_nbl; > + } > srcAddr = fwdEntry->info.srcIpAddr; > } > > @@ -1293,9 +1685,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; > } > @@ -1309,22 +1702,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: > > @@ -1391,7 +1788,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 > @@ -1407,6 +1803,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); > @@ -1425,28 +1822,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 > @@ -1479,6 +1863,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); > + OvsRemoveAllFwdEntriesWithPort > No(instance->portNo); > + 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; > @@ -1506,10 +1929,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); > > - OvsHandleIPNeighTimeout(ipAddr); > + status = OvsGetOrResolveIPNeigh(internalRow, > + ipAddr, &ipNeigh); > + OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); > + > + ExReleaseResourceLite(&ovsInstanceListLock); > > NdisAcquireSpinLock(&ovsIpHelperLock); > } > @@ -1537,7 +1968,6 @@ ip_helper_wait: > NdisReleaseSpinLock(&ovsIpHelperLock); > OvsCleanupFwdTable(); > OvsCleanupIpHelperRequestList(); > - > OVS_LOG_INFO("Terminating the OVS IP Helper system thread"); > > PsTerminateSystemThread(STATUS_SUCCESS); > @@ -1547,7 +1977,7 @@ ip_helper_wait: > NTSTATUS > OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) > { > - NTSTATUS status; > + NTSTATUS status = NDIS_STATUS_SUCCESS; > HANDLE threadHandle; > UINT32 i; > > @@ -1560,12 +1990,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); > @@ -1577,6 +2001,9 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) > ipRouteNotificationHandle = NULL; > unicastIPNotificationHandle = NULL; > > + ExInitializeResourceLite(&ovsInstanceListLock); > + InitializeListHead(&ovsInstanceList); > + > if (ovsFwdHashTable == NULL || > ovsRouteHashTable == NULL || > ovsNeighHashTable == NULL || > @@ -1636,6 +2063,7 @@ init_cleanup: > NdisFreeRWLock(ovsTableLock); > ovsTableLock = NULL; > } > + ExDeleteResourceLite(&ovsInstanceListLock); > NdisFreeSpinLock(&ovsIpHelperLock); > } > return STATUS_SUCCESS; > @@ -1662,6 +2090,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..6bda1b1 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,15 +122,15 @@ 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, > OvsIPHelperCallback cb, > PVOID cbData1, > PVOID cbData2); > -NTSTATUS OvsLookupIPFwdInfo(UINT32 dstIp, POVS_FWD_INFO info); > +NTSTATUS OvsLookupIPFwdInfo(UINT32 srcIp, UINT32 dstIp, POVS_FWD_INFO > info); > VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl); > > #endif /* __IP_HELPER_H_ */ > diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c > index b04a77f..9da81dc 100644 > --- a/datapath-windows/ovsext/Stt.c > +++ b/datapath-windows/ovsext/Stt.c > @@ -107,13 +107,14 @@ 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; > > UNREFERENCED_PARAMETER(switchContext); > - status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > + status = OvsLookupIPFwdInfo(tunKey->src, tunKey->dst, &fwdInfo); > if (status != STATUS_SUCCESS) { > OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); > /* > @@ -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..7c98621 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. > * > @@ -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 428259b..e9e22aa 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,8 +95,11 @@ 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); > +static NTSTATUS OvsConvertIfCountedStrToAnsiStr(PIF_COUNTED_STRING wStr, > + CHAR *str, > + UINT16 maxStrLen); > > /* > * ------------------------------------------------------------ > -------------- > @@ -340,7 +341,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); > @@ -350,26 +351,46 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext, > * from the parent external port. > */ > if (OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { > - NDIS_SWITCH_PORT_PARAMETERS portParam; > - POVS_VPORT_ENTRY virtExtVport = > - (POVS_VPORT_ENTRY)switchContext->virtualExternalVport; > - > - ASSERT(virtExtVport); > + /* The VPORT can be bound to OVS datapath already. Search for it > + * using its friendly name and if not found allocate a new port > + */ > ASSERT(OvsFindVportByPortIdAndNicIndex(switchContext, > nicParam->PortId, > nicParam->NicIndex) == > NULL); > - OvsCopyPortParamsFromVport(virtExtVport, &portParam); > + char convertString[256]; > + RtlZeroMemory(convertString, 256); > NdisReleaseRWLock(switchContext->dispatchLock, &lockState); > - status = HvCreatePort(switchContext, &portParam, > - nicParam->NicIndex); > + status = OvsConvertIfCountedStrToAnsiStr(&portFriendlyName, > + convertString, > + > OVS_MAX_PORT_NAME_LENGTH); > NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, > 0); > if (status != NDIS_STATUS_SUCCESS) { > goto add_nic_done; > } > + POVS_VPORT_ENTRY ovsVport = OvsFindVportByOvsName(switchContext, > + convertString); > + if (ovsVport != NULL) { > + UpdateSwitchCtxWithVport(switchContext, ovsVport, FALSE); > + } else { > + NDIS_SWITCH_PORT_PARAMETERS portParam; > + POVS_VPORT_ENTRY virtExtVport = > + (POVS_VPORT_ENTRY)switchContext->virtualExternalVport; > + > + ASSERT(virtExtVport); > + OvsCopyPortParamsFromVport(virtExtVport, &portParam); > + NdisReleaseRWLock(switchContext->dispatchLock, &lockState); > + status = HvCreatePort(switchContext, &portParam, > + nicParam->NicIndex); > + NdisAcquireRWLockWrite(switchContext->dispatchLock, > &lockState, 0); > + if (status != NDIS_STATUS_SUCCESS) { > + goto add_nic_done; > + } > + } > } > > vport = OvsFindVportByPortIdAndNicIndex(switchContext, > nicParam->PortId, > nicParam->NicIndex); > + > if (vport == NULL) { > OVS_LOG_ERROR("Create NIC without Switch Port," > " PortId: %x, NicIndex: %d", > @@ -434,7 +455,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 +492,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; > } > > @@ -614,7 +635,9 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext, > NdisReleaseRWLock(switchContext->dispatchLock, &lockState); > > if (isInternalPort) { > - OvsInternalAdapterDown(); > + OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId); > + OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE); > + OvsPostVportEvent(&event); > } > > done: > @@ -870,10 +893,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; > @@ -920,7 +939,6 @@ OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport, > vport->portId = portParam->PortId; > vport->nicState = NdisSwitchNicStateUnknown; > vport->isExternal = FALSE; > - vport->isBridgeInternal = FALSE; > > switch (vport->portType) { > case NdisSwitchPortTypeExternal: > @@ -962,7 +980,6 @@ OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT > switchContext, > PNDIS_SWITCH_NIC_PARAMETERS nicParam) > { > ASSERT(vport->portId == nicParam->PortId); > - ASSERT(vport->ovsState == OVS_STATE_PORT_CREATED); > > UNREFERENCED_PARAMETER(switchContext); > > @@ -980,6 +997,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)); > @@ -1041,7 +1060,6 @@ OvsInitTunnelVport(PVOID userContext, > POVS_USER_PARAMS_CONTEXT usrParamsCtx = > (POVS_USER_PARAMS_CONTEXT)userContext; > > - vport->isBridgeInternal = FALSE; > vport->ovsType = ovsType; > vport->ovsState = OVS_STATE_PORT_CREATED; > switch (ovsType) { > @@ -1088,37 +1106,27 @@ OvsInitTunnelVport(PVOID userContext, > > /* > * ------------------------------------------------------------ > -------------- > - * Initializes a bridge internal vport ie. a port of type > - * OVS_VPORT_TYPE_INTERNAL but not present on the Hyper-V switch. > - * ------------------------------------------------------------ > -------------- > - */ > -NTSTATUS > -OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport) > -{ > - vport->isBridgeInternal = TRUE; > - vport->ovsType = OVS_VPORT_TYPE_INTERNAL; > - /* Mark the status to be connected, since there is no other > initialization > - * for this port. */ > - vport->ovsState = OVS_STATE_CONNECTED; > - return STATUS_SUCCESS; > -} > - > -/* > - * ------------------------------------------------------------ > -------------- > * 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) { > /* > @@ -1167,14 +1175,12 @@ UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT > switchContext, > if (vport->nicIndex == 0) { > switchContext->virtualExternalPortId = vport->portId; > switchContext->virtualExternalVport = vport; > - } else { > + } else if (newPort == TRUE) { > switchContext->numPhysicalNics++; > } > break; > case NdisSwitchPortTypeInternal: > - ASSERT(vport->isBridgeInternal == FALSE); > - switchContext->internalPortId = vport->portId; > - switchContext->internalVport = vport; > + switchContext->countInternalVports++; > break; > case NdisSwitchPortTypeSynthetic: > case NdisSwitchPortTypeEmulated: > @@ -1235,10 +1241,6 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT > switchContext, > switchContext->numNonHvVports++; > break; > } > - case OVS_VPORT_TYPE_INTERNAL: > - if (vport->isBridgeInternal) { > - switchContext->numNonHvVports++; > - } > default: > break; > } > @@ -1289,14 +1291,12 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext, > > switch (vport->ovsType) { > case OVS_VPORT_TYPE_INTERNAL: > - if (!vport->isBridgeInternal) { > - if (hvDelete && vport->isAbsentOnHv == FALSE) { > - switchContext->internalPortId = 0; > - switchContext->internalVport = NULL; > - OvsInternalAdapterDown(); > - } > - hvSwitchPort = TRUE; > + if (hvDelete && vport->isAbsentOnHv == FALSE) { > + switchContext->countInternalVports--; > + ASSERT(switchContext->countInternalVports >= 0); > + OvsInternalAdapterDown(vport->portNo, > vport->netCfgInstanceId); > } > + hvSwitchPort = TRUE; > break; > case OVS_VPORT_TYPE_VXLAN: > { > @@ -1557,14 +1557,13 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT > switchContext) > POVS_VPORT_ENTRY vport; > vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); > ASSERT(OvsIsTunnelVportType(vport->ovsType) || > - (vport->ovsType == OVS_VPORT_TYPE_INTERNAL && > - vport->isBridgeInternal) || vport->isAbsentOnHv == > TRUE); > + vport->isAbsentOnHv == TRUE); > OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, > TRUE); > } > } > > ASSERT(switchContext->virtualExternalVport == NULL); > - ASSERT(switchContext->internalVport == NULL); > + ASSERT(switchContext->countInternalVports == 0); > } > > > @@ -2246,12 +2245,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 +2314,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..4dc4e00 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,58 +80,44 @@ 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; > - /* > - * OVS userpace has a notion of bridges which basically defines an > - * L2-domain. Each "bridge" has an "internal" port of type > - * OVS_VPORT_TYPE_INTERNAL. Such a port is connected to the OVS > datapath in > - * one end, and the other end is a virtual adapter on the hypervisor > host. > - * This is akin to the Hyper-V "internal" NIC. It is intuitive to map > the > - * Hyper-V "internal" NIC to the OVS bridge's "internal" port, but > there's > - * only one Hyper-V NIC but multiple bridges. To support multiple OVS > bridge > - * "internal" ports, we use the flag 'isBridgeInternal' in each > vport. We > - * support addition of multiple bridge-internal ports. A vport with > - * 'isBridgeInternal' == TRUE is a dummy port and has no backing > currently. > - * 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? */ > + 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; > + 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 +129,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); > @@ -217,14 +205,6 @@ OvsIsRealExternalVport(POVS_VPORT_ENTRY vport) > } > > static __inline BOOLEAN > -OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport) > -{ > - ASSERT(vport->isBridgeInternal != TRUE || > - vport->ovsType == OVS_VPORT_TYPE_INTERNAL); > - return vport->isBridgeInternal == TRUE; > -} > - > -static __inline BOOLEAN > OvsIsInternalNIC(NDIS_SWITCH_NIC_TYPE nicType) > { > return nicType == NdisSwitchNicTypeInternal; > @@ -261,7 +241,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 +253,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 db45248..949e069 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,15 +343,15 @@ 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; > > - status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > + status = OvsLookupIPFwdInfo(tunKey->src, 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, > -- > 2.10.2.windows.1 > > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev