[ovs-dev] [PATCH v2 2/3] datapath-windows: Add multiple switch internal ports
Alin Serdean
aserdean at cloudbasesolutions.com
Sat Mar 12 21:27:01 UTC 2016
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>
---
v2: change title
---
---
datapath-windows/ovsext/Actions.c | 35 +-
datapath-windows/ovsext/Gre.c | 7 +-
datapath-windows/ovsext/Gre.h | 5 +-
datapath-windows/ovsext/IpHelper.c | 833 ++++++++++++++++++++++++++++---------
datapath-windows/ovsext/IpHelper.h | 17 +-
datapath-windows/ovsext/PacketIO.h | 3 +-
datapath-windows/ovsext/Stt.c | 5 +-
datapath-windows/ovsext/Stt.h | 6 +-
datapath-windows/ovsext/Switch.h | 7 +-
datapath-windows/ovsext/Vport.c | 56 +--
datapath-windows/ovsext/Vport.h | 78 ++--
datapath-windows/ovsext/Vxlan.c | 8 +-
datapath-windows/ovsext/Vxlan.h | 7 +-
13 files changed, 762 insertions(+), 305 deletions(-)
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 5a04541..571213c 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -240,7 +240,6 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx,
// We might get tunnel packets even before the tunnel gets initialized.
if (tunnelVport) {
- ASSERT(ovsFwdCtx->tunnelRxNic == NULL);
ovsFwdCtx->tunnelRxNic = tunnelVport;
return TRUE;
}
@@ -284,7 +283,6 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,
NDIS_SWITCH_DEFAULT_PORT_ID);
if (validSrcPort && OvsDetectTunnelRxPkt(ovsFwdCtx, flowKey)) {
- ASSERT(ovsFwdCtx->tunnelTxNic == NULL);
ASSERT(ovsFwdCtx->tunnelRxNic != NULL);
return TRUE;
}
@@ -650,36 +648,31 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx)
* Setup the source port to be the internal port to as to facilitate the
* second OvsLookupFlow.
*/
- if (ovsFwdCtx->switchContext->internalVport == NULL ||
+ if (ovsFwdCtx->switchContext->countInternalVports <= 0 ||
ovsFwdCtx->switchContext->virtualExternalVport == NULL) {
OvsClearTunTxCtx(ovsFwdCtx);
OvsCompleteNBLForwardingCtx(ovsFwdCtx,
L"OVS-Dropped since either internal or external port is absent");
return NDIS_STATUS_FAILURE;
}
- ovsFwdCtx->srcVportNo =
- ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->portNo;
-
- ovsFwdCtx->fwdDetail->SourcePortId = ovsFwdCtx->switchContext->internalPortId;
- ovsFwdCtx->fwdDetail->SourceNicIndex =
- ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->nicIndex;
+ OVS_FWD_INFO switchFwdInfo = { 0 };
/* Do the encap. Encap function does not consume the NBL. */
switch(ovsFwdCtx->tunnelTxNic->ovsType) {
case OVS_VPORT_TYPE_GRE:
status = OvsEncapGre(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,
&ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,
- &ovsFwdCtx->layers, &newNbl);
+ &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);
break;
case OVS_VPORT_TYPE_VXLAN:
status = OvsEncapVxlan(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,
&ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,
- &ovsFwdCtx->layers, &newNbl);
+ &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);
break;
case OVS_VPORT_TYPE_STT:
status = OvsEncapStt(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,
&ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,
- &ovsFwdCtx->layers, &newNbl);
+ &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);
break;
default:
ASSERT(! "Tx: Unhandled tunnel type");
@@ -688,8 +681,11 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx)
/* Reset the tunnel context so that it doesn't get used after this point. */
OvsClearTunTxCtx(ovsFwdCtx);
- if (status == NDIS_STATUS_SUCCESS) {
+ if (status == NDIS_STATUS_SUCCESS && switchFwdInfo.vport != NULL) {
ASSERT(newNbl);
+ ovsFwdCtx->srcVportNo = switchFwdInfo.vport->portNo;
+ ovsFwdCtx->fwdDetail->SourcePortId = switchFwdInfo.vport->portId;
+ ovsFwdCtx->fwdDetail->SourceNicIndex = switchFwdInfo.vport->nicIndex;
OvsCompleteNBLForwardingCtx(ovsFwdCtx,
L"Complete after cloning NBL for encapsulation");
ovsFwdCtx->curNbl = newNbl;
@@ -697,7 +693,7 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx)
ASSERT(ovsFwdCtx->curNbl == NULL);
} else {
/*
- * XXX: Temporary freeing of the packet until we register a
+ * XXX: Temporary freeing of the packet until we register a
* callback to IP helper.
*/
OvsCompleteNBLForwardingCtx(ovsFwdCtx,
@@ -929,13 +925,11 @@ dropit:
VOID
OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,
VOID *compList,
- PNET_BUFFER_LIST curNbl)
+ PNET_BUFFER_LIST curNbl,
+ POVS_VPORT_ENTRY internalVport)
{
NDIS_STATUS status;
OvsForwardingContext ovsFwdCtx;
- POVS_VPORT_ENTRY internalVport =
- (POVS_VPORT_ENTRY)switchContext->internalVport;
-
/* XXX: make sure comp list was not a stack variable previously. */
OvsCompletionList *completionList = (OvsCompletionList *)compList;
@@ -944,7 +938,7 @@ OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,
* It could, but will we get this callback from IP helper in that case. Need
* to check.
*/
- ASSERT(switchContext->internalVport);
+ ASSERT(switchContext->countInternalVports >= 0);
status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl,
internalVport->portNo, 0,
NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl),
@@ -1088,6 +1082,9 @@ OvsPopFieldInPacketBuf(OvsForwardingContext *ovsFwdCtx,
/* Bail out if L2 + shiftLength is not contiguous in the first buffer. */
if (MIN(packetLen, mdlLen) < sizeof(EthHdr) + shiftLength) {
ASSERT(FALSE);
+ OvsCompleteNBLForwardingCtx(ovsFwdCtx,
+ L"Dropped due to the buffer is not"
+ L"contiguous");
return NDIS_STATUS_FAILURE;
}
bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);
diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c
index cb41593..3933c60 100644
--- a/datapath-windows/ovsext/Gre.c
+++ b/datapath-windows/ovsext/Gre.c
@@ -96,7 +96,8 @@ OvsEncapGre(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl)
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo)
{
OVS_FWD_INFO fwdInfo;
NDIS_STATUS status;
@@ -107,6 +108,8 @@ OvsEncapGre(POVS_VPORT_ENTRY vport,
return NDIS_STATUS_FAILURE;
}
+ RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);
+
status = OvsDoEncapGre(vport, curNbl, tunKey, &fwdInfo, layers,
switchContext, newNbl);
return status;
@@ -236,8 +239,6 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
IP_DF_NBO : 0;
ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64;
ipHdr->protocol = IPPROTO_GRE;
- ASSERT(tunKey->dst == fwdInfo->dstIpAddr);
- ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0);
ipHdr->saddr = fwdInfo->srcIpAddr;
ipHdr->daddr = fwdInfo->dstIpAddr;
diff --git a/datapath-windows/ovsext/Gre.h b/datapath-windows/ovsext/Gre.h
index d2472d9..54f6541 100644
--- a/datapath-windows/ovsext/Gre.h
+++ b/datapath-windows/ovsext/Gre.h
@@ -20,6 +20,8 @@
#include "NetProto.h"
#include "Flow.h"
+typedef union _OVS_FWD_INFO *POVS_FWD_INFO;
+
typedef struct _OVS_GRE_VPORT {
UINT64 ipId;
/*
@@ -64,7 +66,8 @@ NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl);
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo);
NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
PNET_BUFFER_LIST curNbl,
diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c
index 8126222..3cf077d 100644
--- a/datapath-windows/ovsext/IpHelper.c
+++ b/datapath-windows/ovsext/IpHelper.c
@@ -19,6 +19,8 @@
#include "Switch.h"
#include "Jhash.h"
+extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
+
#ifdef OVS_DBG_MOD
#undef OVS_DBG_MOD
#endif
@@ -26,28 +28,45 @@
#include "Debug.h"
/*
- * Fow now, we assume only one internal adapter
+ * IpHelper supports multiple internal adapters.
*/
KSTART_ROUTINE OvsStartIpHelper;
+/* Contains the entries of internal adapter objects. */
+static LIST_ENTRY ovsInstanceList;
+
+/* Passive-level lock used to protect the internal adapter object list. */
+static ERESOURCE ovsInstanceListLock;
+
/*
+ * This structure is used to define each adapter instance.
+ *
+ * Note:
* Only when the internal IP is configured and virtual
* internal port is connected, the IP helper request can be
* queued.
+ *
+ * We only keep internal IP for reference, it will not be used for determining
+ * SRC IP of the Tunnel.
+ *
+ * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the
+ * route manipulation functions, i.e. GetBestRoute, to work.
*/
-static BOOLEAN ovsInternalIPConfigured;
-static BOOLEAN ovsInternalAdapterUp;
-static GUID ovsInternalNetCfgId;
-static MIB_IF_ROW2 ovsInternalRow;
-static MIB_IPINTERFACE_ROW ovsInternalIPRow;
-
-/* we only keep one internal IP for reference, it will not be used for
- * determining SRC IP of Tunnel
- */
-static UINT32 ovsInternalIP;
+typedef struct _OVS_IPHELPER_INSTANCE
+{
+ LIST_ENTRY link;
+
+ BOOLEAN isIpConfigured;
+ UINT32 portNo;
+ GUID netCfgId;
+ MIB_IF_ROW2 internalRow;
+ MIB_IPINTERFACE_ROW internalIPRow;
+ UINT32 ipAddress;
+ ERESOURCE lock;
+} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;
/*
* FWD_ENTRY --------> IPFORWARD_ENTRY
@@ -85,6 +104,9 @@ static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr);
static VOID OvsCleanupIpHelperRequestList(VOID);
static VOID OvsCleanupFwdTable(VOID);
static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);
+static POVS_IPHELPER_INSTANCE OvsIpHelperAllocateInstance(
+ POVS_IP_HELPER_REQUEST request);
+static VOID OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance);
static VOID
OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
@@ -325,30 +347,65 @@ OvsDumpRoute(const SOCKADDR_INET *sourceAddress,
NTSTATUS
-OvsGetRoute(NET_LUID interfaceLuid,
- const SOCKADDR_INET *destinationAddress,
+OvsGetRoute(SOCKADDR_INET *destinationAddress,
PMIB_IPFORWARD_ROW2 route,
- SOCKADDR_INET *sourceAddress)
+ SOCKADDR_INET *sourceAddress,
+ POVS_IPHELPER_INSTANCE *instance,
+ POVS_VPORT_ENTRY* vport)
{
- NTSTATUS status;
+ NTSTATUS status = STATUS_NETWORK_UNREACHABLE;
+ NTSTATUS result = STATUS_SUCCESS;
+ PLIST_ENTRY head, link, next;
if (destinationAddress == NULL || route == NULL) {
return STATUS_INVALID_PARAMETER;
}
- status = GetBestRoute2(&interfaceLuid, 0,
- NULL, destinationAddress,
- 0, route, sourceAddress);
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ ULONG minMetric = MAXULONG;
+ SOCKADDR_INET crtSrcAddr = { 0 };
+ MIB_IPFORWARD_ROW2 crtRoute = { 0 };
+ POVS_IPHELPER_INSTANCE crtInstance = NULL;
+ WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
- if (status != STATUS_SUCCESS) {
- UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
- OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
- return status;
+ crtInstance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&crtInstance->lock, TRUE);
+ result = GetBestRoute2(&crtInstance->internalRow.InterfaceLuid, 0,
+ NULL, destinationAddress, 0, &crtRoute,
+ &crtSrcAddr);
+
+ if (result != STATUS_SUCCESS) {
+ ExReleaseResourceLite(&crtInstance->lock);
+ continue;
+ }
+
+ if (minMetric > crtRoute.Metric) {
+ size_t len = 0;
+ minMetric = crtRoute.Metric;
+
+ RtlCopyMemory(sourceAddress, &crtSrcAddr, sizeof(*sourceAddress));
+ RtlCopyMemory(route, &crtRoute, sizeof(*route));
+ *instance = crtInstance;
+
+ ConvertInterfaceLuidToAlias(&crtInstance->internalRow.InterfaceLuid,
+ interfaceName, IF_MAX_STRING_SIZE + 1);
+ RtlStringCbLengthW(interfaceName, IF_MAX_STRING_SIZE, &len);
+
+ *vport = OvsFindVportByHvNameW(gOvsSwitchContext,
+ interfaceName,
+ len);
+
+ status = STATUS_SUCCESS;
+ }
+ ExReleaseResourceLite(&crtInstance->lock);
}
+ ExReleaseResourceLite(&ovsInstanceListLock);
OvsDumpRoute(sourceAddress, destinationAddress, route);
+
return status;
}
@@ -358,8 +415,8 @@ OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh)
UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
OVS_LOG_INFO("Neigh: %d.%d.%d.%d",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
ipNeigh->PhysicalAddress[0],
ipNeigh->PhysicalAddress[1],
@@ -421,7 +478,8 @@ OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
NTSTATUS
-OvsGetOrResolveIPNeigh(UINT32 ipAddr,
+OvsGetOrResolveIPNeigh(MIB_IF_ROW2 ipRow,
+ UINT32 ipAddr,
PMIB_IPNET_ROW2 ipNeigh)
{
NTSTATUS status;
@@ -429,8 +487,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
ASSERT(ipNeigh);
RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
- ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
- ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
+ ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value;
+ ipNeigh->InterfaceIndex = ipRow.InterfaceIndex;
ipNeigh->Address.si_family = AF_INET;
ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
@@ -438,8 +496,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
if (status != STATUS_SUCCESS) {
RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
- ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
- ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
+ ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value;
+ ipNeigh->InterfaceIndex = ipRow.InterfaceIndex;
ipNeigh->Address.si_family = AF_INET;
ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
status = OvsResolveIPNeighEntry(ipNeigh);
@@ -447,57 +505,241 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
return status;
}
+static __inline BOOLEAN
+OvsCheckInstanceRow(PMIB_IF_ROW2 instanceRow,
+ PNET_LUID netLuid,
+ NET_IFINDEX ifIndex)
+{
+ return (instanceRow->InterfaceLuid.Info.NetLuidIndex ==
+ netLuid->Info.NetLuidIndex &&
+ instanceRow->InterfaceLuid.Info.IfType ==
+ netLuid->Info.IfType &&
+ instanceRow->InterfaceIndex ==
+ ifIndex);
+}
static VOID
-OvsChangeCallbackIpInterface(PVOID context,
- PMIB_IPINTERFACE_ROW ipRow,
- MIB_NOTIFICATION_TYPE notificationType)
+OvsUpdateIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
{
- UNREFERENCED_PARAMETER(context);
- switch (notificationType) {
- case MibParameterNotification:
- case MibAddInstance:
- if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow,
+ &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)
+ ) {
+
/*
* Update the IP Interface Row
*/
- NdisAcquireSpinLock(&ovsIpHelperLock);
- RtlCopyMemory(&ovsInternalIPRow, ipRow,
- sizeof (PMIB_IPINTERFACE_ROW));
- ovsInternalIPConfigured = TRUE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ RtlCopyMemory(&instance->internalIPRow, ipRow,
+ sizeof(PMIB_IPINTERFACE_ROW));
+ instance->isIpConfigured = TRUE;
+
+ OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s",
+ ipRow->InterfaceLuid.Info.NetLuidIndex,
+ ipRow->InterfaceLuid.Info.IfType,
+ "modified");
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
}
- OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s",
- ipRow->InterfaceLuid.Info.NetLuidIndex,
- ipRow->InterfaceLuid.Info.IfType,
- notificationType == MibAddInstance ? "added" : "modified");
- break;
- case MibDeleteInstance:
- OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d, deleted",
- ipRow->InterfaceLuid.Info.NetLuidIndex,
- ipRow->InterfaceLuid.Info.IfType);
- if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalIPConfigured = FALSE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ return;
+}
+
+static VOID
+OvsAddIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
+{
+ PLIST_ENTRY head, link, next;
+ BOOLEAN found = FALSE;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)) {
- OvsCleanupIpHelperRequestList();
+ instance->isIpConfigured = FALSE;
+ ExReleaseResourceLite(&instance->lock);
- OvsCleanupFwdTable();
+ found = TRUE;
+
+ break;
}
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (found != TRUE) {
+ NTSTATUS status;
+ POVS_IPHELPER_INSTANCE instance = NULL;
+ MIB_UNICASTIPADDRESS_ROW ipEntry;
+ BOOLEAN error = TRUE;
+ instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(
+ sizeof(*instance), OVS_IPHELPER_POOL_TAG);
+ if (instance == NULL) {
+ goto error;
+ }
+ RtlZeroMemory(instance, sizeof(*instance));
+
+ InitializeListHead(&instance->link);
+ ExInitializeResourceLite(&instance->lock);
+ WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
+ status = ConvertInterfaceLuidToAlias(&ipRow->InterfaceLuid,
+ interfaceName,
+ IF_MAX_STRING_SIZE + 1);
+ POVS_VPORT_ENTRY vport = OvsFindVportByHvNameW(gOvsSwitchContext,
+ interfaceName,
+ sizeof(WCHAR) *
+ wcslen(interfaceName));
+
+ if (vport == NULL) {
+ goto error;
+ }
+ RtlCopyMemory(&instance->netCfgId,
+ &vport->netCfgInstanceId,
+ sizeof(instance->netCfgId));
+ instance->portNo = vport->portNo;
+ RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));
+ RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));
+ status = OvsGetIfEntry(&instance->netCfgId,
+ &instance->internalRow);
+
+ if (status != STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Fail to get IF entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId.Data1,
+ instance->netCfgId.Data2,
+ instance->netCfgId.Data3,
+ *(UINT16 *)instance->netCfgId.Data4,
+ instance->netCfgId.Data4[2],
+ instance->netCfgId.Data4[3],
+ instance->netCfgId.Data4[4],
+ instance->netCfgId.Data4[5],
+ instance->netCfgId.Data4[6],
+ instance->netCfgId.Data4[7]);
+ goto error;
+ }
+
+ status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,
+ &instance->internalIPRow);
+
+ if (status == STATUS_SUCCESS) {
+ instance->isIpConfigured = TRUE;
+ }
+ else {
+ goto error;
+ }
+
+ status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);
+ if (status != STATUS_SUCCESS) {
+ OVS_LOG_INFO("Fail to get IP entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId.Data1,
+ instance->netCfgId.Data2,
+ instance->netCfgId.Data3,
+ *(UINT16 *)instance->netCfgId.Data4,
+ instance->netCfgId.Data4[2],
+ instance->netCfgId.Data4[3],
+ instance->netCfgId.Data4[4],
+ instance->netCfgId.Data4[5],
+ instance->netCfgId.Data4[6],
+ instance->netCfgId.Data4[7]);
+ goto error;
+ }
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ InsertHeadList(&ovsInstanceList, &instance->link);
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ error = FALSE;
+
+error:
+ if (error) {
+ OvsIpHelperDeleteInstance(instance);
+ }
+ }
+
+ return;
+}
+
+static VOID
+OvsRemoveIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
+{
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)) {
+
+ instance->isIpConfigured = FALSE;
+ RemoveEntryList(&instance->link);
+
+ ExReleaseResourceLite(&instance->lock);
+ OvsIpHelperDeleteInstance(instance);
+
+ OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is "\
+ "deleted",
+ ipRow->InterfaceLuid.Info.NetLuidIndex,
+ ipRow->InterfaceLuid.Info.IfType);
+
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (IsListEmpty(&ovsInstanceList)) {
+ OvsCleanupIpHelperRequestList();
+ OvsCleanupFwdTable();
+ }
+
+ return;
+}
+
+static VOID
+OvsChangeCallbackIpInterface(PVOID context,
+ PMIB_IPINTERFACE_ROW ipRow,
+ MIB_NOTIFICATION_TYPE notificationType)
+{
+ UNREFERENCED_PARAMETER(context);
+ switch (notificationType) {
+ case MibParameterNotification:
+ OvsUpdateIpInterfaceNotification(ipRow);
+ break;
+ case MibAddInstance:
+ OvsAddIpInterfaceNotification(ipRow);
+ break;
+
+ case MibDeleteInstance:
+ OvsRemoveIpInterfaceNotification(ipRow);
break;
case MibInitialNotification:
- OVS_LOG_INFO("Get Initial notification for IP Interface change.");
+ OVS_LOG_INFO("Got Initial notification for IP Interface change.");
default:
return;
}
@@ -529,25 +771,38 @@ OvsChangeCallbackIpRoute(PVOID context,
case MibParameterNotification:
case MibDeleteInstance:
+ {
+ PLIST_ENTRY head, link, next;
+ BOOLEAN found = FALSE;
+
ASSERT(ipRoute);
ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
- OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
- ipRoute->DestinationPrefix.PrefixLength,
- nextHop & 0xff, (nextHop >> 8) & 0xff,
- (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
- notificationType == MibDeleteInstance ? "deleted" :
- "modified");
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
- if (ipRoute->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRoute->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->isIpConfigured &&
+ OvsCheckInstanceRow(&instance->internalRow,
+ &ipRoute->InterfaceLuid,
+ ipRoute->InterfaceIndex)
+ ) {
+ found = TRUE;
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (found) {
POVS_IPFORWARD_ENTRY ipf;
LOCK_STATE_EX lockState;
@@ -557,8 +812,18 @@ OvsChangeCallbackIpRoute(PVOID context,
OvsRemoveIPForwardEntry(ipf);
}
NdisReleaseRWLock(ovsTableLock, &lockState);
+
+ OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
+ ipRoute->DestinationPrefix.PrefixLength,
+ nextHop & 0xff, (nextHop >> 8) & 0xff,
+ (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
+ notificationType == MibDeleteInstance ? "deleted" :
+ "modified");
}
break;
+ }
case MibInitialNotification:
OVS_LOG_INFO("Get Initial notification for IP Route change.");
@@ -579,40 +844,87 @@ OvsChangeCallbackUnicastIpAddress(PVOID context,
switch (notificationType) {
case MibParameterNotification:
case MibAddInstance:
+ {
+ PLIST_ENTRY head, link, next;
+
ASSERT(unicastRow);
ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
- if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- unicastRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
- ovsInternalIP = ipAddr;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->isIpConfigured &&
+ OvsCheckInstanceRow(&instance->internalRow,
+ &unicastRow->InterfaceLuid,
+ unicastRow->InterfaceIndex)
+ ) {
+
+ instance->ipAddress = ipAddr;
+
+ OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
+ notificationType == MibAddInstance ? "added": "modified");
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
}
- OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
- notificationType == MibAddInstance ? "added": "modified");
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
break;
+ }
case MibDeleteInstance:
+ {
+ PLIST_ENTRY head, link, next;
+ LOCK_STATE_EX lockState;
+ BOOLEAN found = FALSE;
+
ASSERT(unicastRow);
ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
- OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
- if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- unicastRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
- LOCK_STATE_EX lockState;
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->isIpConfigured &&
+ OvsCheckInstanceRow(&instance->internalRow,
+ &unicastRow->InterfaceLuid,
+ unicastRow->InterfaceIndex)
+ ) {
+
+ found = TRUE;
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (found) {
NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
OvsRemoveAllFwdEntriesWithSrc(ipAddr);
NdisReleaseRWLock(ovsTableLock, &lockState);
+ OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
}
+
break;
+ }
case MibInitialNotification:
OVS_LOG_INFO("Get Initial notification for Unicast IP Address change.");
@@ -643,7 +955,7 @@ OvsCancelChangeNotification()
static NTSTATUS
OvsRegisterChangeNotification()
{
- NTSTATUS status;
+ NTSTATUS status = NDIS_STATUS_SUCCESS;
status = NotifyIpInterfaceChange(AF_INET, OvsChangeCallbackIpInterface,
@@ -651,7 +963,7 @@ OvsRegisterChangeNotification()
&ipInterfaceNotificationHandle);
if (status != STATUS_SUCCESS) {
OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.",
- status);
+ status);
return status;
}
@@ -659,7 +971,7 @@ OvsRegisterChangeNotification()
TRUE, &ipRouteNotificationHandle);
if (status != STATUS_SUCCESS) {
OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.",
- status);
+ status);
goto register_cleanup;
}
status = NotifyUnicastIpAddressChange(AF_INET,
@@ -682,10 +994,11 @@ static POVS_IPNEIGH_ENTRY
OvsLookupIPNeighEntry(UINT32 ipAddr)
{
PLIST_ENTRY link;
- POVS_IPNEIGH_ENTRY entry;
UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS);
LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) {
+ POVS_IPNEIGH_ENTRY entry;
+
entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link);
if (entry->ipAddr == ipAddr) {
return entry;
@@ -709,7 +1022,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
{
PLIST_ENTRY link;
- POVS_IPFORWARD_ENTRY ipfEntry;
UINT32 hash;
ASSERT(prefix->Prefix.si_family == AF_INET);
@@ -720,6 +1032,8 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
hash = OvsHashIPPrefix(prefix);
LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) {
+ POVS_IPFORWARD_ENTRY ipfEntry;
+
ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link);
if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength &&
ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr ==
@@ -735,10 +1049,11 @@ static POVS_FWD_ENTRY
OvsLookupIPFwdEntry(UINT32 dstIp)
{
PLIST_ENTRY link;
- POVS_FWD_ENTRY entry;
UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS);
LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) {
+ POVS_FWD_ENTRY entry;
+
entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
if (entry->info.dstIpAddr == dstIp) {
return entry;
@@ -759,9 +1074,8 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);
entry = OvsLookupIPFwdEntry(dstIp);
if (entry) {
- info->value[0] = entry->info.value[0];
- info->value[1] = entry->info.value[1];
- info->value[2] = entry->info.value[2];
+ RtlCopyMemory(info->value, entry->info.value,
+ sizeof entry->info.value);
status = STATUS_SUCCESS;
}
NdisReleaseRWLock(ovsTableLock, &lockState);
@@ -770,7 +1084,8 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
static POVS_IPNEIGH_ENTRY
-OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
+OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh,
+ POVS_IPHELPER_INSTANCE instance)
{
POVS_IPNEIGH_ENTRY entry;
@@ -790,6 +1105,7 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,
ETH_ADDR_LEN);
InitializeListHead(&entry->fwdList);
+ entry->context = (PVOID)instance;
return entry;
}
@@ -798,7 +1114,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
static POVS_IPFORWARD_ENTRY
OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)
{
-
POVS_IPFORWARD_ENTRY entry;
ASSERT(ipRoute);
@@ -876,12 +1191,13 @@ OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry)
static VOID
OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf)
{
- POVS_FWD_ENTRY fwdEntry;
PLIST_ENTRY link, next;
ipf->refCount++;
LIST_FORALL_SAFE(&ipf->fwdList, link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);
OvsRemoveFwdEntry(fwdEntry);
}
@@ -896,11 +1212,12 @@ static VOID
OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn)
{
PLIST_ENTRY link, next;
- POVS_FWD_ENTRY fwdEntry;
ipn->refCount++;
LIST_FORALL_SAFE(&ipn->fwdList, link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);
OvsRemoveFwdEntry(fwdEntry);
}
@@ -973,11 +1290,12 @@ static VOID
OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
{
UINT32 i;
- POVS_FWD_ENTRY fwdEntry;
PLIST_ENTRY link, next;
for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
if (fwdEntry->info.srcIpAddr == ipAddr) {
OvsRemoveFwdEntry(fwdEntry);
@@ -991,13 +1309,14 @@ static VOID
OvsCleanupFwdTable(VOID)
{
PLIST_ENTRY link, next;
- POVS_IPNEIGH_ENTRY ipn;
UINT32 i;
LOCK_STATE_EX lockState;
NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
if (ovsNumFwdEntries) {
LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {
+ POVS_IPNEIGH_ENTRY ipn;
+
ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
OvsRemoveIPNeighEntry(ipn);
}
@@ -1017,20 +1336,16 @@ OvsCleanupIpHelperRequestList(VOID)
{
LIST_ENTRY list;
PLIST_ENTRY next, link;
- POVS_IP_HELPER_REQUEST request;
NdisAcquireSpinLock(&ovsIpHelperLock);
- if (ovsNumIpHelperRequests == 0) {
- NdisReleaseSpinLock(&ovsIpHelperLock);
- return;
- }
-
InitializeListHead(&list);
- OvsAppendList(&list, &ovsIpHelperRequestList);
+ OvsAppendList(&list, &ovsIpHelperRequestList);
ovsNumIpHelperRequests = 0;
NdisReleaseSpinLock(&ovsIpHelperLock);
LIST_FORALL_SAFE(&list, link, next) {
+ POVS_IP_HELPER_REQUEST request;
+
request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
if (request->command == OVS_IP_HELPER_FWD_REQUEST &&
@@ -1056,27 +1371,47 @@ OvsWakeupIPHelper(VOID)
}
VOID
-OvsInternalAdapterDown(VOID)
+OvsInternalAdapterDown(UINT32 portNo,
+ GUID netCfgInstanceId)
{
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalAdapterUp = FALSE;
- ovsInternalIPConfigured = FALSE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ PLIST_ENTRY head, link, next;
- OvsCleanupIpHelperRequestList();
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &ovsInstanceList;
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
- OvsCleanupFwdTable();
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->portNo == portNo &&
+ IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) {
+
+ RemoveEntryList(&instance->link);
+
+ ExReleaseResourceLite(&instance->lock);
+
+ OvsIpHelperDeleteInstance(instance);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (IsListEmpty(&ovsInstanceList)) {
+ OvsCleanupIpHelperRequestList();
+
+ OvsCleanupFwdTable();
+ }
}
VOID
-OvsInternalAdapterUp(GUID *netCfgInstanceId)
+OvsInternalAdapterUp(UINT32 portNo,
+ GUID *netCfgInstanceId)
{
POVS_IP_HELPER_REQUEST request;
- RtlCopyMemory(&ovsInternalNetCfgId, netCfgInstanceId, sizeof (GUID));
- RtlZeroMemory(&ovsInternalRow, sizeof (MIB_IF_ROW2));
-
request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(
sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);
if (request == NULL) {
@@ -1084,10 +1419,13 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId)
return;
}
RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));
+ RtlCopyMemory(&request->instanceReq.netCfgInstanceId,
+ netCfgInstanceId,
+ sizeof(*netCfgInstanceId));
request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP;
+ request->instanceReq.portNo = portNo;
NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalAdapterUp = TRUE;
InsertHeadList(&ovsIpHelperRequestList, &request->link);
ovsNumIpHelperRequests++;
if (ovsNumIpHelperRequests == 1) {
@@ -1097,58 +1435,135 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId)
}
+static POVS_IPHELPER_INSTANCE
+OvsIpHelperAllocateInstance(POVS_IP_HELPER_REQUEST request)
+{
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(
+ sizeof(*instance), OVS_IPHELPER_POOL_TAG);
+ if (instance) {
+ RtlZeroMemory(instance, sizeof(*instance));
+
+ RtlCopyMemory(&instance->netCfgId,
+ &request->instanceReq.netCfgInstanceId,
+ sizeof(instance->netCfgId));
+ instance->portNo = request->instanceReq.portNo;
+
+ InitializeListHead(&instance->link);
+ ExInitializeResourceLite(&instance->lock);
+ }
+
+ return instance;
+}
+
+
+static VOID
+OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance)
+{
+ if (instance) {
+ ExDeleteResourceLite(&instance->lock);
+ OvsFreeMemoryWithTag(instance, OVS_IPHELPER_POOL_TAG);
+ }
+}
+
+
+static VOID
+OvsIpHelperDeleteAllInstances()
+{
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &ovsInstanceList;
+ if (!IsListEmpty(head)) {
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+
+ instance->isIpConfigured = FALSE;
+ RemoveEntryList(&instance->link);
+
+ ExReleaseResourceLite(&instance->lock);
+
+ OvsIpHelperDeleteInstance(instance);
+ }
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+}
+
+
static VOID
OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
{
NTSTATUS status;
+ POVS_IPHELPER_INSTANCE instance = NULL;
MIB_UNICASTIPADDRESS_ROW ipEntry;
- GUID *netCfgInstanceId = &ovsInternalNetCfgId;
+ BOOLEAN error = TRUE;
- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
+ do {
+ instance = OvsIpHelperAllocateInstance(request);
+ if (instance == NULL) {
+ break;
+ }
+ RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));
+ RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));
+ status = OvsGetIfEntry(&instance->netCfgId,
+ &instance->internalRow);
- status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow);
+ if (status != STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Fail to get IF entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId.Data1,
+ instance->netCfgId.Data2,
+ instance->netCfgId.Data3,
+ *(UINT16 *)instance->netCfgId.Data4,
+ instance->netCfgId.Data4[2],
+ instance->netCfgId.Data4[3],
+ instance->netCfgId.Data4[4],
+ instance->netCfgId.Data4[5],
+ instance->netCfgId.Data4[6],
+ instance->netCfgId.Data4[7]);
+ break;
+ }
- if (status != STATUS_SUCCESS) {
- OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID"
- " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- netCfgInstanceId->Data1,
- netCfgInstanceId->Data2,
- netCfgInstanceId->Data3,
- *(UINT16 *)netCfgInstanceId->Data4,
- netCfgInstanceId->Data4[2],
- netCfgInstanceId->Data4[3],
- netCfgInstanceId->Data4[4],
- netCfgInstanceId->Data4[5],
- netCfgInstanceId->Data4[6],
- netCfgInstanceId->Data4[7]);
- return;
- }
+ status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,
+ &instance->internalIPRow);
- status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid,
- &ovsInternalIPRow);
+ if (status == STATUS_SUCCESS) {
+ instance->isIpConfigured = TRUE;
+ } else {
+ break;
+ }
- if (status == STATUS_SUCCESS) {
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalIPConfigured = TRUE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
- } else {
- return;
- }
+ status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);
+ if (status != STATUS_SUCCESS) {
+ OVS_LOG_INFO("Fail to get IP entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId.Data1,
+ instance->netCfgId.Data2,
+ instance->netCfgId.Data3,
+ *(UINT16 *)instance->netCfgId.Data4,
+ instance->netCfgId.Data4[2],
+ instance->netCfgId.Data4[3],
+ instance->netCfgId.Data4[4],
+ instance->netCfgId.Data4[5],
+ instance->netCfgId.Data4[6],
+ instance->netCfgId.Data4[7]);
+ break;
+ }
- status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry);
- if (status != STATUS_SUCCESS) {
- OVS_LOG_INFO("Fali to get IP entry for internal port with GUID"
- " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- netCfgInstanceId->Data1,
- netCfgInstanceId->Data2,
- netCfgInstanceId->Data3,
- *(UINT16 *)netCfgInstanceId->Data4,
- netCfgInstanceId->Data4[2],
- netCfgInstanceId->Data4[3],
- netCfgInstanceId->Data4[4],
- netCfgInstanceId->Data4[5],
- netCfgInstanceId->Data4[6],
- netCfgInstanceId->Data4[7]);
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ InsertHeadList(&ovsInstanceList, &instance->link);
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ error = FALSE;
+ } while (error);
+
+ OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
+ if (error) {
+ OvsIpHelperDeleteInstance(instance);
}
}
@@ -1156,15 +1571,11 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
static NTSTATUS
OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request)
{
-
- NdisAcquireSpinLock(&ovsIpHelperLock);
-
- if (ovsInternalAdapterUp == FALSE ||
- ovsInternalIPConfigured == FALSE) {
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ if (IsListEmpty(&ovsInstanceList)) {
OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
return STATUS_NDIS_ADAPTER_NOT_READY;
} else {
+ NdisAcquireSpinLock(&ovsIpHelperLock);
InsertHeadList(&ovsIpHelperRequestList, &request->link);
ovsNumIpHelperRequests++;
if (ovsNumIpHelperRequests == 1) {
@@ -1222,6 +1633,7 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
BOOLEAN newIPF = FALSE;
BOOLEAN newIPN = FALSE;
BOOLEAN newFWD = FALSE;
+ POVS_IPHELPER_INSTANCE instance = NULL;
status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.dst,
&fwdInfo);
@@ -1236,10 +1648,16 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
dst.si_family = AF_INET;
dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst;
- status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src);
+ status = OvsGetRoute(&dst, &ipRoute, &src, &instance, &fwdInfo.vport);
if (status != STATUS_SUCCESS) {
+ UINT32 ipAddr = dst.Ipv4.sin_addr.s_addr;
+ OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
goto fwd_handle_nbl;
}
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
srcAddr = src.Ipv4.sin_addr.s_addr;
/* find IPNeigh */
@@ -1252,13 +1670,16 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
}
NdisReleaseRWLock(ovsTableLock, &lockState);
}
+
RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));
- ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
+ ipNeigh.InterfaceLuid.Value = instance->internalRow.InterfaceLuid.Value;
if (ipAddr == 0) {
ipAddr = request->fwdReq.tunnelKey.dst;
}
- status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
+ status = OvsGetOrResolveIPNeigh(instance->internalRow,
+ ipAddr, &ipNeigh);
if (status != STATUS_SUCCESS) {
+ ExReleaseResourceLite(&instance->lock);
goto fwd_handle_nbl;
}
@@ -1274,6 +1695,7 @@ fwd_request_done:
ipf = OvsCreateIPForwardEntry(&ipRoute);
if (ipf == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
@@ -1291,9 +1713,10 @@ fwd_request_done:
if (ipn == NULL) {
ipn = OvsLookupIPNeighEntry(ipAddr);
if (ipn == NULL) {
- ipn = OvsCreateIPNeighEntry(&ipNeigh);
+ ipn = OvsCreateIPNeighEntry(&ipNeigh, instance);
if (ipn == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
@@ -1307,13 +1730,14 @@ fwd_request_done:
fwdInfo.dstIpAddr = request->fwdReq.tunnelKey.dst;
fwdInfo.srcIpAddr = srcAddr;
RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, ETH_ADDR_LEN);
- RtlCopyMemory(fwdInfo.srcMacAddr, ovsInternalRow.PhysicalAddress,
+ RtlCopyMemory(fwdInfo.srcMacAddr, instance->internalRow.PhysicalAddress,
ETH_ADDR_LEN);
fwdInfo.srcPortNo = request->fwdReq.inPort;
fwdEntry = OvsCreateFwdEntry(&fwdInfo);
if (fwdEntry == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
@@ -1323,6 +1747,7 @@ fwd_request_done:
*/
OvsAddIPFwdCache(fwdEntry, ipf, ipn);
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
fwd_handle_nbl:
@@ -1425,12 +1850,17 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr,
static VOID
-OvsHandleIPNeighTimeout(UINT32 ipAddr)
+OvsHandleIPNeighTimeout(UINT32 ipAddr,
+ PVOID context)
{
MIB_IPNET_ROW2 ipNeigh;
NTSTATUS status;
+ POVS_IPHELPER_INSTANCE instance = (POVS_IPHELPER_INSTANCE)context;
- status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ status = OvsGetOrResolveIPNeigh(instance->internalRow,
+ ipAddr, &ipNeigh);
+ ExReleaseResourceLite(&instance->lock);
OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);
}
@@ -1438,13 +1868,13 @@ OvsHandleIPNeighTimeout(UINT32 ipAddr)
/*
*----------------------------------------------------------------------------
- * IP Helper system threash handle following request
+ * IP Helper system thread handles the following requests:
* 1. Intialize Internal port row when internal port is connected
* 2. Handle FWD request
* 3. Handle IP Neigh timeout
*
* IP Interface, unicast address, and IP route change will be handled
- * by the revelant callback.
+ * by the revelant callbacks.
*----------------------------------------------------------------------------
*/
VOID
@@ -1454,15 +1884,15 @@ OvsStartIpHelper(PVOID data)
POVS_IP_HELPER_REQUEST req;
POVS_IPNEIGH_ENTRY ipn;
PLIST_ENTRY link;
- UINT64 timeVal, timeout;
+ UINT64 timeVal, timeout;
OVS_LOG_INFO("Start the IP Helper Thread, context: %p", context);
NdisAcquireSpinLock(&ovsIpHelperLock);
while (!context->exit) {
-
timeout = 0;
while (!IsListEmpty(&ovsIpHelperRequestList)) {
+ ovsNumIpHelperRequests--;
if (context->exit) {
goto ip_helper_wait;
}
@@ -1503,7 +1933,7 @@ OvsStartIpHelper(PVOID data)
NdisReleaseSpinLock(&ovsIpHelperLock);
- OvsHandleIPNeighTimeout(ipAddr);
+ OvsHandleIPNeighTimeout(ipAddr, ipn->context);
NdisAcquireSpinLock(&ovsIpHelperLock);
}
@@ -1526,7 +1956,6 @@ ip_helper_wait:
NdisReleaseSpinLock(&ovsIpHelperLock);
OvsCleanupFwdTable();
OvsCleanupIpHelperRequestList();
-
OVS_LOG_INFO("Terminating the OVS IP Helper system thread");
PsTerminateSystemThread(STATUS_SUCCESS);
@@ -1536,7 +1965,8 @@ ip_helper_wait:
NTSTATUS
OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)
{
- NTSTATUS status;
+ UNREFERENCED_PARAMETER(ndisFilterHandle);
+ NTSTATUS status = NDIS_STATUS_SUCCESS;
HANDLE threadHandle;
UINT32 i;
@@ -1549,12 +1979,6 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)
ovsNeighHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
sizeof(LIST_ENTRY) * OVS_NEIGH_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG);
- RtlZeroMemory(&ovsInternalRow, sizeof(MIB_IF_ROW2));
- RtlZeroMemory(&ovsInternalIPRow, sizeof (MIB_IPINTERFACE_ROW));
- ovsInternalIP = 0;
-
- ovsInternalAdapterUp = FALSE;
-
InitializeListHead(&ovsSortedIPNeighList);
ovsTableLock = NdisAllocateRWLock(ndisFilterHandle);
@@ -1566,6 +1990,9 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)
ipRouteNotificationHandle = NULL;
unicastIPNotificationHandle = NULL;
+ ExInitializeResourceLite(&ovsInstanceListLock);
+ InitializeListHead(&ovsInstanceList);
+
if (ovsFwdHashTable == NULL ||
ovsRouteHashTable == NULL ||
ovsNeighHashTable == NULL ||
@@ -1625,6 +2052,7 @@ init_cleanup:
NdisFreeRWLock(ovsTableLock);
ovsTableLock = NULL;
}
+ ExDeleteResourceLite(&ovsInstanceListLock);
NdisFreeSpinLock(&ovsIpHelperLock);
}
return STATUS_SUCCESS;
@@ -1651,6 +2079,9 @@ OvsCleanupIpHelper(VOID)
NdisFreeRWLock(ovsTableLock);
NdisFreeSpinLock(&ovsIpHelperLock);
+
+ OvsIpHelperDeleteAllInstances();
+ ExDeleteResourceLite(&ovsInstanceListLock);
}
VOID
diff --git a/datapath-windows/ovsext/IpHelper.h b/datapath-windows/ovsext/IpHelper.h
index 8562f86..095bd05 100644
--- a/datapath-windows/ovsext/IpHelper.h
+++ b/datapath-windows/ovsext/IpHelper.h
@@ -19,6 +19,7 @@
#include <ntddk.h>
#include <netioapi.h>
+#include <Vport.h>
#define OVS_FWD_HASH_TABLE_SIZE ((UINT32)1 << 10)
#define OVS_FWD_HASH_TABLE_MASK (OVS_FWD_HASH_TABLE_SIZE - 1)
@@ -41,6 +42,7 @@ typedef struct _OVS_IPNEIGH_ENTRY {
LIST_ENTRY link;
LIST_ENTRY slink;
LIST_ENTRY fwdList;
+ PVOID context;
} OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY;
typedef struct _OVS_IPFORWARD_ENTRY {
@@ -58,8 +60,9 @@ typedef union _OVS_FWD_INFO {
UINT8 dstMacAddr[ETH_ADDR_LEN];
UINT8 srcMacAddr[ETH_ADDR_LEN];
UINT32 srcPortNo;
+ POVS_VPORT_ENTRY vport;
};
- UINT64 value[3];
+ UINT64 value[4];
} OVS_FWD_INFO, *POVS_FWD_INFO;
typedef struct _OVS_FWD_ENTRY {
@@ -94,13 +97,17 @@ typedef struct _OVS_FWD_REQUEST_INFO {
PVOID cbData2;
} OVS_FWD_REQUEST_INFO, *POVS_FWD_REQUEST_INFO;
+typedef struct _OVS_INSTANCE_REQUEST_INFO {
+ GUID netCfgInstanceId;
+ UINT32 portNo;
+} OVS_INSTANCE_REQUEST_INFO, *POVS_INSTANCE_REQUEST_INFO;
typedef struct _OVS_IP_HELPER_REQUEST {
LIST_ENTRY link;
UINT32 command;
union {
- OVS_FWD_REQUEST_INFO fwdReq;
- UINT32 dummy;
+ OVS_FWD_REQUEST_INFO fwdReq;
+ OVS_INSTANCE_REQUEST_INFO instanceReq;
};
} OVS_IP_HELPER_REQUEST, *POVS_IP_HELPER_REQUEST;
@@ -114,8 +121,8 @@ typedef struct _OVS_IP_HELPER_THREAD_CONTEXT {
NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle);
VOID OvsCleanupIpHelper(VOID);
-VOID OvsInternalAdapterUp(GUID *netCfgInstanceId);
-VOID OvsInternalAdapterDown(VOID);
+VOID OvsInternalAdapterUp(UINT32 portNo, GUID *netCfgInstanceId);
+VOID OvsInternalAdapterDown(UINT32 portNo, GUID netCfgInstanceId);
NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort,
const PVOID tunnelKey,
diff --git a/datapath-windows/ovsext/PacketIO.h b/datapath-windows/ovsext/PacketIO.h
index 7247869..b204167 100644
--- a/datapath-windows/ovsext/PacketIO.h
+++ b/datapath-windows/ovsext/PacketIO.h
@@ -56,6 +56,7 @@ NDIS_STATUS OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
const PNL_ATTR actions, int actionsLen);
VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,
- VOID *compList, PNET_BUFFER_LIST curNbl);
+ VOID *compList, PNET_BUFFER_LIST curNbl,
+ POVS_VPORT_ENTRY internalVport);
#endif /* __PACKETIO_H_ */
diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c
index dd7bf92..47d9a8d 100644
--- a/datapath-windows/ovsext/Stt.c
+++ b/datapath-windows/ovsext/Stt.c
@@ -105,7 +105,8 @@ OvsEncapStt(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl)
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo)
{
OVS_FWD_INFO fwdInfo;
NDIS_STATUS status;
@@ -121,6 +122,8 @@ OvsEncapStt(POVS_VPORT_ENTRY vport,
return NDIS_STATUS_FAILURE;
}
+ RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);
+
status = OvsDoEncapStt(vport, curNbl, tunKey, &fwdInfo, layers,
switchContext, newNbl);
return status;
diff --git a/datapath-windows/ovsext/Stt.h b/datapath-windows/ovsext/Stt.h
index a3e3915..f64654c 100644
--- a/datapath-windows/ovsext/Stt.h
+++ b/datapath-windows/ovsext/Stt.h
@@ -40,6 +40,9 @@
#define STT_CLEANUP_INTERVAL 300000000 // 30s
#define STT_ETH_PAD 2
+
+typedef union _OVS_FWD_INFO *POVS_FWD_INFO;
+
typedef struct SttHdr {
UINT8 version;
UINT8 flags;
@@ -89,7 +92,8 @@ NDIS_STATUS OvsEncapStt(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl);
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo);
NDIS_STATUS OvsDecapStt(POVS_SWITCH_CONTEXT switchContext,
diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h
index 001335a..7b8712d 100644
--- a/datapath-windows/ovsext/Switch.h
+++ b/datapath-windows/ovsext/Switch.h
@@ -127,9 +127,10 @@ typedef struct _OVS_SWITCH_CONTEXT
* 'numPhysicalNics'.
*/
NDIS_SWITCH_PORT_ID virtualExternalPortId;
- NDIS_SWITCH_PORT_ID internalPortId;
- POVS_VPORT_ENTRY virtualExternalVport; // the virtual adapter vport
- POVS_VPORT_ENTRY internalVport;
+ POVS_VPORT_ENTRY virtualExternalVport; /* the virtual adapter
+ * vport */
+ INT32 countInternalVports; /* the number of internal
+ * vports */
/*
* 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,
diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c
index 7b0103d..fad0350 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -81,8 +81,6 @@ static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info,
PVOID outBuffer,
UINT32 outBufLen,
int dpIfIndex);
-static POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext,
- PWSTR wsName, SIZE_T wstrSize);
static VOID UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext,
POVS_VPORT_ENTRY vport, BOOLEAN newPort);
static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
@@ -96,7 +94,7 @@ static VOID OvsTunnelVportPendingInit(PVOID context,
static VOID OvsTunnelVportPendingRemove(PVOID context,
NTSTATUS status,
UINT32 *replyLen);
-static NTSTATUS GetNICAlias(GUID *netCfgInstanceId,
+static NTSTATUS GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam,
IF_COUNTED_STRING *portFriendlyName);
/*
@@ -331,7 +329,7 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
if (OvsIsInternalNIC(nicParam->NicType) ||
OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
- GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
+ GetNICAlias(nicParam, &portFriendlyName);
}
NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
@@ -427,7 +425,7 @@ HvConnectNic(POVS_SWITCH_CONTEXT switchContext,
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
if (nicParam->NicType == NdisSwitchNicTypeInternal) {
- OvsInternalAdapterUp(&nicParam->NetCfgInstanceId);
+ OvsInternalAdapterUp(vport->portNo, &nicParam->NetCfgInstanceId);
}
done:
@@ -464,7 +462,7 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
/* GetNICAlias() must be called outside of a lock. */
if (nicParam->NicType == NdisSwitchNicTypeInternal ||
OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
- GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
+ GetNICAlias(nicParam, &portFriendlyName);
aliasLookup = TRUE;
}
@@ -607,7 +605,7 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
if (isInternalPort) {
- OvsInternalAdapterDown();
+ OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId);
}
done:
@@ -827,10 +825,6 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
portId == switchContext->virtualExternalPortId &&
index == switchContext->virtualExternalVport->nicIndex) {
return (POVS_VPORT_ENTRY)switchContext->virtualExternalVport;
- } else if (switchContext->internalVport &&
- portId == switchContext->internalPortId &&
- index == switchContext->internalVport->nicIndex) {
- return (POVS_VPORT_ENTRY)switchContext->internalVport;
} else {
PLIST_ENTRY head, link;
POVS_VPORT_ENTRY vport;
@@ -937,6 +931,8 @@ OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,
} else {
RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,
sizeof (nicParam->NetCfgInstanceId));
+ RtlCopyMemory(&vport->nicFriendlyName, &nicParam->NicFriendlyName,
+ sizeof (nicParam->NicFriendlyName));
}
RtlCopyMemory(&vport->nicName, &nicParam->NicName,
sizeof (nicParam->NicName));
@@ -1060,11 +1056,12 @@ OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport)
/*
* --------------------------------------------------------------------------
* For external and internal vports 'portFriendlyName' parameter, provided by
- * Hyper-V, is overwritten with the interface alias name.
+ * Hyper-V, is overwritten with the interface alias name and nic friendly name
+ * equivalent.
* --------------------------------------------------------------------------
*/
static NTSTATUS
-GetNICAlias(GUID *netCfgInstanceId,
+GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam,
IF_COUNTED_STRING *portFriendlyName)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -1072,7 +1069,13 @@ GetNICAlias(GUID *netCfgInstanceId,
NET_LUID interfaceLuid = { 0 };
size_t len = 0;
- status = ConvertInterfaceGuidToLuid(netCfgInstanceId,
+ if (nicParam->NicType == NdisSwitchNicTypeInternal) {
+ RtlCopyMemory(portFriendlyName, &nicParam->NicFriendlyName,
+ sizeof nicParam->NicFriendlyName);
+ return status;
+ }
+
+ status = ConvertInterfaceGuidToLuid(&nicParam->NetCfgInstanceId,
&interfaceLuid);
if (status == STATUS_SUCCESS) {
/*
@@ -1083,9 +1086,9 @@ GetNICAlias(GUID *netCfgInstanceId,
IF_MAX_STRING_SIZE + 1);
if (status == STATUS_SUCCESS) {
RtlStringCbPrintfW(portFriendlyName->String,
- IF_MAX_STRING_SIZE, L"%s", interfaceName);
+ IF_MAX_STRING_SIZE, L"%s", interfaceName);
RtlStringCbLengthW(portFriendlyName->String, IF_MAX_STRING_SIZE,
- &len);
+ &len);
portFriendlyName->Length = (USHORT)len;
} else {
OVS_LOG_ERROR("Fail to convert interface LUID to alias, status: %x",
@@ -1127,8 +1130,7 @@ UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext,
break;
case NdisSwitchPortTypeInternal:
ASSERT(vport->isBridgeInternal == FALSE);
- switchContext->internalPortId = vport->portId;
- switchContext->internalVport = vport;
+ switchContext->countInternalVports++;
break;
case NdisSwitchPortTypeSynthetic:
case NdisSwitchPortTypeEmulated:
@@ -1244,9 +1246,9 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext,
case OVS_VPORT_TYPE_INTERNAL:
if (!vport->isBridgeInternal) {
if (hvDelete && vport->isAbsentOnHv == FALSE) {
- switchContext->internalPortId = 0;
- switchContext->internalVport = NULL;
- OvsInternalAdapterDown();
+ switchContext->countInternalVports--;
+ ASSERT(switchContext->countInternalVports >= 0);
+ OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId);
}
hvSwitchPort = TRUE;
}
@@ -1516,7 +1518,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
}
ASSERT(switchContext->virtualExternalVport == NULL);
- ASSERT(switchContext->internalVport == NULL);
+ ASSERT(switchContext->countInternalVports == 0);
}
@@ -2196,12 +2198,12 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
goto Cleanup;
}
- if (portType == OVS_VPORT_TYPE_NETDEV) {
- /* External ports can also be looked up like VIF ports. */
+ if (portType == OVS_VPORT_TYPE_NETDEV ||
+ portType == OVS_VPORT_TYPE_INTERNAL) {
+ /* External and internal ports can also be looked up like VIF ports. */
vport = OvsFindVportByHvNameA(gOvsSwitchContext, portName);
} else {
- ASSERT(OvsIsTunnelVportType(portType) ||
- portType == OVS_VPORT_TYPE_INTERNAL);
+ ASSERT(OvsIsTunnelVportType(portType));
vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
if (vport == NULL) {
@@ -2241,8 +2243,6 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
transportPortDest);
nlError = NlMapStatusToNlErr(status);
- } else {
- OvsInitBridgeInternalVport(vport);
}
vportInitialized = TRUE;
diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h
index 373896d..00bd931 100644
--- a/datapath-windows/ovsext/Vport.h
+++ b/datapath-windows/ovsext/Vport.h
@@ -79,38 +79,39 @@ typedef struct _OVS_VPORT_FULL_STATS {
* tunnel type, such as vxlan, gre
*/
typedef struct _OVS_VPORT_ENTRY {
- LIST_ENTRY ovsNameLink;
- LIST_ENTRY portIdLink;
- LIST_ENTRY portNoLink;
- LIST_ENTRY tunnelVportLink;
-
- OVS_VPORT_STATE ovsState;
- OVS_VPORT_TYPE ovsType;
- OVS_VPORT_STATS stats;
- OVS_VPORT_ERR_STATS errStats;
- UINT32 portNo;
- UINT32 mtu;
+ LIST_ENTRY ovsNameLink;
+ LIST_ENTRY portIdLink;
+ LIST_ENTRY portNoLink;
+ LIST_ENTRY tunnelVportLink;
+
+ OVS_VPORT_STATE ovsState;
+ OVS_VPORT_TYPE ovsType;
+ OVS_VPORT_STATS stats;
+ OVS_VPORT_ERR_STATS errStats;
+ UINT32 portNo;
+ UINT32 mtu;
/* ovsName is the ovs (datapath) port name - it is null terminated. */
- CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH];
-
- PVOID priv;
- NDIS_SWITCH_PORT_ID portId;
- NDIS_SWITCH_NIC_INDEX nicIndex;
- NDIS_SWITCH_NIC_TYPE nicType;
- UINT16 numaNodeId;
- NDIS_SWITCH_PORT_STATE portState;
- NDIS_SWITCH_NIC_STATE nicState;
- NDIS_SWITCH_PORT_TYPE portType;
-
- UINT8 permMacAddress[ETH_ADDR_LEN];
- UINT8 currMacAddress[ETH_ADDR_LEN];
- UINT8 vmMacAddress[ETH_ADDR_LEN];
-
- NDIS_SWITCH_PORT_NAME hvPortName;
- IF_COUNTED_STRING portFriendlyName;
- NDIS_SWITCH_NIC_NAME nicName;
- NDIS_VM_NAME vmName;
- GUID netCfgInstanceId;
+ CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH];
+
+ PVOID priv;
+ NDIS_SWITCH_PORT_ID portId;
+ NDIS_SWITCH_NIC_INDEX nicIndex;
+ NDIS_SWITCH_NIC_TYPE nicType;
+ UINT16 numaNodeId;
+ NDIS_SWITCH_PORT_STATE portState;
+ NDIS_SWITCH_NIC_STATE nicState;
+ NDIS_SWITCH_PORT_TYPE portType;
+
+ UINT8 permMacAddress[ETH_ADDR_LEN];
+ UINT8 currMacAddress[ETH_ADDR_LEN];
+ UINT8 vmMacAddress[ETH_ADDR_LEN];
+
+ NDIS_SWITCH_PORT_NAME hvPortName;
+ IF_COUNTED_STRING portFriendlyName;
+ NDIS_SWITCH_NIC_NAME nicName;
+ NDIS_SWITCH_NIC_FRIENDLYNAME nicFriendlyName;
+ NDIS_VM_NAME vmName;
+ GUID netCfgInstanceId;
/*
* OVS userpace has a notion of bridges which basically defines an
* L2-domain. Each "bridge" has an "internal" port of type
@@ -125,12 +126,12 @@ typedef struct _OVS_VPORT_ENTRY {
* If a flow actions specifies the output port to be a bridge-internal port,
* the port is silently ignored.
*/
- BOOLEAN isBridgeInternal;
- BOOLEAN isExternal;
- UINT32 upcallPid; /* netlink upcall port id */
- PNL_ATTR portOptions;
- BOOLEAN isAbsentOnHv; /* Is this port present on the
- Hyper-V switch? */
+ BOOLEAN isBridgeInternal;
+ BOOLEAN isExternal;
+ UINT32 upcallPid; /* netlink upcall port id */
+ PNL_ATTR portOptions;
+ BOOLEAN isAbsentOnHv; /* Is this port present on the
+ Hyper-V switch? */
} OVS_VPORT_ENTRY, *POVS_VPORT_ENTRY;
struct _OVS_SWITCH_CONTEXT;
@@ -142,6 +143,9 @@ POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name);
POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,
PSTR name);
+POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext,
+ PWSTR wsName,
+ SIZE_T wstrSize);
POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
NDIS_SWITCH_PORT_ID portId,
NDIS_SWITCH_NIC_INDEX index);
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index b89c032..3ac919a 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -282,8 +282,6 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,
IP_DF_NBO : 0;
ipHdr->ttl = tunKey->ttl ? tunKey->ttl : VXLAN_DEFAULT_TTL;
ipHdr->protocol = IPPROTO_UDP;
- ASSERT(tunKey->dst == fwdInfo->dstIpAddr);
- ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0);
ipHdr->saddr = fwdInfo->srcIpAddr;
ipHdr->daddr = fwdInfo->dstIpAddr;
@@ -332,7 +330,8 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl)
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo)
{
NTSTATUS status;
OVS_FWD_INFO fwdInfo;
@@ -340,7 +339,6 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport,
status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo);
if (status != STATUS_SUCCESS) {
OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL);
- // return NDIS_STATUS_PENDING;
/*
* XXX: Don't know if the completionList will make any sense when
* accessed in the callback. Make sure the caveats are known.
@@ -351,6 +349,8 @@ OvsEncapVxlan(POVS_VPORT_ENTRY vport,
return NDIS_STATUS_FAILURE;
}
+ RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);
+
return OvsDoEncapVxlan(vport, curNbl, tunKey, &fwdInfo, layers,
switchContext, newNbl);
}
diff --git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h
index b9462f0..9a41bbe 100644
--- a/datapath-windows/ovsext/Vxlan.h
+++ b/datapath-windows/ovsext/Vxlan.h
@@ -17,7 +17,11 @@
#ifndef __VXLAN_H_
#define __VXLAN_H_ 1
+#include "IpHelper.h"
#include "NetProto.h"
+
+typedef union _OVS_FWD_INFO *POVS_FWD_INFO;
+
typedef struct _OVS_VXLAN_VPORT {
UINT16 dstPort;
UINT64 filterID;
@@ -64,7 +68,8 @@ NDIS_STATUS OvsEncapVxlan(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl);
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo);
NDIS_STATUS OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext,
PNET_BUFFER_LIST curNbl,
--
1.9.5.msysgit.0
More information about the dev
mailing list