summaryrefslogtreecommitdiff
path: root/datapath-windows
diff options
context:
space:
mode:
Diffstat (limited to 'datapath-windows')
-rw-r--r--datapath-windows/ovsext/Actions.c49
-rw-r--r--datapath-windows/ovsext/Geneve.c7
-rw-r--r--datapath-windows/ovsext/Geneve.h6
-rw-r--r--datapath-windows/ovsext/Gre.c7
-rw-r--r--datapath-windows/ovsext/Gre.h8
-rw-r--r--datapath-windows/ovsext/IpHelper.c919
-rw-r--r--datapath-windows/ovsext/IpHelper.h22
-rw-r--r--datapath-windows/ovsext/Stt.c7
-rw-r--r--datapath-windows/ovsext/Stt.h7
-rw-r--r--datapath-windows/ovsext/Switch.h9
-rw-r--r--datapath-windows/ovsext/Vport.c131
-rw-r--r--datapath-windows/ovsext/Vport.h104
-rw-r--r--datapath-windows/ovsext/Vxlan.c10
-rw-r--r--datapath-windows/ovsext/Vxlan.h10
14 files changed, 868 insertions, 428 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index c1e0121cb..2a2441092 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -301,7 +301,6 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,
return TRUE;
}
} else if (OvsIsTunnelVportType(dstVport->ovsType)) {
- ASSERT(ovsFwdCtx->tunnelTxNic == NULL);
ASSERT(ovsFwdCtx->tunnelRxNic == NULL);
/*
@@ -322,7 +321,7 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,
if (!vport ||
(vport->ovsType != OVS_VPORT_TYPE_NETDEV &&
- !OvsIsBridgeInternalVport(vport) &&
+ vport->ovsType != OVS_VPORT_TYPE_INTERNAL &&
!OvsIsTunnelVportType(vport->ovsType))) {
ovsFwdCtx->tunKey.dst = 0;
}
@@ -403,10 +402,6 @@ OvsAddPorts(OvsForwardingContext *ovsFwdCtx,
vport->stats.txBytes +=
NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl));
- if (OvsIsBridgeInternalVport(vport)) {
- return NDIS_STATUS_SUCCESS;
- }
-
if (OvsDetectTunnelPkt(ovsFwdCtx, vport, flowKey)) {
return NDIS_STATUS_SUCCESS;
}
@@ -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;
+ srcNicIndex = 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(switchContext->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 efdf9f71c..d38a65659 100644
--- a/datapath-windows/ovsext/Geneve.c
+++ b/datapath-windows/ovsext/Geneve.c
@@ -72,7 +72,8 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl)
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo)
{
NTSTATUS status;
OVS_FWD_INFO fwdInfo;
@@ -90,7 +91,7 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,
ULONG mss = 0;
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
- status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo);
+ status = OvsLookupIPFwdInfo(tunKey->src, tunKey->dst, &fwdInfo);
if (status != STATUS_SUCCESS) {
OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL);
// return NDIS_STATUS_PENDING;
@@ -104,6 +105,8 @@ NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,
return NDIS_STATUS_FAILURE;
}
+ RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);
+
curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
packetLength = NET_BUFFER_DATA_LENGTH(curNb);
diff --git a/datapath-windows/ovsext/Geneve.h b/datapath-windows/ovsext/Geneve.h
index 057f80a05..be8a834ad 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 7d6c0a218..c5da064f8 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 7e20ced96..c45df8fed 100644
--- a/datapath-windows/ovsext/Gre.h
+++ b/datapath-windows/ovsext/Gre.h
@@ -17,8 +17,11 @@
#ifndef __GRE_H_
#define __GRE_H_ 1
-#include "NetProto.h"
#include "Flow.h"
+#include "IpHelper.h"
+#include "NetProto.h"
+
+typedef union _OVS_FWD_INFO *POVS_FWD_INFO;
typedef struct _OVS_GRE_VPORT {
UINT64 ipId;
@@ -66,7 +69,8 @@ NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport,
OvsIPv4TunnelKey *tunKey,
POVS_SWITCH_CONTEXT switchContext,
POVS_PACKET_HDR_INFO layers,
- PNET_BUFFER_LIST *newNbl);
+ PNET_BUFFER_LIST *newNbl,
+ POVS_FWD_INFO switchFwdInfo);
NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
PNET_BUFFER_LIST curNbl,
diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c
index 636cf9526..0220572cc 100644
--- a/datapath-windows/ovsext/IpHelper.c
+++ b/datapath-windows/ovsext/IpHelper.c
@@ -19,6 +19,8 @@
#include "Switch.h"
#include "Jhash.h"
+extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
+
#ifdef OVS_DBG_MOD
#undef OVS_DBG_MOD
#endif
@@ -26,28 +28,44 @@
#include "Debug.h"
/*
- * Fow now, we assume only one internal adapter
+ * IpHelper supports multiple internal adapters.
*/
KSTART_ROUTINE OvsStartIpHelper;
+/* Contains the entries of internal adapter objects. */
+static LIST_ENTRY ovsInstanceList;
+
+/* Passive-level lock used to protect the internal adapter object list. */
+static ERESOURCE ovsInstanceListLock;
/*
+ * This structure is used to define each adapter instance.
+ *
+ * Note:
* Only when the internal IP is configured and virtual
* internal port is connected, the IP helper request can be
* queued.
+ *
+ * We only keep internal IP for reference, it will not be used for determining
+ * SRC IP of the Tunnel.
+ *
+ * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the
+ * route manipulation functions, i.e. GetBestRoute, to work.
*/
-static BOOLEAN ovsInternalIPConfigured;
-static BOOLEAN ovsInternalAdapterUp;
-static GUID ovsInternalNetCfgId;
-static MIB_IF_ROW2 ovsInternalRow;
-static MIB_IPINTERFACE_ROW ovsInternalIPRow;
-
-/* we only keep one internal IP for reference, it will not be used for
- * determining SRC IP of Tunnel
- */
-static UINT32 ovsInternalIP;
+typedef struct _OVS_IPHELPER_INSTANCE
+{
+ LIST_ENTRY link;
+
+ BOOLEAN isIpConfigured;
+ UINT32 portNo;
+ GUID netCfgId;
+ MIB_IF_ROW2 internalRow;
+ MIB_IPINTERFACE_ROW internalIPRow;
+ UINT32 ipAddress;
+ ERESOURCE lock;
+} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;
/*
* FWD_ENTRY --------> IPFORWARD_ENTRY
@@ -82,9 +100,22 @@ static OVS_IP_HELPER_THREAD_CONTEXT ovsIpHelperThreadContext;
static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix);
static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf);
static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr);
+static VOID OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo);
static VOID OvsCleanupIpHelperRequestList(VOID);
static VOID OvsCleanupFwdTable(VOID);
static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);
+static POVS_IPHELPER_INSTANCE OvsIpHelperAllocateInstance(
+ POVS_IP_HELPER_REQUEST request);
+static VOID OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance);
+
+
+static VOID
+OvsDumpMessageWithGuid(char* message, GUID guid)
+{
+ OVS_LOG_INFO(message, guid.Data1, guid.Data2, guid.Data3,
+ *(UINT16 *)guid.Data4, guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+}
static VOID
OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
@@ -94,17 +125,9 @@ OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
ifRow->InterfaceLuid.Info.IfType);
OVS_LOG_INFO("InterfaceIndex: %d", ifRow->InterfaceIndex);
- OVS_LOG_INFO("Interface GUID: %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- ifRow->InterfaceGuid.Data1,
- ifRow->InterfaceGuid.Data2,
- ifRow->InterfaceGuid.Data3,
- *(UINT16 *)ifRow->InterfaceGuid.Data4,
- ifRow->InterfaceGuid.Data4[2],
- ifRow->InterfaceGuid.Data4[3],
- ifRow->InterfaceGuid.Data4[4],
- ifRow->InterfaceGuid.Data4[5],
- ifRow->InterfaceGuid.Data4[6],
- ifRow->InterfaceGuid.Data4[7]);
+ OvsDumpMessageWithGuid("Interface GUID: "
+ "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ ifRow->InterfaceGuid);
OVS_LOG_INFO("Perm MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
ifRow->PermanentPhysicalAddress[0],
ifRow->PermanentPhysicalAddress[1],
@@ -114,7 +137,6 @@ OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
ifRow->PermanentPhysicalAddress[5]);
}
-
static VOID
OvsDumpIfTable(PMIB_IF_TABLE2 ifTable)
{
@@ -325,30 +347,72 @@ OvsDumpRoute(const SOCKADDR_INET *sourceAddress,
NTSTATUS
-OvsGetRoute(NET_LUID interfaceLuid,
- const SOCKADDR_INET *destinationAddress,
+OvsGetRoute(SOCKADDR_INET *destinationAddress,
PMIB_IPFORWARD_ROW2 route,
- SOCKADDR_INET *sourceAddress)
+ SOCKADDR_INET *sourceAddress,
+ POVS_IPHELPER_INSTANCE *instance,
+ POVS_VPORT_ENTRY* vport,
+ UINT32 srcIp)
{
- NTSTATUS status;
+ NTSTATUS status = STATUS_NETWORK_UNREACHABLE;
+ NTSTATUS result = STATUS_SUCCESS;
+ PLIST_ENTRY head, link, next;
+ ULONG minMetric = MAXULONG;
if (destinationAddress == NULL || route == NULL) {
return STATUS_INVALID_PARAMETER;
}
- status = GetBestRoute2(&interfaceLuid, 0,
- NULL, destinationAddress,
- 0, route, sourceAddress);
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ SOCKADDR_INET crtSrcAddr = { 0 };
+ MIB_IPFORWARD_ROW2 crtRoute = { 0 };
+ POVS_IPHELPER_INSTANCE crtInstance = NULL;
+ WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
- if (status != STATUS_SUCCESS) {
- UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
- OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
- return status;
+ crtInstance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&crtInstance->lock, TRUE);
+ result = GetBestRoute2(&crtInstance->internalRow.InterfaceLuid, 0,
+ NULL, destinationAddress, 0, &crtRoute,
+ &crtSrcAddr);
+
+ if (result != STATUS_SUCCESS) {
+ ExReleaseResourceLite(&crtInstance->lock);
+ continue;
+ }
+
+ if (minMetric > crtRoute.Metric &&
+ (!srcIp || srcIp == crtSrcAddr.Ipv4.sin_addr.S_un.S_addr)) {
+ status = STATUS_SUCCESS;
+ size_t len = 0;
+ minMetric = crtRoute.Metric;
+ LOCK_STATE_EX lockState;
+
+ RtlCopyMemory(sourceAddress, &crtSrcAddr, sizeof(*sourceAddress));
+ RtlCopyMemory(route, &crtRoute, sizeof(*route));
+ *instance = crtInstance;
+
+ ConvertInterfaceLuidToAlias(&crtInstance->internalRow.InterfaceLuid,
+ interfaceName, IF_MAX_STRING_SIZE + 1);
+ RtlStringCbLengthW(interfaceName, IF_MAX_STRING_SIZE, &len);
+
+ if (gOvsSwitchContext != NULL) {
+ NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock,
+ &lockState, 0);
+ *vport = OvsFindVportByHvNameW(gOvsSwitchContext,
+ interfaceName,
+ len);
+ NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
+ }
+ }
+ ExReleaseResourceLite(&crtInstance->lock);
}
+ ExReleaseResourceLite(&ovsInstanceListLock);
OvsDumpRoute(sourceAddress, destinationAddress, route);
+
return status;
}
@@ -358,8 +422,8 @@ OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh)
UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
OVS_LOG_INFO("Neigh: %d.%d.%d.%d",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
ipNeigh->PhysicalAddress[0],
ipNeigh->PhysicalAddress[1],
@@ -421,7 +485,8 @@ OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
NTSTATUS
-OvsGetOrResolveIPNeigh(UINT32 ipAddr,
+OvsGetOrResolveIPNeigh(MIB_IF_ROW2 ipRow,
+ UINT32 ipAddr,
PMIB_IPNET_ROW2 ipNeigh)
{
NTSTATUS status;
@@ -429,8 +494,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
ASSERT(ipNeigh);
RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
- ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
- ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
+ ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value;
+ ipNeigh->InterfaceIndex = ipRow.InterfaceIndex;
ipNeigh->Address.si_family = AF_INET;
ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
@@ -438,8 +503,8 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
if (status != STATUS_SUCCESS) {
RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
- ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
- ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
+ ipNeigh->InterfaceLuid.Value = ipRow.InterfaceLuid.Value;
+ ipNeigh->InterfaceIndex = ipRow.InterfaceIndex;
ipNeigh->Address.si_family = AF_INET;
ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
status = OvsResolveIPNeighEntry(ipNeigh);
@@ -447,57 +512,225 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
return status;
}
+static __inline BOOLEAN
+OvsCheckInstanceRow(PMIB_IF_ROW2 instanceRow,
+ PNET_LUID netLuid,
+ NET_IFINDEX ifIndex)
+{
+ return (instanceRow->InterfaceLuid.Info.NetLuidIndex ==
+ netLuid->Info.NetLuidIndex &&
+ instanceRow->InterfaceLuid.Info.IfType ==
+ netLuid->Info.IfType &&
+ instanceRow->InterfaceIndex ==
+ ifIndex);
+}
static VOID
-OvsChangeCallbackIpInterface(PVOID context,
- PMIB_IPINTERFACE_ROW ipRow,
- MIB_NOTIFICATION_TYPE notificationType)
+OvsUpdateIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
{
- UNREFERENCED_PARAMETER(context);
- switch (notificationType) {
- case MibParameterNotification:
- case MibAddInstance:
- if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow,
+ &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)) {
+
/*
* Update the IP Interface Row
*/
- NdisAcquireSpinLock(&ovsIpHelperLock);
- RtlCopyMemory(&ovsInternalIPRow, ipRow,
- sizeof (PMIB_IPINTERFACE_ROW));
- ovsInternalIPConfigured = TRUE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ RtlCopyMemory(&instance->internalIPRow, ipRow,
+ sizeof(PMIB_IPINTERFACE_ROW));
+ instance->isIpConfigured = TRUE;
+
+ OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s",
+ ipRow->InterfaceLuid.Info.NetLuidIndex,
+ ipRow->InterfaceLuid.Info.IfType,
+ "modified");
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
}
- OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s",
- ipRow->InterfaceLuid.Info.NetLuidIndex,
- ipRow->InterfaceLuid.Info.IfType,
- notificationType == MibAddInstance ? "added" : "modified");
- break;
- case MibDeleteInstance:
- OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d, deleted",
- ipRow->InterfaceLuid.Info.NetLuidIndex,
- ipRow->InterfaceLuid.Info.IfType);
- if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalIPConfigured = FALSE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ return;
+}
+
+static VOID
+OvsAddIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
+{
+ PLIST_ENTRY head, link, next;
+ BOOLEAN found = FALSE;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)) {
+
+ instance->isIpConfigured = FALSE;
+ ExReleaseResourceLite(&instance->lock);
+
+ found = TRUE;
+
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
- OvsCleanupIpHelperRequestList();
+ if (found != TRUE) {
+ NTSTATUS status;
+ POVS_IPHELPER_INSTANCE instance = NULL;
+ MIB_UNICASTIPADDRESS_ROW ipEntry;
+ BOOLEAN error = TRUE;
+ LOCK_STATE_EX lockState;
- OvsCleanupFwdTable();
+ instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(
+ sizeof(*instance), OVS_IPHELPER_POOL_TAG);
+ if (instance == NULL) {
+ goto error;
+ }
+ RtlZeroMemory(instance, sizeof(*instance));
+
+ InitializeListHead(&instance->link);
+ ExInitializeResourceLite(&instance->lock);
+ WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
+ status = ConvertInterfaceLuidToAlias(&ipRow->InterfaceLuid,
+ interfaceName,
+ IF_MAX_STRING_SIZE + 1);
+ if (gOvsSwitchContext == NULL) {
+ goto error;
+ }
+ NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);
+ POVS_VPORT_ENTRY vport = OvsFindVportByHvNameW(gOvsSwitchContext,
+ interfaceName,
+ sizeof(WCHAR) *
+ wcslen(interfaceName));
+
+ if (vport != NULL) {
+ RtlCopyMemory(&instance->netCfgId,
+ &vport->netCfgInstanceId,
+ sizeof(instance->netCfgId));
+ instance->portNo = vport->portNo;
+ }
+ NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
+ RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));
+ RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));
+ status = OvsGetIfEntry(&instance->netCfgId,
+ &instance->internalRow);
+
+ if (status != STATUS_SUCCESS) {
+ OvsDumpMessageWithGuid("Fail to get IF entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId);
+ goto error;
}
+ status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,
+ &instance->internalIPRow);
+
+ if (status == STATUS_SUCCESS) {
+ instance->isIpConfigured = TRUE;
+ } else {
+ goto error;
+ }
+
+ status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);
+ if (status != STATUS_SUCCESS) {
+ OvsDumpMessageWithGuid("Failed to get IP entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId);
+ }
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ InsertHeadList(&ovsInstanceList, &instance->link);
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ error = FALSE;
+
+error:
+ if (error) {
+ OvsIpHelperDeleteInstance(instance);
+ }
+ }
+
+ return;
+}
+
+static VOID
+OvsRemoveIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)
+{
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,
+ ipRow->InterfaceIndex)) {
+
+ instance->isIpConfigured = FALSE;
+ RemoveEntryList(&instance->link);
+
+ ExReleaseResourceLite(&instance->lock);
+ OvsIpHelperDeleteInstance(instance);
+
+ OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is "\
+ "deleted",
+ ipRow->InterfaceLuid.Info.NetLuidIndex,
+ ipRow->InterfaceLuid.Info.IfType);
+
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (IsListEmpty(&ovsInstanceList)) {
+ OvsCleanupIpHelperRequestList();
+ OvsCleanupFwdTable();
+ }
+
+ return;
+}
+
+static VOID
+OvsChangeCallbackIpInterface(PVOID context,
+ PMIB_IPINTERFACE_ROW ipRow,
+ MIB_NOTIFICATION_TYPE notificationType)
+{
+ UNREFERENCED_PARAMETER(context);
+ switch (notificationType) {
+ case MibParameterNotification:
+ OvsUpdateIpInterfaceNotification(ipRow);
+ break;
+ case MibAddInstance:
+ OvsAddIpInterfaceNotification(ipRow);
+ break;
+
+ case MibDeleteInstance:
+ OvsRemoveIpInterfaceNotification(ipRow);
break;
case MibInitialNotification:
- OVS_LOG_INFO("Get Initial notification for IP Interface change.");
+ OVS_LOG_INFO("Got Initial notification for IP Interface change.");
default:
return;
}
@@ -529,10 +762,21 @@ OvsChangeCallbackIpRoute(PVOID context,
case MibParameterNotification:
case MibDeleteInstance:
+ {
ASSERT(ipRoute);
ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
+ POVS_IPFORWARD_ENTRY ipf;
+ LOCK_STATE_EX lockState;
+
+ NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
+ ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix);
+ if (ipf != NULL) {
+ OvsRemoveIPForwardEntry(ipf);
+ }
+ NdisReleaseRWLock(ovsTableLock, &lockState);
+
OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
ipAddr & 0xff, (ipAddr >> 8) & 0xff,
(ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
@@ -541,24 +785,8 @@ OvsChangeCallbackIpRoute(PVOID context,
(nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
notificationType == MibDeleteInstance ? "deleted" :
"modified");
-
- if (ipRoute->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- ipRoute->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
-
- POVS_IPFORWARD_ENTRY ipf;
- LOCK_STATE_EX lockState;
-
- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
- ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix);
- if (ipf != NULL) {
- OvsRemoveIPForwardEntry(ipf);
- }
- NdisReleaseRWLock(ovsTableLock, &lockState);
- }
break;
+ }
case MibInitialNotification:
OVS_LOG_INFO("Get Initial notification for IP Route change.");
@@ -579,40 +807,85 @@ OvsChangeCallbackUnicastIpAddress(PVOID context,
switch (notificationType) {
case MibParameterNotification:
case MibAddInstance:
+ {
+ PLIST_ENTRY head, link, next;
+
ASSERT(unicastRow);
ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
- if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- unicastRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
- ovsInternalIP = ipAddr;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->isIpConfigured &&
+ OvsCheckInstanceRow(&instance->internalRow,
+ &unicastRow->InterfaceLuid,
+ unicastRow->InterfaceIndex)) {
+
+ instance->ipAddress = ipAddr;
+
+ OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
+ notificationType == MibAddInstance ? "added": "modified");
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
}
- OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
- notificationType == MibAddInstance ? "added": "modified");
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
break;
+ }
case MibDeleteInstance:
+ {
+ PLIST_ENTRY head, link, next;
+ LOCK_STATE_EX lockState;
+ BOOLEAN found = FALSE;
+
ASSERT(unicastRow);
ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
- OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
- ipAddr & 0xff, (ipAddr >> 8) & 0xff,
- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
- if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
- ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
- unicastRow->InterfaceLuid.Info.IfType ==
- ovsInternalRow.InterfaceLuid.Info.IfType &&
- unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
- LOCK_STATE_EX lockState;
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &(ovsInstanceList);
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->isIpConfigured &&
+ OvsCheckInstanceRow(&instance->internalRow,
+ &unicastRow->InterfaceLuid,
+ unicastRow->InterfaceIndex)) {
+
+ found = TRUE;
+
+ ExReleaseResourceLite(&instance->lock);
+ break;
+ }
+ ExReleaseResourceLite(&instance->lock);
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ if (found) {
NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
OvsRemoveAllFwdEntriesWithSrc(ipAddr);
NdisReleaseRWLock(ovsTableLock, &lockState);
+ OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
}
+
break;
+ }
case MibInitialNotification:
OVS_LOG_INFO("Get Initial notification for Unicast IP Address change.");
@@ -651,7 +924,7 @@ OvsRegisterChangeNotification()
&ipInterfaceNotificationHandle);
if (status != STATUS_SUCCESS) {
OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.",
- status);
+ status);
return status;
}
@@ -659,7 +932,7 @@ OvsRegisterChangeNotification()
TRUE, &ipRouteNotificationHandle);
if (status != STATUS_SUCCESS) {
OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.",
- status);
+ status);
goto register_cleanup;
}
status = NotifyUnicastIpAddressChange(AF_INET,
@@ -682,10 +955,11 @@ static POVS_IPNEIGH_ENTRY
OvsLookupIPNeighEntry(UINT32 ipAddr)
{
PLIST_ENTRY link;
- POVS_IPNEIGH_ENTRY entry;
UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS);
LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) {
+ POVS_IPNEIGH_ENTRY entry;
+
entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link);
if (entry->ipAddr == ipAddr) {
return entry;
@@ -709,7 +983,6 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
{
PLIST_ENTRY link;
- POVS_IPFORWARD_ENTRY ipfEntry;
UINT32 hash;
ASSERT(prefix->Prefix.si_family == AF_INET);
@@ -720,6 +993,8 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
hash = OvsHashIPPrefix(prefix);
LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) {
+ POVS_IPFORWARD_ENTRY ipfEntry;
+
ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link);
if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength &&
ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr ==
@@ -732,15 +1007,17 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
static POVS_FWD_ENTRY
-OvsLookupIPFwdEntry(UINT32 dstIp)
+OvsLookupIPFwdEntry(UINT32 srcIp, UINT32 dstIp)
{
PLIST_ENTRY link;
- POVS_FWD_ENTRY entry;
UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS);
LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) {
+ POVS_FWD_ENTRY entry;
+
entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
- if (entry->info.dstIpAddr == dstIp) {
+ if (entry->info.dstIpAddr == dstIp &&
+ (!srcIp || entry->info.srcIpAddr == srcIp)) {
return entry;
}
}
@@ -749,7 +1026,8 @@ OvsLookupIPFwdEntry(UINT32 dstIp)
NTSTATUS
-OvsLookupIPFwdInfo(UINT32 dstIp,
+OvsLookupIPFwdInfo(UINT32 srcIp,
+ UINT32 dstIp,
POVS_FWD_INFO info)
{
POVS_FWD_ENTRY entry;
@@ -757,11 +1035,10 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
NTSTATUS status = STATUS_NOT_FOUND;
NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);
- entry = OvsLookupIPFwdEntry(dstIp);
+ entry = OvsLookupIPFwdEntry(srcIp, dstIp);
if (entry) {
- info->value[0] = entry->info.value[0];
- info->value[1] = entry->info.value[1];
- info->value[2] = entry->info.value[2];
+ RtlCopyMemory(info->value, entry->info.value,
+ sizeof entry->info.value);
status = STATUS_SUCCESS;
}
NdisReleaseRWLock(ovsTableLock, &lockState);
@@ -770,7 +1047,8 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
static POVS_IPNEIGH_ENTRY
-OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
+OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh,
+ POVS_IPHELPER_INSTANCE instance)
{
POVS_IPNEIGH_ENTRY entry;
@@ -790,6 +1068,7 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,
ETH_ADDR_LEN);
InitializeListHead(&entry->fwdList);
+ entry->context = (PVOID)instance;
return entry;
}
@@ -798,7 +1077,6 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
static POVS_IPFORWARD_ENTRY
OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)
{
-
POVS_IPFORWARD_ENTRY entry;
ASSERT(ipRoute);
@@ -876,12 +1154,13 @@ OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry)
static VOID
OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf)
{
- POVS_FWD_ENTRY fwdEntry;
PLIST_ENTRY link, next;
ipf->refCount++;
LIST_FORALL_SAFE(&ipf->fwdList, link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);
OvsRemoveFwdEntry(fwdEntry);
}
@@ -896,11 +1175,12 @@ static VOID
OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn)
{
PLIST_ENTRY link, next;
- POVS_FWD_ENTRY fwdEntry;
ipn->refCount++;
LIST_FORALL_SAFE(&ipn->fwdList, link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);
OvsRemoveFwdEntry(fwdEntry);
}
@@ -919,10 +1199,10 @@ static VOID
OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn)
{
PLIST_ENTRY link;
- POVS_IPNEIGH_ENTRY entry;
if (!IsListEmpty(&ovsSortedIPNeighList)) {
link = ovsSortedIPNeighList.Blink;
+ POVS_IPNEIGH_ENTRY entry;
entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
if (entry->timeout > ipn->timeout) {
ipn->timeout++;
@@ -973,11 +1253,12 @@ static VOID
OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
{
UINT32 i;
- POVS_FWD_ENTRY fwdEntry;
PLIST_ENTRY link, next;
for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
if (fwdEntry->info.srcIpAddr == ipAddr) {
OvsRemoveFwdEntry(fwdEntry);
@@ -988,19 +1269,38 @@ OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
static VOID
+OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo)
+{
+ UINT32 i;
+ PLIST_ENTRY link, next;
+
+ for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
+ LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
+ POVS_FWD_ENTRY fwdEntry;
+
+ fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
+ if (fwdEntry->info.srcPortNo == portNo) {
+ OvsRemoveFwdEntry(fwdEntry);
+ }
+ }
+ }
+}
+
+static VOID
OvsCleanupFwdTable(VOID)
{
PLIST_ENTRY link, next;
- POVS_IPNEIGH_ENTRY ipn;
UINT32 i;
LOCK_STATE_EX lockState;
NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
if (ovsNumFwdEntries) {
- LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {
- ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
- OvsRemoveIPNeighEntry(ipn);
- }
+ LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {
+ POVS_IPNEIGH_ENTRY ipn;
+
+ ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
+ OvsRemoveIPNeighEntry(ipn);
+ }
}
for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
ASSERT(IsListEmpty(&ovsFwdHashTable[i]));
@@ -1017,20 +1317,16 @@ OvsCleanupIpHelperRequestList(VOID)
{
LIST_ENTRY list;
PLIST_ENTRY next, link;
- POVS_IP_HELPER_REQUEST request;
NdisAcquireSpinLock(&ovsIpHelperLock);
- if (ovsNumIpHelperRequests == 0) {
- NdisReleaseSpinLock(&ovsIpHelperLock);
- return;
- }
-
InitializeListHead(&list);
- OvsAppendList(&list, &ovsIpHelperRequestList);
+ OvsAppendList(&list, &ovsIpHelperRequestList);
ovsNumIpHelperRequests = 0;
NdisReleaseSpinLock(&ovsIpHelperLock);
LIST_FORALL_SAFE(&list, link, next) {
+ POVS_IP_HELPER_REQUEST request;
+
request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
if (request->command == OVS_IP_HELPER_FWD_REQUEST &&
@@ -1056,27 +1352,40 @@ OvsWakeupIPHelper(VOID)
}
VOID
-OvsInternalAdapterDown(VOID)
+OvsInternalAdapterDown(UINT32 portNo,
+ GUID netCfgInstanceId)
{
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalAdapterUp = FALSE;
- ovsInternalIPConfigured = FALSE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ POVS_IP_HELPER_REQUEST request;
- OvsCleanupIpHelperRequestList();
+ request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(
+ sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);
+ if (request == NULL) {
+ OVS_LOG_ERROR("Fail to initialize Internal Adapter");
+ return;
+ }
+ RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));
+ RtlCopyMemory(&request->instanceReq.netCfgInstanceId,
+ &netCfgInstanceId,
+ sizeof(netCfgInstanceId));
+ request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN;
+ request->instanceReq.portNo = portNo;
- OvsCleanupFwdTable();
+ NdisAcquireSpinLock(&ovsIpHelperLock);
+ InsertHeadList(&ovsIpHelperRequestList, &request->link);
+ ovsNumIpHelperRequests++;
+ if (ovsNumIpHelperRequests == 1) {
+ OvsWakeupIPHelper();
+ }
+ NdisReleaseSpinLock(&ovsIpHelperLock);
}
VOID
-OvsInternalAdapterUp(GUID *netCfgInstanceId)
+OvsInternalAdapterUp(UINT32 portNo,
+ GUID *netCfgInstanceId)
{
POVS_IP_HELPER_REQUEST request;
- RtlCopyMemory(&ovsInternalNetCfgId, netCfgInstanceId, sizeof (GUID));
- RtlZeroMemory(&ovsInternalRow, sizeof (MIB_IF_ROW2));
-
request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(
sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);
if (request == NULL) {
@@ -1084,10 +1393,13 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId)
return;
}
RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));
+ RtlCopyMemory(&request->instanceReq.netCfgInstanceId,
+ netCfgInstanceId,
+ sizeof(*netCfgInstanceId));
request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP;
+ request->instanceReq.portNo = portNo;
NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalAdapterUp = TRUE;
InsertHeadList(&ovsIpHelperRequestList, &request->link);
ovsNumIpHelperRequests++;
if (ovsNumIpHelperRequests == 1) {
@@ -1099,58 +1411,116 @@ OvsInternalAdapterUp(GUID *netCfgInstanceId)
}
+static POVS_IPHELPER_INSTANCE
+OvsIpHelperAllocateInstance(POVS_IP_HELPER_REQUEST request)
+{
+ POVS_IPHELPER_INSTANCE instance = NULL;
+
+ instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(
+ sizeof(*instance), OVS_IPHELPER_POOL_TAG);
+ if (instance) {
+ RtlZeroMemory(instance, sizeof(*instance));
+
+ RtlCopyMemory(&instance->netCfgId,
+ &request->instanceReq.netCfgInstanceId,
+ sizeof(instance->netCfgId));
+ instance->portNo = request->instanceReq.portNo;
+
+ InitializeListHead(&instance->link);
+ ExInitializeResourceLite(&instance->lock);
+ }
+
+ return instance;
+}
+
+
+static VOID
+OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance)
+{
+ if (instance) {
+ ExDeleteResourceLite(&instance->lock);
+ OvsFreeMemoryWithTag(instance, OVS_IPHELPER_POOL_TAG);
+ }
+}
+
+
+static VOID
+OvsIpHelperDeleteAllInstances()
+{
+ PLIST_ENTRY head, link, next;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &ovsInstanceList;
+ if (!IsListEmpty(head)) {
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+
+ instance->isIpConfigured = FALSE;
+ RemoveEntryList(&instance->link);
+
+ ExReleaseResourceLite(&instance->lock);
+
+ OvsIpHelperDeleteInstance(instance);
+ }
+ }
+ ExReleaseResourceLite(&ovsInstanceListLock);
+}
+
+
static VOID
OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
{
NTSTATUS status;
+ POVS_IPHELPER_INSTANCE instance = NULL;
MIB_UNICASTIPADDRESS_ROW ipEntry;
- GUID *netCfgInstanceId = &ovsInternalNetCfgId;
+ BOOLEAN error = TRUE;
- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
+ do {
+ instance = OvsIpHelperAllocateInstance(request);
+ if (instance == NULL) {
+ break;
+ }
+ RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));
+ RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));
+ status = OvsGetIfEntry(&instance->netCfgId,
+ &instance->internalRow);
- status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow);
+ if (status != STATUS_SUCCESS) {
+ OvsDumpMessageWithGuid("Fail to get IF entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId);
+ break;
+ }
- if (status != STATUS_SUCCESS) {
- OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID"
- " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- netCfgInstanceId->Data1,
- netCfgInstanceId->Data2,
- netCfgInstanceId->Data3,
- *(UINT16 *)netCfgInstanceId->Data4,
- netCfgInstanceId->Data4[2],
- netCfgInstanceId->Data4[3],
- netCfgInstanceId->Data4[4],
- netCfgInstanceId->Data4[5],
- netCfgInstanceId->Data4[6],
- netCfgInstanceId->Data4[7]);
- return;
- }
+ status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,
+ &instance->internalIPRow);
- status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid,
- &ovsInternalIPRow);
+ if (status == STATUS_SUCCESS) {
+ instance->isIpConfigured = TRUE;
+ } else {
+ break;
+ }
- if (status == STATUS_SUCCESS) {
- NdisAcquireSpinLock(&ovsIpHelperLock);
- ovsInternalIPConfigured = TRUE;
- NdisReleaseSpinLock(&ovsIpHelperLock);
- } else {
- return;
- }
+ status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);
+ if (status != STATUS_SUCCESS) {
+ OvsDumpMessageWithGuid("Fail to get IP entry for internal port with GUID"
+ " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ instance->netCfgId);
+ }
- status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry);
- if (status != STATUS_SUCCESS) {
- OVS_LOG_INFO("Fali to get IP entry for internal port with GUID"
- " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- netCfgInstanceId->Data1,
- netCfgInstanceId->Data2,
- netCfgInstanceId->Data3,
- *(UINT16 *)netCfgInstanceId->Data4,
- netCfgInstanceId->Data4[2],
- netCfgInstanceId->Data4[3],
- netCfgInstanceId->Data4[4],
- netCfgInstanceId->Data4[5],
- netCfgInstanceId->Data4[6],
- netCfgInstanceId->Data4[7]);
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ InsertHeadList(&ovsInstanceList, &instance->link);
+ ExReleaseResourceLite(&ovsInstanceListLock);
+
+ error = FALSE;
+ } while (error);
+
+ OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
+ if (error) {
+ OvsIpHelperDeleteInstance(instance);
}
}
@@ -1158,15 +1528,11 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
static NTSTATUS
OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request)
{
-
- NdisAcquireSpinLock(&ovsIpHelperLock);
-
- if (ovsInternalAdapterUp == FALSE ||
- ovsInternalIPConfigured == FALSE) {
- NdisReleaseSpinLock(&ovsIpHelperLock);
+ if (IsListEmpty(&ovsInstanceList)) {
OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);
return STATUS_NDIS_ADAPTER_NOT_READY;
} else {
+ NdisAcquireSpinLock(&ovsIpHelperLock);
InsertHeadList(&ovsIpHelperRequestList, &request->link);
ovsNumIpHelperRequests++;
if (ovsNumIpHelperRequests == 1) {
@@ -1214,7 +1580,7 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
NTSTATUS status;
MIB_IPFORWARD_ROW2 ipRoute;
MIB_IPNET_ROW2 ipNeigh;
- OVS_FWD_INFO fwdInfo;
+ OVS_FWD_INFO fwdInfo = { 0 };
UINT32 ipAddr;
UINT32 srcAddr;
POVS_FWD_ENTRY fwdEntry = NULL;
@@ -1224,8 +1590,10 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
BOOLEAN newIPF = FALSE;
BOOLEAN newIPN = FALSE;
BOOLEAN newFWD = FALSE;
+ POVS_IPHELPER_INSTANCE instance = NULL;
- status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.dst,
+ status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.src,
+ request->fwdReq.tunnelKey.dst,
&fwdInfo);
if (status == STATUS_SUCCESS) {
goto fwd_handle_nbl;
@@ -1238,10 +1606,23 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
dst.si_family = AF_INET;
dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst;
- status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src);
- if (status != STATUS_SUCCESS) {
+ status = OvsGetRoute(&dst, &ipRoute, &src, &instance, &fwdInfo.vport, request->fwdReq.tunnelKey.src);
+ if (request->fwdReq.tunnelKey.src && request->fwdReq.tunnelKey.src != src.Ipv4.sin_addr.s_addr) {
+ UINT32 ipAddr = dst.Ipv4.sin_addr.s_addr;
+ OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
+ goto fwd_handle_nbl;
+ }
+ if (status != STATUS_SUCCESS || instance == NULL) {
+ UINT32 ipAddr = dst.Ipv4.sin_addr.s_addr;
+ OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
+ ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+ (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
goto fwd_handle_nbl;
}
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
srcAddr = src.Ipv4.sin_addr.s_addr;
/* find IPNeigh */
@@ -1254,13 +1635,16 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
}
NdisReleaseRWLock(ovsTableLock, &lockState);
}
+
RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));
- ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
+ ipNeigh.InterfaceLuid.Value = instance->internalRow.InterfaceLuid.Value;
if (ipAddr == 0) {
ipAddr = request->fwdReq.tunnelKey.dst;
}
- status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
+ status = OvsGetOrResolveIPNeigh(instance->internalRow,
+ ipAddr, &ipNeigh);
if (status != STATUS_SUCCESS) {
+ ExReleaseResourceLite(&instance->lock);
goto fwd_handle_nbl;
}
@@ -1276,6 +1660,7 @@ fwd_request_done:
ipf = OvsCreateIPForwardEntry(&ipRoute);
if (ipf == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
@@ -1284,6 +1669,13 @@ fwd_request_done:
PLIST_ENTRY link;
link = ipf->fwdList.Flink;
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);
+ if (fwdEntry->info.srcIpAddr != srcAddr) {
+ OvsRemoveFwdEntry(fwdEntry);
+ NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto fwd_handle_nbl;
+ }
srcAddr = fwdEntry->info.srcIpAddr;
}
@@ -1293,9 +1685,10 @@ fwd_request_done:
if (ipn == NULL) {
ipn = OvsLookupIPNeighEntry(ipAddr);
if (ipn == NULL) {
- ipn = OvsCreateIPNeighEntry(&ipNeigh);
+ ipn = OvsCreateIPNeighEntry(&ipNeigh, instance);
if (ipn == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
@@ -1309,22 +1702,26 @@ fwd_request_done:
fwdInfo.dstIpAddr = request->fwdReq.tunnelKey.dst;
fwdInfo.srcIpAddr = srcAddr;
RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, ETH_ADDR_LEN);
- RtlCopyMemory(fwdInfo.srcMacAddr, ovsInternalRow.PhysicalAddress,
+ RtlCopyMemory(fwdInfo.srcMacAddr, instance->internalRow.PhysicalAddress,
ETH_ADDR_LEN);
fwdInfo.srcPortNo = request->fwdReq.inPort;
fwdEntry = OvsCreateFwdEntry(&fwdInfo);
if (fwdEntry == NULL) {
NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
status = STATUS_INSUFFICIENT_RESOURCES;
goto fwd_handle_nbl;
}
newFWD = TRUE;
- /*
- * Cache the result
- */
- OvsAddIPFwdCache(fwdEntry, ipf, ipn);
- NdisReleaseRWLock(ovsTableLock, &lockState);
+ if (status == STATUS_SUCCESS) {
+ /*
+ * Cache the result
+ */
+ OvsAddIPFwdCache(fwdEntry, ipf, ipn);
+ NdisReleaseRWLock(ovsTableLock, &lockState);
+ ExReleaseResourceLite(&instance->lock);
+ }
fwd_handle_nbl:
@@ -1391,7 +1788,6 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr,
(const PVOID)ipNeigh->PhysicalAddress,
(size_t)ETH_ADDR_LEN)) {
PLIST_ENTRY link;
- POVS_FWD_ENTRY fwdEntry;
NdisReleaseRWLock(ovsTableLock, &lockState);
/*
* need update, release and acquire write lock
@@ -1407,6 +1803,7 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr,
}
LIST_FORALL(&ipn->fwdList, link) {
+ POVS_FWD_ENTRY fwdEntry;
fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);
RtlCopyMemory(fwdEntry->info.dstMacAddr,
ipNeigh->PhysicalAddress, ETH_ADDR_LEN);
@@ -1425,28 +1822,15 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr,
NdisReleaseRWLock(ovsTableLock, &lockState);
}
-
-static VOID
-OvsHandleIPNeighTimeout(UINT32 ipAddr)
-{
- MIB_IPNET_ROW2 ipNeigh;
- NTSTATUS status;
-
- status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
-
- OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);
-}
-
-
/*
*----------------------------------------------------------------------------
- * IP Helper system threash handle following request
+ * IP Helper system thread handles the following requests:
* 1. Intialize Internal port row when internal port is connected
* 2. Handle FWD request
* 3. Handle IP Neigh timeout
*
* IP Interface, unicast address, and IP route change will be handled
- * by the revelant callback.
+ * by the revelant callbacks.
*----------------------------------------------------------------------------
*/
VOID
@@ -1479,6 +1863,45 @@ OvsStartIpHelper(PVOID data)
case OVS_IP_HELPER_INTERNAL_ADAPTER_UP:
OvsHandleInternalAdapterUp(req);
break;
+ case OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN:
+ {
+ PLIST_ENTRY head, link, next;
+ UINT32 portNo = req->instanceReq.portNo;
+ GUID netCfgInstanceId = req->instanceReq.netCfgInstanceId;
+
+ ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
+ head = &ovsInstanceList;
+ LIST_FORALL_SAFE(head, link, next) {
+ POVS_IPHELPER_INSTANCE instance = NULL;
+ LOCK_STATE_EX lockState;
+
+ instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);
+
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
+ if (instance->portNo == portNo &&
+ IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) {
+
+ NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
+ 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 8562f868c..6bda1b12a 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 b04a77f04..9da81dc4e 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 1b7e79703..988a1c1eb 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 001335a1e..7c9862183 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 428259bdd..e9e22aaeb 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 1f4968ee7..4dc4e0094 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 db452483a..949e069b7 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 b9462f0ba..f4a8bceba 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,