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 <svintu...@cloudbasesolutions.com>
Reported-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com>
Reported-at: https://github.com/openvswitch/ovs-issues/issues/64
---
 datapath-windows/ovsext/Actions.c |  8 +++--
 datapath-windows/ovsext/Switch.c  | 16 ++++++----
 datapath-windows/ovsext/Switch.h  |  2 +-
 datapath-windows/ovsext/Tunnel.c  |  3 +-
 datapath-windows/ovsext/Vport.c   | 63 ++++++++++++++++++++++++++-------------
 datapath-windows/ovsext/Vport.h   | 14 +++++----
 datapath-windows/ovsext/Vxlan.c   |  2 +-
 datapath-windows/ovsext/Vxlan.h   |  4 +--
 8 files changed, 71 insertions(+), 41 deletions(-)

diff --git a/datapath-windows/ovsext/Actions.c 
b/datapath-windows/ovsext/Actions.c
index a93fe03..20d2f1e 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -203,9 +203,10 @@ 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;
+        flowKey->ipKey.nwProto == IPPROTO_UDP) {
+        UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst);
+        tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext,
+                                                  dstPort);
         ovsActionStats.rxVxlan++;
     }
 
@@ -1318,6 +1319,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 cf5e3c4..665aff4 100644
--- a/datapath-windows/ovsext/Switch.c
+++ b/datapath-windows/ovsext/Switch.c
@@ -366,6 +366,8 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
         OvsAllocateMemory(sizeof (LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
     switchContext->pidHashArray = (PLIST_ENTRY)
         OvsAllocateMemory(sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE);
+    switchContext->tunnelVportsArray = (PLIST_ENTRY)
+        OvsAllocateMemory(sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
     status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);
 
     if (status == NDIS_STATUS_SUCCESS) {
@@ -376,7 +378,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);
         }
@@ -394,6 +397,10 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
             OvsFreeMemory(switchContext->pidHashArray);
         }
 
+        if (switchContext->tunnelVportsArray) {
+            OvsFreeMemory(switchContext->tunnelVportsArray);
+        }
+
         OvsDeleteFlowTable(&switchContext->datapath);
         OvsCleanupBufferPool(switchContext);
 
@@ -403,12 +410,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++) {
@@ -445,6 +449,8 @@ OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
     switchContext->portNoHashArray = NULL;
     OvsFreeMemory(switchContext->pidHashArray);
     switchContext->pidHashArray = NULL;
+    OvsFreeMemory(switchContext->tunnelVportsArray);
+    switchContext->tunnelVportsArray = NULL;
     OvsDeleteFlowTable(&switchContext->datapath);
     OvsCleanupBufferPool(switchContext);
     OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h
index 7960072..f2558e5 100644
--- a/datapath-windows/ovsext/Switch.h
+++ b/datapath-windows/ovsext/Switch.h
@@ -132,7 +132,7 @@ typedef struct _OVS_SWITCH_CONTEXT
     POVS_VPORT_ENTRY        virtualExternalVport;   // the virtual adapter 
vport
     POVS_VPORT_ENTRY        internalVport;
 
-    POVS_VPORT_ENTRY        vxlanVport;
+    PLIST_ENTRY             tunnelVportsArray;
 
     /*
      * 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,
diff --git a/datapath-windows/ovsext/Tunnel.c b/datapath-windows/ovsext/Tunnel.c
index fed58f1..002f180 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 968c112..bc5c23b 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -574,6 +574,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)
 {
@@ -999,8 +1018,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
@@ -1011,10 +1030,17 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
 
     switch(vport->ovsType) {
     case OVS_VPORT_TYPE_VXLAN:
-        //ASSERT(switchContext->vxlanVport == NULL);
-        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++;
@@ -1096,7 +1122,8 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
         break;
     case OVS_VPORT_TYPE_VXLAN:
         OvsCleanupVxlanTunnel(vport);
-        switchContext->vxlanVport = NULL;
+        RemoveEntryList(&vport->tunnelVportLink);
+        InitializeListHead(&vport->tunnelVportLink);
         break;
     case OVS_VPORT_TYPE_GRE:
     case OVS_VPORT_TYPE_GRE64:
@@ -1295,19 +1322,6 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT 
switchContext)
             vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);
             OvsRemoveAndDeleteVport(switchContext, vport, TRUE, TRUE, NULL);
         }
-    }
-    /*
-     * Remove 'virtualExternalVport' as well. This port is not part of the
-     * 'portIdHashArray'.
-     */
-    if (switchContext->virtualExternalVport) {
-        OvsRemoveAndDeleteVport(switchContext,
-            (POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE,
-            NULL);
-    }
-
-    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) {
@@ -1320,9 +1334,18 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT 
switchContext)
         }
     }
 
+    /*
+     * Remove 'virtualExternalVport' as well. This port is not part of the
+     * 'portIdHashArray'.
+     */
+    if (switchContext->virtualExternalVport) {
+        OvsRemoveAndDeleteVport(switchContext,
+            (POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE,
+            NULL);
+    }
+
     ASSERT(switchContext->virtualExternalVport == NULL);
     ASSERT(switchContext->internalVport == NULL);
-    ASSERT(switchContext->vxlanVport == NULL);
 }
 
 
@@ -2033,8 +2056,6 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT 
usrParamsCtx,
     } else {
         ASSERT(OvsIsTunnelVportType(portType) ||
                (portType == OVS_VPORT_TYPE_INTERNAL && isBridgeInternal));
-        //ASSERT(OvsGetTunnelVport(gOvsSwitchContext, portType) == NULL ||
-        //       !OvsIsTunnelVportType(portType));
 
         vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
         if (vport == NULL) {
diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h
index 348fbfd..1d8e253 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);
@@ -182,11 +183,12 @@ OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType)
 
 static __inline POVS_VPORT_ENTRY
 OvsGetTunnelVport(POVS_SWITCH_CONTEXT switchContext,
-                  OVS_VPORT_TYPE ovsType)
+                  OVS_VPORT_TYPE ovsType,
+                  UINT16 dstPort)
 {
     switch(ovsType) {
     case OVS_VPORT_TYPE_VXLAN:
-        return switchContext->vxlanVport;
+        return OvsFindTunnelVportByDstPort(switchContext, dstPort);
     default:
         return NULL;
     }
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index 8981bf5..717bbe4 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -238,7 +238,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 ade6b0c..5104bd4 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;
@@ -76,6 +76,4 @@ OvsGetVxlanTunHdrSize(VOID)
            sizeof (VXLANHdr);
 }
 
-#define VXLAN_UDP_PORT_NBO 0xB512
-
 #endif /* __VXLAN_H_ */
-- 
1.9.0.msysgit.0
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to