On Mon, May 11, 2015 at 5:42 AM, Sorin Vinturis
<[email protected]> wrote:
> 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 <[email protected]>
> Reported-by: Alin Gabriel Serdean <[email protected]>
> Reported-at: https://github.com/openvswitch/ovs-issues/issues/64
> Acked-by: Eitan Eliahu <[email protected]>
The patch does not apply on tip of master. Please rebase.
> ---
> datapath-windows/ovsext/Actions.c | 13 +++++++++----
> datapath-windows/ovsext/Switch.c | 16 +++++++++++-----
> datapath-windows/ovsext/Switch.h | 6 ++++--
> datapath-windows/ovsext/Tunnel.c | 3 ++-
> datapath-windows/ovsext/Vport.c | 40
> +++++++++++++++++++++++++++++++++------
> datapath-windows/ovsext/Vport.h | 21 +++++---------------
> datapath-windows/ovsext/Vxlan.c | 2 +-
> datapath-windows/ovsext/Vxlan.h | 2 +-
> 8 files changed, 67 insertions(+), 36 deletions(-)
>
> diff --git a/datapath-windows/ovsext/Actions.c
> b/datapath-windows/ovsext/Actions.c
> index a93fe03..79e464c 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 416bcc0..f877854 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 6ec34e1..8e1eb5f 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 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 e3a1803..aafbbcc 100644
> --- a/datapath-windows/ovsext/Vport.c
> +++ b/datapath-windows/ovsext/Vport.c
> @@ -591,6 +591,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)
> {
> @@ -1038,8 +1057,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
> @@ -1050,9 +1069,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++;
> @@ -1152,7 +1179,8 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext,
> OvsTunnelVportPendingUninit,
> tunnelContext);
>
> - switchContext->vxlanVport = NULL;
> + RemoveEntryList(&vport->tunnelVportLink);
> + InitializeListHead(&vport->tunnelVportLink);
> break;
> }
> case OVS_VPORT_TYPE_GRE:
> @@ -1352,6 +1380,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT
> switchContext)
> OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
> }
> }
> +
> /*
> * Remove 'virtualExternalVport' as well. This port is not part of the
> * 'portIdHashArray'.
> @@ -1361,9 +1390,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;
> @@ -1377,7 +1406,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 4cfda30..086f03f 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 963d033..0474fcd 100644
> --- a/datapath-windows/ovsext/Vxlan.c
> +++ b/datapath-windows/ovsext/Vxlan.c
> @@ -264,7 +264,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 248a5dc..0e28304 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;
> --
> 1.9.0.msysgit.0
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev