summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Vport.c
diff options
context:
space:
mode:
authorAlin Serdean <aserdean@cloudbasesolutions.com>2014-10-09 17:46:57 +0000
committerBen Pfaff <blp@nicira.com>2014-10-09 15:47:53 -0700
commit429d455615b010cebe9cf1fbcb10b5e20c08c21f (patch)
tree47a17b726d003d7af0ead977c74e4ec4c13d1e16 /datapath-windows/ovsext/Vport.c
parent91c261cd0efc40f7ed70427441141656cf5a3932 (diff)
downloadopenvswitch-429d455615b010cebe9cf1fbcb10b5e20c08c21f.tar.gz
datapath-windows: Make VPORT ovs number values smaller than MAXUINT16
For this, the old method of finding vports based on the ovs port numbers is removed. Now, the lookup of a vport by ovs port number is done the same way as the lookup by hyper-v switch port id. This is done so that the kernel is able to interact with the userspace correctly when using vport channels. The problem manifested in lib/dpif-netlink.c, at the function vport_add_channels. This patch removes the field vportArray from OVS_SWITCH_CONTEXT. In its place, portNoHashArray is set. In the OVS_VPORT_ENTRY struct, we also add portNoLink. This new method will do lookup and insertions of vports by ovs (datapath) port numbers the same way it is done for hyper-v switch port ids. This patch implicitly removes the indexes, which were previously used in insertions and lookups on ovs port numbers. The removal of the index also means that the vxlan vport can no longer be looked up the same way as it was done before: now we hold a pointer to it, vxlanVport in OVS_SWITCH_CONTEXT. For the moment, we can have only one vxlan vport. When more will be allowed, this field will turn into a list of vxlan ports. The invalid port number value (held in OVS_DPPORT_NUMBER_INVALID) is now changed from 0 to MAXUINT16, the same as it is on linux. The function OvsComputeVportNo has also been removed, since the computation of a vport port number can no longer be done like this. When vport add will be added, a new, updated OvsComputeVportNo function will be added. Also, in OvsInitVportCommon, we no longer need to (and no longer can) initialize vport->ovsName, nor vport->ovsNameLen, because they will be initialized by the netlink command vport add. Since the netlink command vport add will generate numbers for the datapath (ovs) port numbers and set the port names, we cannot insert the vport into the hash array of port numbers here, nor into the hash array of port names. Signed-off-by: Samuel Ghinet <sghinet@cloudbasesolutions.com> Co-authored-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com> Acked-by: Ankur Sharma <ankursharma@vmware.com> Acked-by: Eitan Eliahu <eliahue@vmware.com> Acked-by: Nithin Raju <nithin@vmware.com> Tested-by: Nithin Raju <nithin@vmware.com> Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'datapath-windows/ovsext/Vport.c')
-rw-r--r--datapath-windows/ovsext/Vport.c162
1 files changed, 39 insertions, 123 deletions
diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c
index 9ffb25ec0..c26ee0fbe 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -219,7 +219,7 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
add_nic_done:
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
- if (portNo && event) {
+ if (portNo != OVS_DPPORT_NUMBER_INVALID && event) {
OvsPostEvent(portNo, event);
}
@@ -268,6 +268,7 @@ HvConnectNic(POVS_SWITCH_CONTEXT switchContext,
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+ /* XXX only if portNo != INVALID or always? */
OvsPostEvent(portNo, OVS_EVENT_LINK_UP);
if (nicParam->NicType == NdisSwitchNicTypeInternal) {
@@ -392,6 +393,7 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+ /* XXX if portNo != INVALID or always? */
OvsPostEvent(portNo, OVS_EVENT_LINK_DOWN);
if (isInternalPort) {
@@ -440,6 +442,7 @@ HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,
vport->ovsState = OVS_STATE_PORT_CREATED;
NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+ /* XXX if portNo != INVALID or always? */
OvsPostEvent(portNo, OVS_EVENT_DISCONNECT);
done:
@@ -454,14 +457,15 @@ POVS_VPORT_ENTRY
OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
UINT32 portNo)
{
- if (OVS_VPORT_INDEX(portNo) < OVS_MAX_VPORT_ARRAY_SIZE) {
- if (OVS_IS_VPORT_ENTRY_NULL(switchContext, OVS_VPORT_INDEX(portNo))) {
- return NULL;
- } else {
- POVS_VPORT_ENTRY vport;
- vport = (POVS_VPORT_ENTRY)
- switchContext->vportArray[OVS_VPORT_INDEX(portNo)];
- return vport->portNo == portNo ? vport : NULL;
+ POVS_VPORT_ENTRY vport;
+ PLIST_ENTRY head, link;
+ UINT32 hash = OvsJhashBytes((const VOID *)&portNo, sizeof(portNo),
+ OVS_HASH_BASIS);
+ head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
+ LIST_FORALL(head, link) {
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
+ if (vport->portNo == portNo) {
+ return vport;
}
}
return NULL;
@@ -493,18 +497,7 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
NDIS_SWITCH_NIC_INDEX index)
{
if (portId == switchContext->externalPortId) {
- if (index == 0) {
- return (POVS_VPORT_ENTRY)switchContext->externalVport;
- } else if (index > OVS_MAX_PHYS_ADAPTERS) {
- return NULL;
- }
- if (OVS_IS_VPORT_ENTRY_NULL(switchContext,
- index + OVS_EXTERNAL_VPORT_START)) {
- return NULL;
- } else {
- return (POVS_VPORT_ENTRY)switchContext->vportArray[
- index + OVS_EXTERNAL_VPORT_START];
- }
+ return (POVS_VPORT_ENTRY)switchContext->externalVport;
} else if (switchContext->internalPortId == portId) {
return (POVS_VPORT_ENTRY)switchContext->internalVport;
} else {
@@ -523,72 +516,6 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
}
}
-UINT32
-OvsComputeVportNo(POVS_SWITCH_CONTEXT switchContext,
- UINT32 nicIndex,
- OVS_VPORT_TYPE ovsType,
- BOOLEAN isExternal)
-{
- UINT32 index = 0xffffff, i = 0;
- UINT64 gen;
-
- if (isExternal) {
- if (nicIndex == 0) {
- return 0; // not a valid portNo
- } else if (nicIndex > OVS_MAX_PHYS_ADAPTERS) {
- return 0;
- } else {
- index = nicIndex + OVS_EXTERNAL_VPORT_START;
- }
- }
-
- switch (ovsType) {
- case OVS_VPORT_TYPE_INTERNAL:
- index = OVS_INTERNAL_VPORT_DEFAULT_INDEX;
- break;
- case OVS_VPORT_TYPE_NETDEV:
- index = switchContext->lastPortIndex + 1;
- if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
- index = OVS_VM_VPORT_START;
- }
- while (!OVS_IS_VPORT_ENTRY_NULL(switchContext, index) &&
- i < (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
- index++;
- i++;
- if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
- index = OVS_VM_VPORT_START;
- }
- }
- if (i == (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
- return 0; // not available
- }
- switchContext->lastPortIndex = index;
- break;
- case OVS_VPORT_TYPE_GRE:
- index = OVS_GRE_VPORT_INDEX;
- break;
- case OVS_VPORT_TYPE_GRE64:
- index = OVS_GRE64_VPORT_INDEX;
- break;
- case OVS_VPORT_TYPE_VXLAN:
- index = OVS_VXLAN_VPORT_INDEX;
- break;
- default:
- ASSERT(isExternal);
- }
- if (index > OVS_MAX_VPORT_ARRAY_SIZE) {
- return 0;
- }
- gen = (UINT64)switchContext->vportArray[index];
- if (gen > 0xff) {
- return 0;
- } else if (gen == 0) {
- gen++;
- }
- return OVS_VPORT_PORT_NO(index, (UINT32)gen);
-}
-
-
static POVS_VPORT_ENTRY
OvsAllocateVport(VOID)
{
@@ -599,6 +526,12 @@ OvsAllocateVport(VOID)
}
RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY));
vport->ovsState = OVS_STATE_UNKNOWN;
+ vport->portNo = OVS_DPPORT_NUMBER_INVALID;
+
+ InitializeListHead(&vport->ovsNameLink);
+ InitializeListHead(&vport->portIdLink);
+ InitializeListHead(&vport->portNoLink);
+
return vport;
}
@@ -707,22 +640,11 @@ OvsInitPhysNicVport(POVS_VPORT_ENTRY vport,
}
static NDIS_STATUS
OvsInitVportCommon(POVS_SWITCH_CONTEXT switchContext,
-POVS_VPORT_ENTRY vport)
+ POVS_VPORT_ENTRY vport)
{
UINT32 hash;
- size_t len;
- if (vport->portType != NdisSwitchPortTypeExternal ||
- vport->nicIndex != 0) {
- vport->portNo = OvsComputeVportNo(switchContext, vport->nicIndex,
- vport->ovsType, vport->portType == NdisSwitchPortTypeExternal);
- if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {
- return NDIS_STATUS_RESOURCES;
- }
- ASSERT(OVS_IS_VPORT_ENTRY_NULL(switchContext,
- OVS_VPORT_INDEX(vport->portNo)));
+ ASSERT(vport->portNo == OVS_DPPORT_NUMBER_INVALID);
- switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] = vport;
- }
switch (vport->portType) {
case NdisSwitchPortTypeExternal:
if (vport->nicIndex == 0) {
@@ -730,8 +652,7 @@ POVS_VPORT_ENTRY vport)
switchContext->externalVport = vport;
RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
"external.virtualAdapter");
- }
- else {
+ } else {
switchContext->numPhysicalNics++;
RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
"external.%lu", (UINT32)vport->nicIndex);
@@ -740,27 +661,23 @@ POVS_VPORT_ENTRY vport)
case NdisSwitchPortTypeInternal:
switchContext->internalPortId = vport->portId;
switchContext->internalVport = vport;
- RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
- "internal");
break;
case NdisSwitchPortTypeSynthetic:
- RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
- "vmNICSyn.%lx", vport->portNo);
break;
case NdisSwitchPortTypeEmulated:
- RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
- "vmNICEmu.%lx", vport->portNo);
break;
}
- StringCbLengthA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
- vport->ovsNameLen = (UINT32)len;
+
if (vport->portType == NdisSwitchPortTypeExternal &&
vport->nicIndex == 0) {
return NDIS_STATUS_SUCCESS;
}
- hash = OvsJhashBytes(vport->ovsName, vport->ovsNameLen, OVS_HASH_BASIS);
- InsertHeadList(&switchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK],
- &vport->ovsNameLink);
+
+ /*
+ * NOTE: OvsJhashWords has portId as "1" word. This should be ok, even
+ * though sizeof(NDIS_SWITCH_PORT_ID) = 4, not 2, because the
+ * hyper-v switch seems to use only 2 bytes out of 4.
+ */
hash = OvsJhashWords(&vport->portId, 1, OVS_HASH_BASIS);
InsertHeadList(&switchContext->portIdHashArray[hash & OVS_VPORT_MASK],
&vport->portIdLink);
@@ -773,8 +690,6 @@ static VOID
OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
POVS_VPORT_ENTRY vport)
{
- UINT64 gen = vport->portNo >> 24;
-
if (vport->isExternal) {
if (vport->nicIndex == 0) {
ASSERT(switchContext->numPhysicalNics == 0);
@@ -807,9 +722,7 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
RemoveEntryList(&vport->ovsNameLink);
RemoveEntryList(&vport->portIdLink);
- gen = (gen + 1) & 0xff;
- switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] =
- (PVOID)(UINT64)gen;
+ RemoveEntryList(&vport->portNoLink);
switchContext->numVports--;
OvsFreeMemory(vport);
}
@@ -933,14 +846,17 @@ cleanup:
VOID
OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
{
- UINT32 i;
+ for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash) {
+ PLIST_ENTRY head, link;
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
- if (!OVS_IS_VPORT_ENTRY_NULL(switchContext, i)) {
- OvsRemoveAndDeleteVport(switchContext,
- (POVS_VPORT_ENTRY)switchContext->vportArray[i]);
+ head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
+ LIST_FORALL(head, link) {
+ POVS_VPORT_ENTRY vport;
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
+ OvsRemoveAndDeleteVport(switchContext, vport);
}
}
+
if (switchContext->externalVport) {
OvsRemoveAndDeleteVport(switchContext,
(POVS_VPORT_ENTRY)switchContext->externalVport);