summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext
diff options
context:
space:
mode:
authorSorin Vinturis <svinturis@cloudbasesolutions.com>2015-05-27 16:58:25 +0000
committerBen Pfaff <blp@nicira.com>2015-05-27 12:36:42 -0700
commitffde5f8f292055c36d41651967ca057d30ded877 (patch)
treebacc52850ed95a165f030d4b392d62efd9b6bcd1 /datapath-windows/ovsext
parent5e82ceefd12dfcb954da48d027b47d98dc53676a (diff)
downloadopenvswitch-ffde5f8f292055c36d41651967ca057d30ded877.tar.gz
datapath-windows: Support for multiple VXLAN tunnels
At the moment the OVS extension supports only one VXLAN tunnel that is cached in the extension switch context. Replaced the latter cached pointer with an array list that contains all VXLAN tunnel vports. Signed-off-by: Sorin Vinturis <svinturis@cloudbasesolutions.com> Reported-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com> Reported-at: https://github.com/openvswitch/ovs-issues/issues/64 Acked-by: Eitan Eliahu <eliahue@vmware.com> Acked-by: Nithin Raju <nithin@vmware.com> Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'datapath-windows/ovsext')
-rw-r--r--datapath-windows/ovsext/Actions.c13
-rw-r--r--datapath-windows/ovsext/Switch.c16
-rw-r--r--datapath-windows/ovsext/Switch.h6
-rw-r--r--datapath-windows/ovsext/Tunnel.c3
-rw-r--r--datapath-windows/ovsext/Vport.c44
-rw-r--r--datapath-windows/ovsext/Vport.h21
-rw-r--r--datapath-windows/ovsext/Vxlan.c2
-rw-r--r--datapath-windows/ovsext/Vxlan.h2
8 files changed, 70 insertions, 37 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index a93fe0331..79e464c80 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -184,6 +184,9 @@ OvsInitForwardingCtx(OvsForwardingContext *ovsFwdCtx,
}
/*
+ * XXX: When we search for the tunnelVport we also need to specify the
+ * tunnelling protocol or the L4 protocol as key as well, because there are
+ * different protocols that can use the same destination port.
* --------------------------------------------------------------------------
* OvsDetectTunnelRxPkt --
* Utility function for an RX packet to detect its tunnel type.
@@ -203,16 +206,17 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx,
* packets only if they are at least VXLAN header size.
*/
if (!flowKey->ipKey.nwFrag &&
- flowKey->ipKey.nwProto == IPPROTO_UDP &&
- flowKey->ipKey.l4.tpDst == VXLAN_UDP_PORT_NBO) {
- tunnelVport = ovsFwdCtx->switchContext->vxlanVport;
- ovsActionStats.rxVxlan++;
+ flowKey->ipKey.nwProto == IPPROTO_UDP) {
+ UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst);
+ tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext,
+ dstPort);
}
// We might get tunnel packets even before the tunnel gets initialized.
if (tunnelVport) {
ASSERT(ovsFwdCtx->tunnelRxNic == NULL);
ovsFwdCtx->tunnelRxNic = tunnelVport;
+ ovsActionStats.rxVxlan++;
return TRUE;
}
@@ -1318,6 +1322,7 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx,
status = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey);
ASSERT(status == NDIS_STATUS_SUCCESS);
tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key));
+ tunKey.dst_port = key->ipKey.l4.tpDst;
RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey);
break;
diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c
index 416bcc03f..f8778546c 100644
--- a/datapath-windows/ovsext/Switch.c
+++ b/datapath-windows/ovsext/Switch.c
@@ -367,6 +367,8 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->tunnelVportsArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);
if (status == NDIS_STATUS_SUCCESS) {
@@ -377,7 +379,8 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
switchContext->portNoHashArray == NULL ||
switchContext->ovsPortNameHashArray == NULL ||
switchContext->portIdHashArray== NULL ||
- switchContext->pidHashArray == NULL) {
+ switchContext->pidHashArray == NULL ||
+ switchContext->tunnelVportsArray == NULL) {
if (switchContext->dispatchLock) {
NdisFreeRWLock(switchContext->dispatchLock);
}
@@ -398,6 +401,10 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
OVS_SWITCH_POOL_TAG);
}
+ if (switchContext->tunnelVportsArray) {
+ OvsFreeMemory(switchContext->tunnelVportsArray);
+ }
+
OvsDeleteFlowTable(&switchContext->datapath);
OvsCleanupBufferPool(switchContext);
@@ -407,12 +414,9 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->ovsPortNameHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portIdHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portNoHashArray[i]);
+ InitializeListHead(&switchContext->tunnelVportsArray[i]);
}
for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
@@ -465,6 +469,8 @@ OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)
OvsFreeMemoryWithTag(switchContext->pidHashArray,
OVS_SWITCH_POOL_TAG);
switchContext->pidHashArray = NULL;
+ OvsFreeMemory(switchContext->tunnelVportsArray);
+ switchContext->tunnelVportsArray = NULL;
OvsDeleteFlowTable(&switchContext->datapath);
OvsCleanupBufferPool(switchContext);
diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h
index 6ec34e1f4..8e1eb5f2c 100644
--- a/datapath-windows/ovsext/Switch.h
+++ b/datapath-windows/ovsext/Switch.h
@@ -132,8 +132,6 @@ typedef struct _OVS_SWITCH_CONTEXT
POVS_VPORT_ENTRY virtualExternalVport; // the virtual adapter vport
POVS_VPORT_ENTRY internalVport;
- POVS_VPORT_ENTRY vxlanVport;
-
/*
* 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,
* namely: VIF (vNIC) ports, external port and Hyper-V internal port.
@@ -148,11 +146,15 @@ typedef struct _OVS_SWITCH_CONTEXT
* exist on the Hyper-V switch, and 'numNonHvVports' counts such ports in
* 'portNoHashArray'.
*
+ * 'tunnelVportsArray' contains tunnel ports that are added from OVS
+ * userspace. Currently only VXLAN tunnels are added in this list.
+ *
* 'ovsPortNameHashArray' contains the same entries as 'portNoHashArray' but
* hashed on a different key.
*/
PLIST_ENTRY portIdHashArray; // based on Hyper-V portId
PLIST_ENTRY portNoHashArray; // based on ovs port number
+ PLIST_ENTRY tunnelVportsArray; // based on ovs dst port number
PLIST_ENTRY ovsPortNameHashArray; // based on ovsName
PLIST_ENTRY pidHashArray; // based on packet pids
NDIS_SPIN_LOCK pidHashLock; // Lock for pidHash table
diff --git a/datapath-windows/ovsext/Tunnel.c b/datapath-windows/ovsext/Tunnel.c
index fed58f1c3..002f18024 100644
--- a/datapath-windows/ovsext/Tunnel.c
+++ b/datapath-windows/ovsext/Tunnel.c
@@ -285,7 +285,8 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl,
SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL;
- vport = gOvsSwitchContext->vxlanVport;
+ vport = OvsFindTunnelVportByDstPort(gOvsSwitchContext,
+ htons(tunnelKey.dst_port));
if (vport == NULL){
status = STATUS_UNSUCCESSFUL;
diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c
index 66f918906..5a1b64f18 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -601,6 +601,25 @@ OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
POVS_VPORT_ENTRY
+OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort)
+{
+ 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 (((POVS_VXLAN_VPORT)vport->priv)->dstPort == dstPort) {
+ return vport;
+ }
+ }
+ return NULL;
+}
+
+
+POVS_VPORT_ENTRY
OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name)
{
@@ -1048,8 +1067,8 @@ InitHvVportCommon(POVS_SWITCH_CONTEXT switchContext,
* --------------------------------------------------------------------------
* 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
@@ -1060,9 +1079,17 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
switch(vport->ovsType) {
case OVS_VPORT_TYPE_VXLAN:
- switchContext->vxlanVport = vport;
+ {
+ POVS_VXLAN_VPORT vxlanVport = (POVS_VXLAN_VPORT)vport->priv;
+ hash = OvsJhashBytes(&vxlanVport->dstPort,
+ sizeof(vxlanVport->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++;
@@ -1131,6 +1158,11 @@ OvsCleanupVportCommon(POVS_SWITCH_CONTEXT switchContext,
InitializeListHead(&vport->ovsNameLink);
RemoveEntryList(&vport->portNoLink);
InitializeListHead(&vport->portNoLink);
+ if (OVS_VPORT_TYPE_VXLAN == vport->ovsType) {
+ RemoveEntryList(&vport->tunnelVportLink);
+ InitializeListHead(&vport->tunnelVportLink);
+ }
+
deletedOnOvs = TRUE;
}
@@ -1224,8 +1256,6 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext,
vport,
OvsTunnelVportPendingUninit,
tunnelContext);
-
- switchContext->vxlanVport = NULL;
break;
}
case OVS_VPORT_TYPE_GRE:
@@ -1386,6 +1416,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
}
}
+
/*
* Remove 'virtualExternalVport' as well. This port is not part of the
* 'portIdHashArray'.
@@ -1395,9 +1426,9 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
(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;
@@ -1411,7 +1442,6 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
ASSERT(switchContext->virtualExternalVport == NULL);
ASSERT(switchContext->internalVport == NULL);
- ASSERT(switchContext->vxlanVport == NULL);
}
diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h
index 593805315..84ac3d3fa 100644
--- a/datapath-windows/ovsext/Vport.h
+++ b/datapath-windows/ovsext/Vport.h
@@ -84,6 +84,7 @@ 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;
@@ -135,10 +136,8 @@ typedef struct _OVS_VPORT_ENTRY {
struct _OVS_SWITCH_CONTEXT;
-POVS_VPORT_ENTRY
-OvsFindVportByPortNo(struct _OVS_SWITCH_CONTEXT *switchContext,
- UINT32 portNo);
-
+POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
+ UINT32 portNo);
/* "name" is null-terminated */
POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name);
@@ -147,6 +146,8 @@ POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,
POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
NDIS_SWITCH_PORT_ID portId,
NDIS_SWITCH_NIC_INDEX index);
+POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort);
NDIS_STATUS OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT *switchContext);
NDIS_STATUS OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT *switchContext);
@@ -180,18 +181,6 @@ OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType)
ovsType == OVS_VPORT_TYPE_GRE64;
}
-static __inline POVS_VPORT_ENTRY
-OvsGetTunnelVport(POVS_SWITCH_CONTEXT switchContext,
- OVS_VPORT_TYPE ovsType)
-{
- switch(ovsType) {
- case OVS_VPORT_TYPE_VXLAN:
- return switchContext->vxlanVport;
- default:
- return NULL;
- }
-}
-
static __inline BOOLEAN
OvsIsInternalVportType(OVS_VPORT_TYPE ovsType)
{
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index 9d4266544..9935bdff0 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -274,7 +274,7 @@ OvsDoEncapVxlan(PNET_BUFFER_LIST curNbl,
/* UDP header */
udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr);
udpHdr->source = htons(tunKey->flow_hash | 32768);
- udpHdr->dest = VXLAN_UDP_PORT_NBO;
+ udpHdr->dest = htons(tunKey->dst_port);
udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom +
sizeof *udpHdr + sizeof *vxlanHdr);
udpHdr->check = 0;
diff --git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h
index 248a5dcde..0e2830496 100644
--- a/datapath-windows/ovsext/Vxlan.h
+++ b/datapath-windows/ovsext/Vxlan.h
@@ -19,7 +19,7 @@
#include "NetProto.h"
typedef struct _OVS_VXLAN_VPORT {
- UINT32 dstPort;
+ UINT16 dstPort;
UINT64 inPkts;
UINT64 outPkts;
UINT64 slowInPkts;