#include "Event.h"
#include "User.h"
#include "Vxlan.h"
+#include "Stt.h"
#include "IpHelper.h"
#include "Oid.h"
#include "Datapath.h"
static NDIS_STATUS InitHvVportCommon(POVS_SWITCH_CONTEXT switchContext,
POVS_VPORT_ENTRY vport,
BOOLEAN newPort);
-static VOID OvsCleanupVportCommon(POVS_SWITCH_CONTEXT switchContext,
- POVS_VPORT_ENTRY vport,
- BOOLEAN hvSwitchPort,
- BOOLEAN hvDelete,
- BOOLEAN ovsDelete);
+static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
+ POVS_SWITCH_CONTEXT switchContext,
+ POVS_VPORT_ENTRY vport,
+ BOOLEAN hvDelete,
+ BOOLEAN ovsDelete);
static VOID OvsTunnelVportPendingInit(PVOID context,
NTSTATUS status,
UINT32 *replyLen);
-static VOID OvsTunnelVportPendingUninit(PVOID context,
+static VOID OvsTunnelVportPendingRemove(PVOID context,
NTSTATUS status,
UINT32 *replyLen);
vport = OvsFindVportByHvNameW(gOvsSwitchContext,
portParam->PortFriendlyName.String,
portParam->PortFriendlyName.Length);
- if (vport && vport->isPresentOnHv == FALSE) {
+ if (vport && vport->isAbsentOnHv == FALSE) {
OVS_LOG_ERROR("Port add failed since a port already exists on "
"the specified port Id: %u, ovsName: %s",
portParam->PortId, vport->ovsName);
}
if (vport != NULL) {
- ASSERT(vport->isPresentOnHv);
+ ASSERT(vport->isAbsentOnHv);
ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);
/*
status = STATUS_DATA_NOT_ACCEPTED;
goto create_port_done;
}
- vport->isPresentOnHv = FALSE;
+ vport->isAbsentOnHv = FALSE;
} else {
vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
if (vport == NULL) {
/* Store the nic and the OVS states as Nic Create won't be called */
ovsState = vport->ovsState;
nicState = vport->nicState;
-
+
/*
* Currently only the port friendly name is being updated
* Make sure that no other properties are changed
}
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort,
+ OVS_VPORT_TYPE ovsPortType)
+{
+ POVS_VPORT_ENTRY vport;
+ PLIST_ENTRY head, link;
+ UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort),
+ OVS_HASH_BASIS);
+ head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]);
+ LIST_FORALL(head, link) {
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink);
+ if (GetPortFromPriv(vport) == dstPort &&
+ vport->ovsType == ovsPortType) {
+ return vport;
+ }
+ }
+ return NULL;
+}
+
+
POVS_VPORT_ENTRY
OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name)
}
RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY));
vport->ovsState = OVS_STATE_UNKNOWN;
- vport->isPresentOnHv = FALSE;
+ vport->isAbsentOnHv = FALSE;
vport->portNo = OVS_DPPORT_NUMBER_INVALID;
InitializeListHead(&vport->ovsNameLink);
{
POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL;
- tunnelContext = OvsAllocateMemory(sizeof(*tunnelContext));
+ tunnelContext = OvsAllocateMemoryWithTag(sizeof(*tunnelContext),
+ OVS_VPORT_POOL_TAG);
if (tunnelContext == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
dstPort,
OvsTunnelVportPendingInit,
(PVOID)tunnelContext);
+ if (status != STATUS_PENDING) {
+ OvsFreeMemoryWithTag(tunnelContext, OVS_VPORT_POOL_TAG);
+ tunnelContext = NULL;
+ }
break;
}
+ case OVS_VPORT_TYPE_STT:
+ status = OvsInitSttTunnel(vport, dstPort);
+ break;
default:
ASSERT(0);
}
* --------------------------------------------------------------------------
* Functionality common to any port added from OVS userspace.
*
- * Inserts the port into 'portIdHashArray', 'ovsPortNameHashArray' and caches
- * the pointer in the 'switchContext' if needed.
+ * Inserts the port into 'portNoHashArray', 'ovsPortNameHashArray' and in
+ * 'tunnelVportsArray' if appropriate.
* --------------------------------------------------------------------------
*/
NDIS_STATUS
switch(vport->ovsType) {
case OVS_VPORT_TYPE_VXLAN:
- switchContext->vxlanVport = vport;
+ case OVS_VPORT_TYPE_STT:
+ {
+ UINT16 dstPort = GetPortFromPriv(vport);
+ hash = OvsJhashBytes(&dstPort,
+ sizeof(dstPort),
+ OVS_HASH_BASIS);
+ InsertHeadList(
+ &gOvsSwitchContext->tunnelVportsArray[hash & OVS_VPORT_MASK],
+ &vport->tunnelVportLink);
switchContext->numNonHvVports++;
break;
+ }
case OVS_VPORT_TYPE_INTERNAL:
if (vport->isBridgeInternal) {
switchContext->numNonHvVports++;
return STATUS_SUCCESS;
}
-static VOID
-OvsCleanupVportCommon(POVS_SWITCH_CONTEXT switchContext,
- POVS_VPORT_ENTRY vport,
- BOOLEAN hvSwitchPort,
- BOOLEAN hvDelete,
- BOOLEAN ovsDelete)
+
+/*
+ * --------------------------------------------------------------------------
+ * Provides functionality that is partly complementatry to
+ * InitOvsVportCommon()/InitHvVportCommon().
+ *
+ * 'hvDelete' indicates if caller is removing the vport as a result of the
+ * port being removed on the Hyper-V switch.
+ * 'ovsDelete' indicates if caller is removing the vport as a result of the
+ * port being removed from OVS userspace.
+ * --------------------------------------------------------------------------
+ */
+NTSTATUS
+OvsRemoveAndDeleteVport(PVOID usrParamsContext,
+ POVS_SWITCH_CONTEXT switchContext,
+ POVS_VPORT_ENTRY vport,
+ BOOLEAN hvDelete,
+ BOOLEAN ovsDelete)
{
+ POVS_USER_PARAMS_CONTEXT usrParamsCtx =
+ (POVS_USER_PARAMS_CONTEXT)usrParamsContext;
+ BOOLEAN hvSwitchPort = FALSE;
BOOLEAN deletedOnOvs = FALSE;
BOOLEAN deletedOnHv = FALSE;
+ 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;
+ }
+ break;
+ case OVS_VPORT_TYPE_VXLAN:
+ {
+ NTSTATUS status;
+ status = OvsRemoveTunnelVport(usrParamsCtx, switchContext, vport,
+ hvDelete, ovsDelete);
+ if (status != STATUS_SUCCESS) {
+ return status;
+ }
+ }
+ case OVS_VPORT_TYPE_STT:
+ OvsCleanupSttTunnel(vport);
+ break;
+ case OVS_VPORT_TYPE_GRE:
+ case OVS_VPORT_TYPE_GRE64:
+ break;
+ case OVS_VPORT_TYPE_NETDEV:
+ if (vport->isExternal) {
+ if (vport->nicIndex == 0) {
+ /* Such a vport is not part of any of the hash tables, since it
+ * is not exposed to userspace. See Vport.h for explanation. */
+ ASSERT(hvDelete == TRUE);
+ ASSERT(switchContext->numPhysicalNics == 0);
+ switchContext->virtualExternalPortId = 0;
+ switchContext->virtualExternalVport = NULL;
+ OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
+ return STATUS_SUCCESS;
+ }
+ }
+ hvSwitchPort = TRUE;
+ default:
+ break;
+ }
+
/*
* 'hvDelete' == TRUE indicates that the port should be removed from the
* 'portIdHashArray', while 'ovsDelete' == TRUE indicates that the port
*
* Both 'hvDelete' and 'ovsDelete' can be set to TRUE by the caller.
*/
- if (vport->isPresentOnHv == TRUE) {
+ if (vport->isAbsentOnHv == TRUE) {
deletedOnHv = TRUE;
}
if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {
}
if (hvDelete && !deletedOnHv) {
- vport->isPresentOnHv = TRUE;
+ vport->isAbsentOnHv = TRUE;
+
+ if (vport->isExternal) {
+ ASSERT(vport->nicIndex != 0);
+ ASSERT(switchContext->numPhysicalNics);
+ switchContext->numPhysicalNics--;
+ }
/* Remove the port from the relevant lists. */
RemoveEntryList(&vport->portIdLink);
InitializeListHead(&vport->ovsNameLink);
RemoveEntryList(&vport->portNoLink);
InitializeListHead(&vport->portNoLink);
+ if (OVS_VPORT_TYPE_VXLAN == vport->ovsType ||
+ OVS_VPORT_TYPE_STT == vport->ovsType) {
+ RemoveEntryList(&vport->tunnelVportLink);
+ InitializeListHead(&vport->tunnelVportLink);
+ }
+
deletedOnOvs = TRUE;
}
if (deletedOnHv && deletedOnOvs) {
if (hvSwitchPort) {
switchContext->numHvVports--;
- }
- else {
+ } else {
switchContext->numNonHvVports--;
}
OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
}
+
+ return STATUS_SUCCESS;
}
-/*
- * --------------------------------------------------------------------------
- * Provides functionality that is partly complementatry to
- * InitOvsVportCommon()/InitHvVportCommon().
- *
- * 'hvDelete' indicates if caller is removing the vport as a result of the
- * port being removed on the Hyper-V switch.
- * 'ovsDelete' indicates if caller is removing the vport as a result of the
- * port being removed from OVS userspace.
- * --------------------------------------------------------------------------
- */
-NTSTATUS
-OvsRemoveAndDeleteVport(PVOID usrParamsContext,
- POVS_SWITCH_CONTEXT switchContext,
- POVS_VPORT_ENTRY vport,
- BOOLEAN hvDelete,
- BOOLEAN ovsDelete)
+static NTSTATUS
+OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
+ POVS_SWITCH_CONTEXT switchContext,
+ POVS_VPORT_ENTRY vport,
+ BOOLEAN hvDelete,
+ BOOLEAN ovsDelete)
{
- NTSTATUS status = STATUS_SUCCESS;
- POVS_USER_PARAMS_CONTEXT usrParamsCtx =
- (POVS_USER_PARAMS_CONTEXT)usrParamsContext;
- BOOLEAN hvSwitchPort = FALSE;
+ POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL;
+ PIRP irp = NULL;
- if (vport->isExternal) {
- if (vport->nicIndex == 0) {
- ASSERT(switchContext->numPhysicalNics == 0);
- switchContext->virtualExternalPortId = 0;
- switchContext->virtualExternalVport = NULL;
- OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
- return STATUS_SUCCESS;
- } else {
- ASSERT(switchContext->numPhysicalNics);
- switchContext->numPhysicalNics--;
- hvSwitchPort = TRUE;
- }
+ tunnelContext = OvsAllocateMemory(sizeof(*tunnelContext));
+ if (tunnelContext == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ RtlZeroMemory(tunnelContext, sizeof(*tunnelContext));
- switch (vport->ovsType) {
- case OVS_VPORT_TYPE_INTERNAL:
- if (!vport->isBridgeInternal) {
- switchContext->internalPortId = 0;
- switchContext->internalVport = NULL;
- OvsInternalAdapterDown();
- hvSwitchPort = TRUE;
- }
- break;
- case OVS_VPORT_TYPE_VXLAN:
- {
- POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL;
- PIRP irp = NULL;
-
- tunnelContext = OvsAllocateMemory(sizeof(*tunnelContext));
- if (tunnelContext == NULL) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- RtlZeroMemory(tunnelContext, sizeof(*tunnelContext));
-
- tunnelContext->switchContext = switchContext;
- tunnelContext->hvSwitchPort = hvSwitchPort;
- tunnelContext->hvDelete = hvDelete;
- tunnelContext->ovsDelete = ovsDelete;
- tunnelContext->vport = vport;
-
- if (usrParamsCtx) {
- tunnelContext->inputBuffer = usrParamsCtx->inputBuffer;
- tunnelContext->outputBuffer = usrParamsCtx->outputBuffer;
- tunnelContext->outputLength = usrParamsCtx->outputLength;
- irp = usrParamsCtx->irp;
- }
-
- status = OvsCleanupVxlanTunnel(irp,
- vport,
- OvsTunnelVportPendingUninit,
- tunnelContext);
-
- switchContext->vxlanVport = NULL;
- break;
- }
- case OVS_VPORT_TYPE_GRE:
- case OVS_VPORT_TYPE_GRE64:
- break;
- case OVS_VPORT_TYPE_NETDEV:
- hvSwitchPort = TRUE;
- default:
- break;
- }
+ tunnelContext->switchContext = switchContext;
+ tunnelContext->hvSwitchPort = FALSE;
+ tunnelContext->hvDelete = hvDelete;
+ tunnelContext->ovsDelete = ovsDelete;
+ tunnelContext->vport = vport;
- if (STATUS_SUCCESS == status) {
- OvsCleanupVportCommon(switchContext,
- vport,
- hvSwitchPort,
- hvDelete,
- ovsDelete);
+ if (usrParamsCtx) {
+ tunnelContext->inputBuffer = usrParamsCtx->inputBuffer;
+ tunnelContext->outputBuffer = usrParamsCtx->outputBuffer;
+ tunnelContext->outputLength = usrParamsCtx->outputLength;
+ irp = usrParamsCtx->irp;
}
- return status;
+ return OvsCleanupVxlanTunnel(irp, vport, OvsTunnelVportPendingRemove,
+ tunnelContext);
}
+
+
NDIS_STATUS
OvsAddConfiguredSwitchPorts(POVS_SWITCH_CONTEXT switchContext)
{
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
}
}
+
/*
* Remove 'virtualExternalVport' as well. This port is not part of the
* 'portIdHashArray'.
(POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE);
}
+
for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {
PLIST_ENTRY head, link, next;
-
head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
LIST_FORALL_SAFE(head, link, next) {
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->isPresentOnHv == TRUE);
+ vport->isBridgeInternal) || vport->isAbsentOnHv == TRUE);
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
}
}
ASSERT(switchContext->virtualExternalVport == NULL);
ASSERT(switchContext->internalVport == NULL);
- ASSERT(switchContext->vxlanVport == NULL);
}
vportAllocated = TRUE;
if (OvsIsTunnelVportType(portType)) {
- UINT16 udpPortDest = VXLAN_UDP_PORT;
+ UINT16 transportPortDest = 0;
+
+ switch (portType) {
+ case OVS_VPORT_TYPE_VXLAN:
+ transportPortDest = VXLAN_UDP_PORT;
+ break;
+ case OVS_VPORT_TYPE_STT:
+ transportPortDest = STT_TCP_PORT;
+ break;
+ default:
+ break;
+ }
+
PNL_ATTR attr = NlAttrFindNested(vportAttrs[OVS_VPORT_ATTR_OPTIONS],
OVS_TUNNEL_ATTR_DST_PORT);
if (attr) {
- udpPortDest = NlAttrGetU16(attr);
+ transportPortDest = NlAttrGetU16(attr);
}
status = OvsInitTunnelVport(usrParamsCtx,
vport,
portType,
- udpPortDest);
+ transportPortDest);
nlError = NlMapStatusToNlErr(status);
} else {
* Allow the vport to be deleted, because there is no
* corresponding hyper-v switch part.
*/
- vport->isPresentOnHv = TRUE;
+ vport->isAbsentOnHv = TRUE;
} else {
goto Cleanup;
}
if (vport && vportAllocated == TRUE) {
if (vportInitialized == TRUE) {
if (OvsIsTunnelVportType(portType)) {
- OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);
+ switch (vport->ovsType) {
+ case OVS_VPORT_TYPE_VXLAN:
+ OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);
+ break;
+ case OVS_VPORT_TYPE_STT:
+ OvsCleanupSttTunnel(vport);;
+ break;
+ default:
+ ASSERT(!"Invalid tunnel port type");
+ }
}
}
OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
}
static VOID
-OvsTunnelVportPendingUninit(PVOID context,
+OvsTunnelVportPendingRemove(PVOID context,
NTSTATUS status,
UINT32 *replyLen)
{
}
}
- OvsCleanupVportCommon(switchContext,
- vport,
- tunnelContext->hvSwitchPort,
- tunnelContext->hvDelete,
- tunnelContext->ovsDelete);
+ ASSERT(vport->isAbsentOnHv == TRUE);
+ ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);
+
+ /* Remove the port from the relevant lists. */
+ switchContext->numNonHvVports--;
+ RemoveEntryList(&vport->ovsNameLink);
+ RemoveEntryList(&vport->portNoLink);
+ RemoveEntryList(&vport->tunnelVportLink);
+
+ if (vport->priv) {
+ OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG);
+ vport->priv = NULL;
+ }
+
+ OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
}
* Allow the vport to be deleted, because there is no
* corresponding hyper-v switch part.
*/
- vport->isPresentOnHv = TRUE;
+ vport->isAbsentOnHv = TRUE;
if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {
/*