[ovs-dev] [PATCH 2/3 v8] datapath-windows: Add multiple switch internal ports
Sairam Venugopal
vsairam at vmware.com
Tue Dec 20 20:13:02 UTC 2016
Acked-by: Sairam Venugopal <vsairam at vmware.com>
On 12/20/16, 11:42 AM, "Alin Serdean" <aserdean at 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 <aserdean at cloudbasesolutions.com>
>Co-authored-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
>Signed-off-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
>Acked-by: Paul Boca <pboca at cloudbasesolutions.com>
>---
>v8: Rebase
>v7: Rebase
>v6: Rebase
>v5: Rebase
>v4: Address comments (fix aligment, switch goto labels)
>v3: Add acked
>v2: Rebase
>---
> datpath-windows/ovsext/Actions.c | 49 +-
> 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, 868 insertions(+), 428 deletions(-)
>
>diff --git a/datapath-windows/ovsext/Actions.c
>b/datapath-windows/ovsext/Actions.c
>index c1e0121..2a24410 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 @@ OvsDetecTunnelPkt(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;
> }
>@@ -671,7 +666,7 @@ 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,
>@@ -679,37 +674,28 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx)
> return NDIS_STATUS_FAILURE;
> }
>
>- /*
>- * Save the 'srcVportNo', 'srcPortId', 'srcNicIndex' so that
>- * this can be applied to the new NBL later on.
>- */
>- srcVportNo =
>-
>((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->portNo;
>- srcPortId = ovsFwdCtx->switchContext->internalPortId;
>- srcNicIndex =
>-
>((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");
>@@ -718,8 +704,16 @@ 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);
>+ /*
>+ * Save the 'srcVportNo', 'srcPortId', 'srcNicIndex' so that
>+ * this can be applied to the new NBL later on.
>+ */
>+ srcVportNo = switchFwdInfo.vport->portNo;
>+ srcPortId = switchFwdInfo.vport->portId;
>+ srcNiIndex = switchFwdInfo.vport->nicIndex;
>+
> OvsCompleteNBLForwardingCtx(ovsFwdCtx,
> L"Complete after cloning NBL for
>encapsulation");
> status = OvsInitForwardingCtx(ovsFwdCtx,
>ovsFwdCtx->switchContext,
>@@ -971,12 +965,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;
>@@ -986,7 +979,7 @@ OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,
> * It could, but will we get this callback from IP helper in that
>case. Need
> * to check.
> */
>- ASSERT(switchContet->internalVport);
>+ ASSERT(switchContext->countInternalVports > 0);
> status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl,
> internalVport->portNo, 0,
>
>NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl),
>@@ -1076,7 +1069,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 00644
>--- a/datapath-windows/ovsext/Geneve.c
>+++ b/datapath-windows/ovsext/Geneve.c
>@@ -72,7 +72,8 @@ NDIS_STATUS OvsEncapGenee(POVS_VPORT_ENTRY vport,
> OvsIPv4TunnelKey *tunKey,
> POVS_SWITCH_CONTEXT switchContext,
> POVS_PACKET_HDR_INFO layers,
>- PNET_BUFFER_LIST *newNbl)
>+ PNET_BUFFER_LIST *newNl,
>+ POVS_FWD_INFO switchFwdnfo)
> {
> NTSTATUS status;
> OVS_FWD_INFO fwdInfo;
>@@ -90,7 +91,7 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,
> ULONG mss = 0;
> NDIS_TCP_IP_CHECKSUM_NT_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,
> retun NDIS_STATUS_FAILURE;
> }
>
>+ RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof
>fwdInfo.value);
>+
> curNb = NET_BUFFER_LIST_FIRST_NB(urNbl);
> packetLength = NET_BUFFER_DATA_LENGTH(curNb);
>
>diff --git /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 _O;
>@@ -66,7 +69,8 @@ NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport,
> OvsIPv4unnelKey *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 iternal adapters.
> */
>
> KSTART_ROUTINE OvsStartIpHelper;
>
>+/* Contains the entries of internal adapter objects. */
>+static LIST_ENTRY ovsInstanceList;
>+
>+/* Passive-level loc 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_HREAD_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[], 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("Interfce GUID:
>%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
>- ifRow>InterfaceGuid.Data1,
>- ifRow->InterfaceGuid.Data2,
>- ifRow->InterfaceGuid.Data3,
>- *(UINT6 *)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;
>+ NTSTATU status = STATUS_NETWORK_UNREACHABLE;
>+ NTSTATUS result = STATUS_SUCCESS;
>+ PLIST_ENTRY head, link, next;
>+ ULONG minMetric = MAXLONG;
>
> 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;
>+ crtIstance = 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;
>+ OCK_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 & xff, (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_IFROW2 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(ipNeih, 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 ==
>+ etLuid->Info.NetLuidIndex &&
>+ instanceRow->InterfaceLuid.Info.IfType =
>+ netLuid->Info.IfType &&
>+ instanceRow->InterfaceInex ==
>+ 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);
>+
>+ ExAcquireResourcexclusiveLite(&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,
>- ipRo->InterfaceLuid.Info.IfType,
>- notificationType == MibAddInsance ? "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->InterfaceLui.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;
>+ PVS_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 (OvsSwitchContext == 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->internaRow,
>&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
>+OvsChangeCllbackIpInterface(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);
>+
>OvsRemoveAllFwdEntriesWithPortNo(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
>dev at openvswitch.org
>https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_
>mailman_listinfo_ovs-2Ddev&d=DgICAg&c=uilaK90D4TOVoH58JNXRgQ&r=Z6vowHUOjP5
>ysP_g372c49Nqc1vEKqHKNBkR5Q5Z7uo&m=lQ_oSxjf1gYibKKEwmXTos4Ark1Aq26O_lgryNr
>6kXw&s=2wdv5o0mi8vuzA9PCULtgnJxVF8pzPMW2OhW98k0UZQ&e=
More information about the dev
mailing list