X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=datapath-windows%2Fovsext%2FActions.c;h=c113a84ebf98f314059fb80f2bad38525010ba02;hb=85571a3daa67603ce4096c12ba0522acded4deb0;hp=f5ce12e90766fec39297fec2e64c061553b141e0;hpb=4a3c9b7048fe7f7af444954b36f7bb104d6d6389;p=cascardo%2Fovs.git diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index f5ce12e90..c113a84eb 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -16,15 +16,17 @@ #include "precomp.h" -#include "Switch.h" -#include "Vport.h" +#include "Checksum.h" #include "Event.h" -#include "User.h" -#include "NetProto.h" #include "Flow.h" -#include "Vxlan.h" -#include "Checksum.h" +#include "Gre.h" +#include "NetProto.h" #include "PacketIO.h" +#include "Stt.h" +#include "Switch.h" +#include "User.h" +#include "Vport.h" +#include "Vxlan.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD @@ -33,8 +35,12 @@ #include "Debug.h" typedef struct _OVS_ACTION_STATS { + UINT64 rxGre; + UINT64 txGre; UINT64 rxVxlan; UINT64 txVxlan; + UINT64 rxStt; + UINT64 txStt; UINT64 flowMiss; UINT64 flowUserspace; UINT64 txTcp; @@ -202,11 +208,33 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx, /* XXX: we should also check for the length of the UDP payload to pick * 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++; + if (!flowKey->ipKey.nwFrag) { + UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst); + switch (flowKey->ipKey.nwProto) { + case IPPROTO_GRE: + tunnelVport = OvsFindTunnelVportByPortType(ovsFwdCtx->switchContext, + OVS_VPORT_TYPE_GRE); + if (tunnelVport) { + ovsActionStats.rxGre++; + } + break; + case IPPROTO_TCP: + tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, + dstPort, + OVS_VPORT_TYPE_STT); + if (tunnelVport) { + ovsActionStats.rxStt++; + } + break; + case IPPROTO_UDP: + tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, + dstPort, + OVS_VPORT_TYPE_VXLAN); + if (tunnelVport) { + ovsActionStats.rxVxlan++; + } + break; + } } // We might get tunnel packets even before the tunnel gets initialized. @@ -248,10 +276,11 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, * port or if it is being executed from userspace, the source port is * default port. */ - BOOLEAN validSrcPort = (ovsFwdCtx->fwdDetail->SourcePortId == - ovsFwdCtx->switchContext->externalPortId) || - (ovsFwdCtx->fwdDetail->SourcePortId == - NDIS_SWITCH_DEFAULT_PORT_ID); + BOOLEAN validSrcPort = + (ovsFwdCtx->fwdDetail->SourcePortId == + ovsFwdCtx->switchContext->virtualExternalPortId) || + (ovsFwdCtx->fwdDetail->SourcePortId == + NDIS_SWITCH_DEFAULT_PORT_ID); if (validSrcPort && OvsDetectTunnelRxPkt(ovsFwdCtx, flowKey)) { ASSERT(ovsFwdCtx->tunnelTxNic == NULL); @@ -265,25 +294,39 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, /* * Tx: * The destination port is a tunnel port. Encapsulation must be - * performed only on packets that originate from a VIF port or from - * userspace (default port) + * performed only on packets that originate from: + * - a VIF port + * - a bridge-internal port (packets generated from userspace) + * - no port. * * If the packet will not be encapsulated, consume the tunnel context * by clearing it. */ - if (ovsFwdCtx->srcVportNo != OVS_DEFAULT_PORT_NO) { + if (ovsFwdCtx->srcVportNo != OVS_DPPORT_NUMBER_INVALID) { POVS_VPORT_ENTRY vport = OvsFindVportByPortNo( ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo); - if (!vport || vport->ovsType != OVS_VPORT_TYPE_NETDEV) { + if (!vport || + (vport->ovsType != OVS_VPORT_TYPE_NETDEV && + !OvsIsBridgeInternalVport(vport))) { ovsFwdCtx->tunKey.dst = 0; } } /* Tunnel the packet only if tunnel context is set. */ if (ovsFwdCtx->tunKey.dst != 0) { - ovsActionStats.txVxlan++; + switch(dstVport->ovsType) { + case OVS_VPORT_TYPE_GRE: + ovsActionStats.txGre++; + break; + case OVS_VPORT_TYPE_VXLAN: + ovsActionStats.txVxlan++; + break; + case OVS_VPORT_TYPE_STT: + ovsActionStats.txStt++; + break; + } ovsFwdCtx->tunnelTxNic = dstVport; } @@ -343,6 +386,10 @@ OvsAddPorts(OvsForwardingContext *ovsFwdCtx, vport->stats.txBytes += NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl)); + if (OvsIsBridgeInternalVport(vport)) { + return NDIS_STATUS_SUCCESS; + } + if (OvsDetectTunnelPkt(ovsFwdCtx, vport, flowKey)) { return NDIS_STATUS_SUCCESS; } @@ -533,9 +580,10 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) /* Assert that in the Rx direction, key is always setup. */ ASSERT(ovsFwdCtx->tunnelRxNic == NULL || ovsFwdCtx->tunKey.dst != 0); - status = OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, - &key, &ovsFwdCtx->layers, ovsFwdCtx->tunKey.dst != 0 ? - &ovsFwdCtx->tunKey : NULL); + status = + OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, + &key, &ovsFwdCtx->layers, + ovsFwdCtx->tunKey.dst != 0 ? &ovsFwdCtx->tunKey : NULL); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Flow extract failed"); @@ -548,20 +596,19 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) OvsFlowUsed(flow, ovsFwdCtx->curNbl, &ovsFwdCtx->layers); ovsFwdCtx->switchContext->datapath.hits++; status = OvsActionsExecute(ovsFwdCtx->switchContext, - ovsFwdCtx->completionList, ovsFwdCtx->curNbl, - ovsFwdCtx->srcVportNo, ovsFwdCtx->sendFlags, - &key, &hash, &ovsFwdCtx->layers, - flow->actions, flow->actionsLen); + ovsFwdCtx->completionList, ovsFwdCtx->curNbl, + ovsFwdCtx->srcVportNo, ovsFwdCtx->sendFlags, + &key, &hash, &ovsFwdCtx->layers, + flow->actions, flow->actionsLen); ovsFwdCtx->curNbl = NULL; } else { LIST_ENTRY missedPackets; UINT32 num = 0; ovsFwdCtx->switchContext->datapath.misses++; InitializeListHead(&missedPackets); - status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS, - ovsFwdCtx->srcVportNo, + status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS, vport, &key,ovsFwdCtx->curNbl, - ovsFwdCtx->tunnelRxNic != NULL, &ovsFwdCtx->layers, + FALSE, &ovsFwdCtx->layers, ovsFwdCtx->switchContext, &missedPackets, &num); if (num) { OvsQueuePackets(&missedPackets, num); @@ -603,10 +650,11 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) * Setup the source port to be the internal port to as to facilitate the * second OvsLookupFlow. */ - if (ovsFwdCtx->switchContext->internalVport == NULL) { + if (ovsFwdCtx->switchContext->internalVport == NULL || + ovsFwdCtx->switchContext->virtualExternalVport == NULL) { OvsClearTunTxCtx(ovsFwdCtx); OvsCompleteNBLForwardingCtx(ovsFwdCtx, - L"OVS-Dropped since internal port is absent"); + L"OVS-Dropped since either internal or external port is absent"); return NDIS_STATUS_FAILURE; } ovsFwdCtx->srcVportNo = @@ -618,12 +666,21 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) /* Do the encap. Encap function does not consume the NBL. */ switch(ovsFwdCtx->tunnelTxNic->ovsType) { + case OVS_VPORT_TYPE_GRE: + status = OvsEncapGre(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, + &ovsFwdCtx->layers, &newNbl); + break; case OVS_VPORT_TYPE_VXLAN: - status = OvsEncapVxlan(ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, - ovsFwdCtx->switchContext, - (VOID *)ovsFwdCtx->completionList, + status = OvsEncapVxlan(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, &ovsFwdCtx->layers, &newNbl); break; + case OVS_VPORT_TYPE_STT: + status = OvsEncapStt(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, + &ovsFwdCtx->layers, &newNbl); + break; default: ASSERT(! "Tx: Unhandled tunnel type"); } @@ -671,6 +728,7 @@ OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNET_BUFFER_LIST newNbl = NULL; POVS_VPORT_ENTRY tunnelRxVport = ovsFwdCtx->tunnelRxNic; + PCWSTR dropReason = L"OVS-dropped due to new decap packet"; if (OvsValidateIPChecksum(ovsFwdCtx->curNbl, &ovsFwdCtx->layers) != NDIS_STATUS_SUCCESS) { @@ -679,14 +737,27 @@ OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) goto dropNbl; } + /* + * Decap port functions should return a new NBL if it was copied, and + * this new NBL should be setup as the ovsFwdCtx->curNbl. + */ + switch(tunnelRxVport->ovsType) { + case OVS_VPORT_TYPE_GRE: + status = OvsDecapGre(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, &newNbl); + break; case OVS_VPORT_TYPE_VXLAN: - /* - * OvsDoDecapVxlan should return a new NBL if it was copied, and - * this new NBL should be setup as the ovsFwdCtx->curNbl. - */ - status = OvsDoDecapVxlan(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, - &ovsFwdCtx->tunKey, &newNbl); + status = OvsDecapVxlan(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, &newNbl); + break; + case OVS_VPORT_TYPE_STT: + status = OvsDecapStt(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, + &ovsFwdCtx->tunKey, &newNbl); + if (status == NDIS_STATUS_SUCCESS && newNbl == NULL) { + /* This was an STT-LSO Fragment */ + dropReason = L"OVS-STT segment is cached"; + } break; default: OVS_LOG_ERROR("Rx: Unhandled tunnel type: %d\n", @@ -704,25 +775,26 @@ OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) * tunnelRxNic and other fields will be cleared, re-init the context * before usage. */ - OvsCompleteNBLForwardingCtx(ovsFwdCtx, - L"OVS-dropped due to new decap packet"); + OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason); - /* Decapsulated packet is in a new NBL */ - ovsFwdCtx->tunnelRxNic = tunnelRxVport; - OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, - newNbl, tunnelRxVport->portNo, 0, - NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), - ovsFwdCtx->completionList, - &ovsFwdCtx->layers, FALSE); + if (newNbl) { + /* Decapsulated packet is in a new NBL */ + ovsFwdCtx->tunnelRxNic = tunnelRxVport; + OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, + newNbl, tunnelRxVport->portNo, 0, + NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), + ovsFwdCtx->completionList, + &ovsFwdCtx->layers, FALSE); - /* - * Set the NBL's SourcePortId and SourceNicIndex to default values to - * keep NDIS happy when we forward the packet. - */ - ovsFwdCtx->fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; - ovsFwdCtx->fwdDetail->SourceNicIndex = 0; + /* + * Set the NBL's SourcePortId and SourceNicIndex to default values to + * keep NDIS happy when we forward the packet. + */ + ovsFwdCtx->fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; + ovsFwdCtx->fwdDetail->SourceNicIndex = 0; - status = OvsDoFlowLookupOutput(ovsFwdCtx); + status = OvsDoFlowLookupOutput(ovsFwdCtx); + } ASSERT(ovsFwdCtx->curNbl == NULL); OvsClearTunRxCtx(ovsFwdCtx); @@ -755,6 +827,7 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) { NDIS_STATUS status = STATUS_SUCCESS; POVS_SWITCH_CONTEXT switchContext = ovsFwdCtx->switchContext; + PCWSTR dropReason; /* * Handle the case where the some of the destination ports are tunneled @@ -783,6 +856,7 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) if (newNbl == NULL) { status = NDIS_STATUS_RESOURCES; ovsActionStats.noCopiedNbl++; + dropReason = L"Dropped due to failure to create NBL copy."; goto dropit; } } @@ -795,6 +869,7 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE); ovsActionStats.cannotGrowDest++; + dropReason = L"Dropped due to failure to update destinations."; goto dropit; } @@ -810,8 +885,7 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) ovsFwdCtx->completionList, &ovsFwdCtx->layers, FALSE); if (status != NDIS_STATUS_SUCCESS) { - OvsCompleteNBLForwardingCtx(ovsFwdCtx, - L"Dropped due to resouces"); + dropReason = L"Dropped due to resouces."; goto dropit; } } @@ -832,7 +906,7 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) dropit: if (status != NDIS_STATUS_SUCCESS) { - OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"Dropped due to XXX"); + OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason); } return status; @@ -902,7 +976,6 @@ OvsOutputBeforeSetAction(OvsForwardingContext *ovsFwdCtx) { PNET_BUFFER_LIST newNbl; NDIS_STATUS status = NDIS_STATUS_SUCCESS; - PNET_BUFFER nb; /* * Create a copy and work on the copy after this point. The original NBL is @@ -922,14 +995,14 @@ OvsOutputBeforeSetAction(OvsForwardingContext *ovsFwdCtx) * XXX Head room needs to include the additional encap. * XXX copySize check is not considering multiple NBs. */ - nb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, 0, 0, TRUE /*copy NBL info*/); ASSERT(ovsFwdCtx->destPortsSizeOut > 0 || ovsFwdCtx->tunnelTxNic != NULL || ovsFwdCtx->tunnelRxNic != NULL); - /* Send the original packet out */ + /* Send the original packet out and save the original source port number */ + UINT32 tempVportNo = ovsFwdCtx->srcVportNo; status = OvsOutputForwardingCtx(ovsFwdCtx); ASSERT(ovsFwdCtx->curNbl == NULL); ASSERT(ovsFwdCtx->destPortsSizeOut == 0); @@ -947,7 +1020,7 @@ OvsOutputBeforeSetAction(OvsForwardingContext *ovsFwdCtx) OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE); } else { status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, - newNbl, ovsFwdCtx->srcVportNo, 0, + newNbl, tempVportNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), ovsFwdCtx->completionList, &ovsFwdCtx->layers, FALSE); @@ -1303,30 +1376,17 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx, case OVS_KEY_ATTR_TUNNEL: { OvsIPv4TunnelKey tunKey; - - status = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey); + 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; } - case OVS_KEY_ATTR_SKB_MARK: - /* XXX: Not relevant to Hyper-V. Return OK */ - break; - case OVS_KEY_ATTR_UNSPEC: - case OVS_KEY_ATTR_ENCAP: - case OVS_KEY_ATTR_ETHERTYPE: - case OVS_KEY_ATTR_IN_PORT: - case OVS_KEY_ATTR_VLAN: - case OVS_KEY_ATTR_ICMP: - case OVS_KEY_ATTR_ICMPV6: - case OVS_KEY_ATTR_ARP: - case OVS_KEY_ATTR_ND: - case __OVS_KEY_ATTR_MAX: + default: - OVS_LOG_INFO("Unhandled attribute %#x", type); - ASSERT(FALSE); + OVS_LOG_INFO("Unhandled attribute %#x", type); + break; } return status; } @@ -1487,7 +1547,7 @@ OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext, elem = OvsCreateQueueNlPacket((PVOID)userdataAttr, userdataAttr->nlaLen, OVS_PACKET_CMD_ACTION, - portNo, key,ovsFwdCtx.curNbl, + vport, key, ovsFwdCtx.curNbl, NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx.curNbl), isRecv, layers);