NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
NDIS_RWL_AT_DISPATCH_LEVEL);
- if (gOvsSwitchContext->numHvVports > 0) {
+ if (gOvsSwitchContext->numHvVports > 0 ||
+ gOvsSwitchContext->numNonHvVports > 0) {
/* inBucket: the bucket, used for lookup */
UINT32 inBucket = instance->dumpState.index[0];
/* inIndex: index within the given bucket, used for lookup */
for (i = inBucket; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
PLIST_ENTRY head, link;
- head = &(gOvsSwitchContext->portIdHashArray[i]);
+ head = &(gOvsSwitchContext->portNoHashArray[i]);
POVS_VPORT_ENTRY vport = NULL;
outIndex = 0;
* inIndex + 1 vport from the bucket.
*/
if (outIndex >= inIndex) {
- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);
-
- if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) {
- OvsCreateMsgFromVport(vport, msgIn,
- usrParamsCtx->outputBuffer,
- usrParamsCtx->outputLength,
- gOvsSwitchContext->dpNo);
- ++outIndex;
- break;
- } else {
- vport = NULL;
- }
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
+
+ ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);
+ OvsCreateMsgFromVport(vport, msgIn,
+ usrParamsCtx->outputBuffer,
+ usrParamsCtx->outputLength,
+ gOvsSwitchContext->dpNo);
+ ++outIndex;
+ break;
}
++outIndex;
PCHAR portName;
ULONG portNameLen;
UINT32 portType;
- UINT32 hash;
+ BOOLEAN isBridgeInternal = FALSE;
+ BOOLEAN vportAllocated = FALSE;
+ BOOLEAN addInternalPortAsNetdev = FALSE;
static const NL_POLICY ovsVportPolicy[] = {
[OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },
goto Cleanup;
}
- if (portType == OVS_VPORT_TYPE_INTERNAL) {
+ if (portName && portType == OVS_VPORT_TYPE_NETDEV &&
+ !strcmp(OVS_DPPORT_INTERNAL_NAME_A, portName)) {
+ addInternalPortAsNetdev = TRUE;
+ }
+
+ if (portName && portType == OVS_VPORT_TYPE_INTERNAL &&
+ strcmp(OVS_DPPORT_INTERNAL_NAME_A, portName)) {
+ isBridgeInternal = TRUE;
+ }
+
+ if (portType == OVS_VPORT_TYPE_INTERNAL && !isBridgeInternal) {
vport = gOvsSwitchContext->internalVport;
} else if (portType == OVS_VPORT_TYPE_NETDEV) {
- if (!strcmp(portName, "external")) {
- vport = gOvsSwitchContext->virtualExternalVport;
- } else {
- vport = OvsFindVportByHvName(gOvsSwitchContext, portName);
- }
+ /* External ports can also be looked up like VIF ports. */
+ vport = OvsFindVportByHvName(gOvsSwitchContext, portName);
} else {
- /* XXX: change when other tunneling ports are added */
- ASSERT(portType == OVS_VPORT_TYPE_VXLAN);
-
- if (gOvsSwitchContext->vxlanVport) {
- nlError = NL_ERROR_EXIST;
- goto Cleanup;
- }
+ ASSERT(OvsIsTunnelVportType(portType) ||
+ (portType == OVS_VPORT_TYPE_INTERNAL && isBridgeInternal));
+ ASSERT(OvsGetTunnelVport(gOvsSwitchContext, portType) == NULL ||
+ !OvsIsTunnelVportType(portType));
vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
if (vport == NULL) {
nlError = NL_ERROR_NOMEM;
goto Cleanup;
}
+ vportAllocated = TRUE;
- vport->ovsState = OVS_STATE_PORT_CREATED;
+ if (OvsIsTunnelVportType(portType)) {
+ nlError = OvsInitTunnelVport(vport, portType, VXLAN_UDP_PORT);
+ } else {
+ OvsInitBridgeInternalVport(vport);
+ }
- /*
- * XXX: when we allow configuring the vxlan udp port, we should read
- * this from vport->options instead!
- */
- nlError = OvsInitVxlanTunnel(vport, VXLAN_UDP_PORT);
- if (nlError != NL_ERROR_SUCCESS) {
- goto Cleanup;
+ if (nlError == NL_ERROR_SUCCESS) {
+ vport->ovsState = OVS_STATE_CONNECTED;
+ vport->nicState = NdisSwitchNicStateConnected;
+
+ /*
+ * Allow the vport to be deleted, because there is no
+ * corresponding hyper-v switch part.
+ */
+ vport->hvDeleted = TRUE;
}
}
nlError = NL_ERROR_INVAL;
goto Cleanup;
}
-
if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) {
nlError = NL_ERROR_EXIST;
goto Cleanup;
}
- /* Fill the data in vport */
- vport->ovsType = portType;
-
+ /* Initialize the vport with OVS specific properties. */
+ if (addInternalPortAsNetdev != TRUE) {
+ vport->ovsType = portType;
+ }
if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {
/*
- * XXX: when we implement the limit for ovs port number to be
- * MAXUINT16, we'll need to check the port number received from the
- * userspace.
- */
+ * XXX: when we implement the limit for ovs port number to be
+ * MAXUINT16, we'll need to check the port number received from the
+ * userspace.
+ */
vport->portNo = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]);
} else {
vport->portNo = OvsComputeVportNo(gOvsSwitchContext);
ASSERT(portNameLen <= OVS_MAX_PORT_NAME_LENGTH);
RtlCopyMemory(vport->ovsName, portName, portNameLen);
-
/* if we don't have options, then vport->portOptions will be NULL */
vport->portOptions = vportAttrs[OVS_VPORT_ATTR_OPTIONS];
/*
- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,
- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,
- * it means we have an array of pids, instead of a single pid.
- * ATM we assume we have one pid only.
- */
+ * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,
+ * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,
+ * it means we have an array of pids, instead of a single pid.
+ * ATM we assume we have one pid only.
+ */
vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]);
- if (vport->ovsType == OVS_VPORT_TYPE_VXLAN) {
- gOvsSwitchContext->vxlanVport = vport;
- } else if (vport->ovsType == OVS_VPORT_TYPE_INTERNAL) {
- gOvsSwitchContext->internalVport = vport;
- gOvsSwitchContext->internalPortId = vport->portId;
- } else if (vport->ovsType == OVS_VPORT_TYPE_NETDEV &&
- vport->isExternal) {
- gOvsSwitchContext->virtualExternalVport = vport;
- gOvsSwitchContext->virtualExternalPortId = vport->portId;
- }
-
- /*
- * insert the port into the hash array of ports: by port number and ovs
- * and ovs (datapath) port name.
- * NOTE: OvsJhashWords has portNo as "1" word. This is ok, because the
- * portNo is stored in 2 bytes only (max port number = MAXUINT16).
- */
- hash = OvsJhashWords(&vport->portNo, 1, OVS_HASH_BASIS);
- InsertHeadList(&gOvsSwitchContext->portNoHashArray[hash & OVS_VPORT_MASK],
- &vport->portNoLink);
-
- hash = OvsJhashBytes(vport->ovsName, portNameLen, OVS_HASH_BASIS);
- InsertHeadList(&gOvsSwitchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK],
- &vport->ovsNameLink);
+ status = InitOvsVportCommon(gOvsSwitchContext, vport);
+ ASSERT(status == STATUS_SUCCESS);
status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer,
usrParamsCtx->outputLength,
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- if (vport && vport->ovsType == OVS_VPORT_TYPE_VXLAN) {
+ if (vport && vportAllocated == TRUE) {
OvsRemoveAndDeleteVport(gOvsSwitchContext, vport);
}