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