*/
#include "precomp.h"
+
+#include "Datapath.h"
+#include "Event.h"
+#include "Gre.h"
+#include "IpHelper.h"
#include "Jhash.h"
+#include "Oid.h"
+#include "Stt.h"
#include "Switch.h"
-#include "Vport.h"
-#include "Event.h"
#include "User.h"
+#include "Vport.h"
#include "Vxlan.h"
-#include "Stt.h"
-#include "IpHelper.h"
-#include "Oid.h"
-#include "Datapath.h"
+#include "Geneve.h"
#ifdef OVS_DBG_MOD
#undef OVS_DBG_MOD
* delete will delete the vport.
*/
if (vport) {
+ OVS_EVENT_ENTRY event;
+
+ event.portNo = vport->portNo;
+ event.ovsType = vport->ovsType;
+ event.upcallPid = vport->upcallPid;
+ RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);
+ event.type = OVS_EVENT_LINK_DOWN;
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);
+ OvsPostEvent(&event);
} else {
OVS_LOG_WARN("Vport not present.");
}
goto done;
}
- if (nicParam->NicType == NdisSwitchNicTypeInternal ||
- (nicParam->NicType == NdisSwitchNicTypeExternal &&
- nicParam->NicIndex != 0)) {
+ if (OvsIsInternalNIC(nicParam->NicType) ||
+ OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
}
* structure for each such NIC, and each NIC inherits a lot of properties
* from the parent external port.
*/
- if (nicParam->NicType == NdisSwitchNicTypeExternal &&
- nicParam->NicIndex != 0) {
+ if (OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
+ NDIS_SWITCH_PORT_PARAMETERS portParam;
POVS_VPORT_ENTRY virtExtVport =
(POVS_VPORT_ENTRY)switchContext->virtualExternalVport;
- vport = OvsFindVportByPortIdAndNicIndex(switchContext,
- nicParam->PortId,
- nicParam->NicIndex);
- if (vport == NULL) {
- NDIS_SWITCH_PORT_PARAMETERS portParam;
- /* Find by interface name */
- WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
- NET_LUID interfaceLuid = { 0 };
- size_t len = 0;
- status = ConvertInterfaceGuidToLuid(&nicParam->NetCfgInstanceId,
- &interfaceLuid);
- if (status == STATUS_SUCCESS) {
- status = ConvertInterfaceLuidToAlias(&interfaceLuid,
- interfaceName,
- IF_MAX_STRING_SIZE + 1);
- if (status == STATUS_SUCCESS) {
- RtlStringCbLengthW(interfaceName,
- IF_MAX_STRING_SIZE,
- &len);
- vport = OvsFindVportByHvNameW(switchContext,
- interfaceName,
- len);
- }
- }
-
- 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;
- }
+ ASSERT(virtExtVport);
+ ASSERT(OvsFindVportByPortIdAndNicIndex(switchContext,
+ nicParam->PortId,
+ nicParam->NicIndex) == NULL);
+ 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;
}
}
goto add_nic_done;
}
OvsInitVportWithNicParam(switchContext, vport, nicParam);
- if (nicParam->NicType == NdisSwitchNicTypeInternal ||
- (nicParam->NicType == NdisSwitchNicTypeExternal &&
- nicParam->NicIndex != 0)) {
+ if (OvsIsInternalNIC(nicParam->NicType) ||
+ OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,
sizeof portFriendlyName);
}
{
LOCK_STATE_EX lockState;
POVS_VPORT_ENTRY vport;
- UINT32 portNo;
VPORT_NIC_ENTER(nicParam);
vport->ovsState = OVS_STATE_CONNECTED;
vport->nicState = NdisSwitchNicStateConnected;
- portNo = vport->portNo;
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
LOCK_STATE_EX lockState;
UINT32 event = 0;
IF_COUNTED_STRING portFriendlyName = {0};
+ BOOLEAN nameChanged = FALSE;
+ BOOLEAN aliasLookup = FALSE;
VPORT_NIC_ENTER(nicParam);
/* GetNICAlias() must be called outside of a lock. */
if (nicParam->NicType == NdisSwitchNicTypeInternal ||
- (nicParam->NicType == NdisSwitchNicTypeExternal &&
- nicParam->NicIndex != 0)) {
+ OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
+ aliasLookup = TRUE;
}
NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
case NdisSwitchNicTypeInternal:
RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,
sizeof (GUID));
- RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,
- sizeof portFriendlyName);
+ if (aliasLookup) {
+ if (RtlCompareMemory(&vport->portFriendlyName,
+ &portFriendlyName, vport->portFriendlyName.Length) !=
+ vport->portFriendlyName.Length) {
+ RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,
+ sizeof portFriendlyName);
+ nameChanged = TRUE;
+ }
+ }
break;
case NdisSwitchNicTypeSynthetic:
case NdisSwitchNicTypeEmulated:
}
vport->numaNodeId = nicParam->NumaNodeId;
+ if (nameChanged) {
+ OVS_EVENT_ENTRY evt;
+ evt.portNo = vport->portNo;
+ evt.ovsType = vport->ovsType;
+ evt.upcallPid = vport->upcallPid;
+ RtlCopyMemory(&evt.ovsName, &vport->ovsName, sizeof evt.ovsName);
+ evt.type = OVS_EVENT_LINK_DOWN;
+ OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
+ OvsPostEvent(&evt);
+ }
+
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
/*
RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);
event.type = OVS_EVENT_LINK_DOWN;
- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-
/*
* Delete the port from the hash tables accessible to userspace. After this
* point, userspace should not be able to access this port.
*/
- OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
- OvsPostEvent(&event);
+ if (OvsIsRealExternalVport(vport)) {
+ OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
+ OvsPostEvent(&event);
+ }
+ NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
if (isInternalPort) {
OvsInternalAdapterDown();
vport->nicState = NdisSwitchNicStateUnknown;
vport->ovsState = OVS_STATE_PORT_CREATED;
- if (vport->portType == NdisSwitchPortTypeExternal &&
- vport->nicIndex != 0) {
+ if (OvsIsRealExternalVport(vport)) {
+ /* This vport was created in HvCreateNic(). */
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);
}
POVS_VPORT_ENTRY
-OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
- UINT16 dstPort,
- OVS_VPORT_TYPE ovsPortType)
+OvsFindTunnelVportByDstPortAndType(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort,
+ OVS_VPORT_TYPE ovsPortType)
{
POVS_VPORT_ENTRY vport;
PLIST_ENTRY head, link;
return NULL;
}
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByDstPortAndNWProto(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort,
+ UINT8 nwProto)
+{
+ 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) {
+ switch (nwProto) {
+ case IPPROTO_UDP:
+ if (vport->ovsType != OVS_VPORT_TYPE_GENEVE &&
+ vport->ovsType != OVS_VPORT_TYPE_VXLAN) {
+ continue;
+ }
+ break;
+ case IPPROTO_TCP:
+ if (vport->ovsType != OVS_VPORT_TYPE_STT) {
+ continue;
+ }
+ break;
+ case IPPROTO_GRE:
+ break;
+ default:
+ continue;
+ }
+ return vport;
+ }
+ }
+ return NULL;
+}
+
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext,
+ OVS_VPORT_TYPE ovsPortType)
+{
+ POVS_VPORT_ENTRY vport;
+ PLIST_ENTRY head, link;
+ UINT16 dstPort = 0;
+ 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 (vport->ovsType == ovsPortType) {
+ return vport;
+ }
+ }
+ return NULL;
+}
POVS_VPORT_ENTRY
OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
UNREFERENCED_PARAMETER(switchContext);
RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
- sizeof (nicParam->PermanentMacAddress));
+ sizeof (vport->permMacAddress));
RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
- sizeof (nicParam->CurrentMacAddress));
+ sizeof (vport->currMacAddress));
if (nicParam->NicType == NdisSwitchNicTypeSynthetic ||
nicParam->NicType == NdisSwitchNicTypeEmulated) {
RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,
- sizeof (nicParam->VMMacAddress));
+ sizeof (vport->vmMacAddress));
RtlCopyMemory(&vport->vmName, &nicParam->VmName,
sizeof (nicParam->VmName));
} else {
vport->mtu = nicParam->MTU;
vport->nicState = nicParam->NicState;
vport->nicIndex = nicParam->NicIndex;
+ vport->nicType = nicParam->NicType;
vport->numaNodeId = nicParam->NumaNodeId;
switch (vport->nicState) {
vport->ovsState = OVS_STATE_PORT_CREATED;
switch (ovsType) {
case OVS_VPORT_TYPE_GRE:
+ status = OvsInitGreTunnel(vport);
break;
case OVS_VPORT_TYPE_VXLAN:
{
case OVS_VPORT_TYPE_STT:
status = OvsInitSttTunnel(vport, dstPort);
break;
+ case OVS_VPORT_TYPE_GENEVE:
+ status = OvsInitGeneveTunnel(vport, dstPort);
+ break;
default:
ASSERT(0);
}
GetNICAlias(GUID *netCfgInstanceId,
IF_COUNTED_STRING *portFriendlyName)
{
- NTSTATUS status = STATUS_SUCCESS;
- WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
- NET_LUID interfaceLuid = { 0 };
- size_t len = 0;
+ NTSTATUS status;
+ WCHAR interfaceName[IF_MAX_STRING_SIZE + 1];
+ NET_LUID interfaceLuid;
+ size_t len;
status = ConvertInterfaceGuidToLuid(netCfgInstanceId,
&interfaceLuid);
UINT32 hash;
switch(vport->ovsType) {
+ case OVS_VPORT_TYPE_GRE:
case OVS_VPORT_TYPE_VXLAN:
case OVS_VPORT_TYPE_STT:
+ case OVS_VPORT_TYPE_GENEVE:
{
UINT16 dstPort = GetPortFromPriv(vport);
hash = OvsJhashBytes(&dstPort,
return status;
}
}
+ case OVS_VPORT_TYPE_GENEVE:
+ OvsCleanupGeneveTunnel(vport);
+ break;
case OVS_VPORT_TYPE_STT:
OvsCleanupSttTunnel(vport);
break;
case OVS_VPORT_TYPE_GRE:
+ OvsCleanupGreTunnel(vport);
break;
case OVS_VPORT_TYPE_NETDEV:
if (vport->isExternal) {
InitializeListHead(&vport->ovsNameLink);
RemoveEntryList(&vport->portNoLink);
InitializeListHead(&vport->portNoLink);
- if (OVS_VPORT_TYPE_VXLAN == vport->ovsType ||
- OVS_VPORT_TYPE_STT == vport->ovsType) {
+ if (OvsIsTunnelVportType(vport->ovsType)) {
RemoveEntryList(&vport->tunnelVportLink);
InitializeListHead(&vport->tunnelVportLink);
}
OVS_MAX_PORT_NAME_LENGTH);
if (status != STATUS_SUCCESS) {
OVS_LOG_INFO("Fail to convert NIC name.");
- extInfo->vmUUID[0] = 0;
+ extInfo->name[0] = 0;
}
status = OvsConvertIfCountedStrToAnsiStr(&vport->vmName,
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
return STATUS_SUCCESS;
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
return STATUS_SUCCESS;
if (OvsIsTunnelVportType(portType)) {
UINT16 transportPortDest = 0;
+ UINT8 nwProto = IPPROTO_NONE;
+ POVS_VPORT_ENTRY dupVport;
switch (portType) {
+ case OVS_VPORT_TYPE_GRE:
+ nwProto = IPPROTO_GRE;
+ break;
case OVS_VPORT_TYPE_VXLAN:
transportPortDest = VXLAN_UDP_PORT;
+ nwProto = IPPROTO_UDP;
+ break;
+ case OVS_VPORT_TYPE_GENEVE:
+ transportPortDest = GENEVE_UDP_PORT;
break;
case OVS_VPORT_TYPE_STT:
transportPortDest = STT_TCP_PORT;
+ nwProto = IPPROTO_TCP;
break;
default:
nlError = NL_ERROR_INVAL;
}
}
+ /*
+ * We don't allow two tunnel ports on identical N/W protocol and
+ * L4 port number. This is applicable even if the two ports are of
+ * different tunneling types.
+ */
+ dupVport =
+ OvsFindTunnelVportByDstPortAndNWProto(gOvsSwitchContext,
+ transportPortDest,
+ nwProto);
+ if (dupVport) {
+ OVS_LOG_ERROR("Vport for N/W proto and port already exists,"
+ " type: %u, dst port: %u, name: %s", dupVport->ovsType,
+ transportPortDest, dupVport->ovsName);
+ goto Cleanup;
+ }
+
status = OvsInitTunnelVport(usrParamsCtx,
vport,
portType,
gOvsSwitchContext->dpNo);
*replyLen = msgOut->nlMsg.nlmsgLen;
+ OVS_LOG_INFO("Created new vport, name: %s, type: %u", vport->ovsName,
+ vport->ovsType);
Cleanup:
NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
case OVS_VPORT_TYPE_STT:
OvsCleanupSttTunnel(vport);
break;
+ case OVS_VPORT_TYPE_GENEVE:
+ OvsCleanupGeneveTunnel(vport);
+ break;
default:
ASSERT(!"Invalid tunnel port type");
}
OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
}
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
return STATUS_SUCCESS;
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;
*replyLen = msgOut->nlMsg.nlmsgLen;
} else {
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;
-
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
}
} while (error);
if (error) {
- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) msgOut;
+ POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;
OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);
OvsFreeMemory(vport);
- NlBuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ ASSERT(msgError);
+ NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+ ASSERT(*replyLen != 0);
}
}