It would be awesome to apply it on 2.5 as well. I will update the matrix once it is applied.
Thanks, Alin. > -----Mesaj original----- > De la: Justin Pettit [mailto:[email protected]] > Trimis: Friday, December 11, 2015 10:33 PM > Către: Alin Serdean <[email protected]> > Cc: [email protected] > Subiect: Re: [ovs-dev] [PATCH v4] datapath-windows: Add GRE TEB support > for windows datapath > > If everyone is happy with this, I'll apply it. I assume we should also update > the FAQ support Matrix to indicate GRE support on Hyper-V, correct? Would > you like this cherry-picked to branch-2.5? > > --Justin > > > > On Dec 11, 2015, at 11:18 AM, Alin Serdean > <[email protected]> wrote: > > > > This patch introduces the support for GRE TEB (trasparent ethernet > > bridging) for the windows datapath. > > > > The GRE support is based on http://tools.ietf.org/html/rfc2890, > > without taking into account the GRE sequence, and it supports only the > > GRE protocol type 6558 (trasparent ethernet bridging) like its linux > counterpart. > > > > Util.h: define the GRE pool tag > > Vport.c/h: sort the includes alphabetically > > add the function OvsFindTunnelVportByPortType which searches the > > tunnelVportsArray for a given port type Actions.c : sort the > > includes alphabetically > > call the GRE encapsulation / decapsulation functions when > > needed Gre.c/h : add GRE type defines > > add initialization/cleanup functions > > add encapsulation / decapsulation functions with software offloads > > (hardware offloads will be added in a separate patch) > > support > > > > Tested using: PSPING > > (https://technet.microsoft.com/en-us/sysinternals/psping.aspx) > > (ICMP, TCP, UDP) with various packet lengths > > IPERF3 > > (https://iperf.fr/iperf-download.php) > > (TCP, UDP) with various options > > > > Signed-off-by: Alin Gabriel Serdean <[email protected]> > > Acked-by: Nithin Raju <[email protected]> > > Acked-by: Sorin Vinturis <[email protected]> > > --- > > v4: clearly specify in the commit message we do not support GRE sequence > > add Acked-by's > > v3: add LSO v2 support, remove GRE sequence since it is not used, address > > comments > > v2: add Gre.c/h to automake.mk EXTRA_DIST > > --- > > datapath-windows/automake.mk | 20 +- > > datapath-windows/ovsext/Actions.c | 71 ++++-- > > datapath-windows/ovsext/Gre.c | 453 > +++++++++++++++++++++++++++++++++ > > datapath-windows/ovsext/Gre.h | 100 ++++++++ > > datapath-windows/ovsext/Util.h | 1 + > > datapath-windows/ovsext/Vport.c | 40 ++- > > datapath-windows/ovsext/Vport.h | 13 +- > > datapath-windows/ovsext/ovsext.vcxproj | 2 + > > 8 files changed, 656 insertions(+), 44 deletions(-) create mode 100644 > > datapath-windows/ovsext/Gre.c create mode 100644 > > datapath-windows/ovsext/Gre.h > > > > diff --git a/datapath-windows/automake.mk > > b/datapath-windows/automake.mk index ed48c69..7f12d92 100644 > > --- a/datapath-windows/automake.mk > > +++ b/datapath-windows/automake.mk > > @@ -4,45 +4,49 @@ EXTRA_DIST += \ > > datapath-windows/Package/package.VcxProj \ > > datapath-windows/Package/package.VcxProj.user \ > > datapath-windows/include/OvsDpInterfaceExt.h \ > > + datapath-windows/misc/OVS.psm1 \ > > datapath-windows/misc/install.cmd \ > > datapath-windows/misc/uninstall.cmd \ > > - datapath-windows/misc/OVS.psm1 \ > > datapath-windows/ovsext.sln \ > > - datapath-windows/ovsext/Datapath.c \ > > - datapath-windows/ovsext/Datapath.h \ > > - datapath-windows/ovsext/DpInternal.h\ > > datapath-windows/ovsext/Actions.c \ > > datapath-windows/ovsext/Atomic.h \ > > datapath-windows/ovsext/BufferMgmt.c \ > > datapath-windows/ovsext/BufferMgmt.h \ > > datapath-windows/ovsext/Checksum.c \ > > datapath-windows/ovsext/Checksum.h \ > > + datapath-windows/ovsext/Datapath.c \ > > + datapath-windows/ovsext/Datapath.h \ > > datapath-windows/ovsext/Debug.c \ > > datapath-windows/ovsext/Debug.h \ > > + datapath-windows/ovsext/DpInternal.h\ > > datapath-windows/ovsext/Driver.c \ > > datapath-windows/ovsext/Ethernet.h \ > > datapath-windows/ovsext/Event.c \ > > datapath-windows/ovsext/Event.h \ > > datapath-windows/ovsext/Flow.c \ > > datapath-windows/ovsext/Flow.h \ > > + datapath-windows/ovsext/Gre.h \ > > + datapath-windows/ovsext/Gre.c \ > > datapath-windows/ovsext/IpHelper.c \ > > datapath-windows/ovsext/IpHelper.h \ > > datapath-windows/ovsext/Jhash.c \ > > datapath-windows/ovsext/Jhash.h \ > > + datapath-windows/ovsext/NetProto.h \ > > datapath-windows/ovsext/Netlink/Netlink.c \ > > datapath-windows/ovsext/Netlink/Netlink.h \ > > datapath-windows/ovsext/Netlink/NetlinkBuf.c \ > > datapath-windows/ovsext/Netlink/NetlinkBuf.h \ > > datapath-windows/ovsext/Netlink/NetlinkError.h \ > > datapath-windows/ovsext/Netlink/NetlinkProto.h \ > > - datapath-windows/ovsext/NetProto.h \ > > datapath-windows/ovsext/Oid.c \ > > datapath-windows/ovsext/Oid.h \ > > datapath-windows/ovsext/PacketIO.c \ > > datapath-windows/ovsext/PacketIO.h \ > > datapath-windows/ovsext/PacketParser.c \ > > datapath-windows/ovsext/PacketParser.h \ > > - datapath-windows/ovsext/Switch.c \ > > + datapath-windows/ovsext/Stt.c \ > > + datapath-windows/ovsext/Stt.h \ > > + datapath-windows/ovsext/Switch.c \ > > datapath-windows/ovsext/Switch.h \ > > datapath-windows/ovsext/Tunnel.c \ > > datapath-windows/ovsext/Tunnel.h \ > > @@ -51,13 +55,11 @@ EXTRA_DIST += \ > > datapath-windows/ovsext/Types.h \ > > datapath-windows/ovsext/User.c \ > > datapath-windows/ovsext/User.h \ > > - datapath-windows/ovsext/Util.c \ > > + datapath-windows/ovsext/Util.c \ > > datapath-windows/ovsext/Util.h \ > > datapath-windows/ovsext/Vport.c \ > > datapath-windows/ovsext/Vport.h \ > > datapath-windows/ovsext/Vxlan.c \ > > - datapath-windows/ovsext/Stt.h \ > > - datapath-windows/ovsext/Stt.c \ > > datapath-windows/ovsext/Vxlan.h \ > > datapath-windows/ovsext/ovsext.inf \ > > datapath-windows/ovsext/ovsext.rc \ > > diff --git a/datapath-windows/ovsext/Actions.c > > b/datapath-windows/ovsext/Actions.c > > index 7d34458..bfa8482 100644 > > --- a/datapath-windows/ovsext/Actions.c > > +++ b/datapath-windows/ovsext/Actions.c > > @@ -16,16 +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 "Stt.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 > > @@ -34,6 +35,8 @@ > > #include "Debug.h" > > > > typedef struct _OVS_ACTION_STATS { > > + UINT64 rxGre; > > + UINT64 txGre; > > UINT64 rxVxlan; > > UINT64 txVxlan; > > UINT64 rxStt; > > @@ -205,27 +208,35 @@ 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) { > > - UINT16 dstPort = ntohs(flowKey->ipKey.l4.tpDst); > > - tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx- > >switchContext, > > - dstPort, > > - OVS_VPORT_TYPE_VXLAN); > > - if (tunnelVport) { > > - ovsActionStats.rxVxlan++; > > - } > > - } else if (!flowKey->ipKey.nwFrag && > > - flowKey->ipKey.nwProto == IPPROTO_TCP) { > > + if (!flowKey->ipKey.nwFrag) { > > UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst); > > - tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx- > >switchContext, > > - dstPort, > > - OVS_VPORT_TYPE_STT); > > - if (tunnelVport) { > > - ovsActionStats.rxStt++; > > + 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. > > if (tunnelVport) { > > ASSERT(ovsFwdCtx->tunnelRxNic == NULL); @@ -306,6 +317,9 @@ > > OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, > > /* Tunnel the packet only if tunnel context is set. */ > > if (ovsFwdCtx->tunKey.dst != 0) { > > switch(dstVport->ovsType) { > > + case OVS_VPORT_TYPE_GRE: > > + ovsActionStats.txGre++; > > + break; > > case OVS_VPORT_TYPE_VXLAN: > > ovsActionStats.txVxlan++; > > break; > > @@ -652,6 +666,11 @@ 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->tunnelTxNic, ovsFwdCtx->curNbl, > > &ovsFwdCtx->tunKey, > > ovsFwdCtx->switchContext, @@ -724,6 +743,10 @@ > OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) > > */ > > > > switch(tunnelRxVport->ovsType) { > > + case OVS_VPORT_TYPE_GRE: > > + status = OvsDecapGre(ovsFwdCtx->switchContext, ovsFwdCtx- > >curNbl, > > + &ovsFwdCtx->tunKey, &newNbl); > > + break; > > case OVS_VPORT_TYPE_VXLAN: > > status = OvsDecapVxlan(ovsFwdCtx->switchContext, ovsFwdCtx- > >curNbl, > > &ovsFwdCtx->tunKey, &newNbl); diff > > --git a/datapath-windows/ovsext/Gre.c b/datapath- > windows/ovsext/Gre.c > > new file mode 100644 index 0000000..3ebfda3 > > --- /dev/null > > +++ b/datapath-windows/ovsext/Gre.c > > @@ -0,0 +1,453 @@ > > +/* > > + * Copyright (c) 2015 Cloudbase Solutions Srl > > + * > > + * Licensed under the Apache License, Version 2.0 (the "License"); > > + * you may not use this file except in compliance with the License. > > + * You may obtain a copy of the License at > > + * > > + * http://www.apache.org/licenses/LICENSE-2.0 > > + * > > + * Unless required by applicable law or agreed to in writing, > > +software > > + * distributed under the License is distributed on an "AS IS" BASIS, > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express > or implied. > > + * See the License for the specific language governing permissions > > +and > > + * limitations under the License. > > + */ > > + > > +#include "precomp.h" > > + > > +#include "Atomic.h" > > +#include "Checksum.h" > > +#include "Flow.h" > > +#include "Gre.h" > > +#include "IpHelper.h" > > +#include "NetProto.h" > > +#include "PacketIO.h" > > +#include "PacketParser.h" > > +#include "Switch.h" > > +#include "User.h" > > +#include "Util.h" > > +#include "Vport.h" > > + > > +#ifdef OVS_DBG_MOD > > +#undef OVS_DBG_MOD > > +#endif > > +#define OVS_DBG_MOD OVS_DBG_GRE > > +#include "Debug.h" > > + > > +static NDIS_STATUS > > +OvsDoEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, > > + const OvsIPv4TunnelKey *tunKey, > > + const POVS_FWD_INFO fwdInfo, > > + POVS_PACKET_HDR_INFO layers, > > + POVS_SWITCH_CONTEXT switchContext, > > + PNET_BUFFER_LIST *newNbl); > > + > > +/* > > + * > > +--------------------------------------------------------------------- > > +----- > > + * OvsInitGreTunnel -- > > + * Initialize GRE tunnel module. > > + * > > +--------------------------------------------------------------------- > > +----- > > + */ > > +NTSTATUS > > +OvsInitGreTunnel(POVS_VPORT_ENTRY vport) { > > + POVS_GRE_VPORT grePort; > > + > > + grePort = > (POVS_GRE_VPORT)OvsAllocateMemoryWithTag(sizeof(*grePort), > > + OVS_GRE_POOL_TAG); > > + if (!grePort) { > > + OVS_LOG_ERROR("Insufficient memory, can't allocate > OVS_GRE_VPORT"); > > + return STATUS_INSUFFICIENT_RESOURCES; > > + } > > + > > + RtlZeroMemory(grePort, sizeof(*grePort)); > > + vport->priv = (PVOID)grePort; > > + return STATUS_SUCCESS; > > +} > > + > > +/* > > + * > > +--------------------------------------------------------------------- > > +----- > > + * OvsCleanupGreTunnel -- > > + * Cleanup GRE Tunnel module. > > + * > > +--------------------------------------------------------------------- > > +----- > > + */ > > +void > > +OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport) { > > + if (vport->ovsType != OVS_VPORT_TYPE_GRE || > > + vport->priv == NULL) { > > + return; > > + } > > + > > + OvsFreeMemoryWithTag(vport->priv, OVS_GRE_POOL_TAG); > > + vport->priv = NULL; > > +} > > + > > +/* > > + * > > +--------------------------------------------------------------------- > > +----- > > + * OvsEncapGre -- > > + * Encapsulates a packet with an GRE header. > > + * > > +--------------------------------------------------------------------- > > +----- > > + */ > > +NDIS_STATUS > > +OvsEncapGre(POVS_VPORT_ENTRY vport, > > + PNET_BUFFER_LIST curNbl, > > + OvsIPv4TunnelKey *tunKey, > > + POVS_SWITCH_CONTEXT switchContext, > > + POVS_PACKET_HDR_INFO layers, > > + PNET_BUFFER_LIST *newNbl) { > > + OVS_FWD_INFO fwdInfo; > > + NDIS_STATUS status; > > + > > + status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > > + if (status != STATUS_SUCCESS) { > > + OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); > > + return NDIS_STATUS_FAILURE; > > + } > > + > > + status = OvsDoEncapGre(vport, curNbl, tunKey, &fwdInfo, layers, > > + switchContext, newNbl); > > + return status; > > +} > > + > > +/* > > + * > > +--------------------------------------------------------------------- > > +----- > > + * OvsDoEncapGre -- > > + * Internal utility function which actually does the GRE encap. > > + * > > +--------------------------------------------------------------------- > > +----- > > + */ > > +NDIS_STATUS > > +OvsDoEncapGre(POVS_VPORT_ENTRY vport, > > + PNET_BUFFER_LIST curNbl, > > + const OvsIPv4TunnelKey *tunKey, > > + const POVS_FWD_INFO fwdInfo, > > + POVS_PACKET_HDR_INFO layers, > > + POVS_SWITCH_CONTEXT switchContext, > > + PNET_BUFFER_LIST *newNbl) { > > + NDIS_STATUS status; > > + PNET_BUFFER curNb; > > + PMDL curMdl; > > + PUINT8 bufferStart; > > + EthHdr *ethHdr; > > + IPHdr *ipHdr; > > + PGREHdr greHdr; > > + POVS_GRE_VPORT vportGre; > > + UINT32 headRoom = GreTunHdrSize(tunKey->flags); #if DBG > > + UINT32 counterHeadRoom; > > +#endif > > + UINT32 packetLength; > > + ULONG mss = 0; > > + ASSERT(*newNbl == NULL); > > + > > + curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > > + packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > + > > + if (layers->isTcp) { > > + NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; > > + > > + tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, > > + > > TcpLargeSendNetBufferListInfo); > > + switch (tsoInfo.Transmit.Type) { > > + case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: > > + mss = tsoInfo.LsoV1Transmit.MSS; > > + break; > > + case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: > > + mss = tsoInfo.LsoV2Transmit.MSS; > > + break; > > + default: > > + OVS_LOG_ERROR("Unknown LSO transmit type:%d", > > + tsoInfo.Transmit.Type); > > + return NDIS_STATUS_FAILURE; > > + } > > + OVS_LOG_TRACE("MSS %u packet len %u", mss, > > + packetLength); > > + if (mss) { > > + OVS_LOG_TRACE("l4Offset %d", layers->l4Offset); > > + *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers, > > + mss, headRoom); > > + if (*newNbl == NULL) { > > + OVS_LOG_ERROR("Unable to segment NBL"); > > + return NDIS_STATUS_FAILURE; > > + } > > + /* Clear out LSO flags after this point */ > > + NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) > = 0; > > + } > > + } > > + > > + vportGre = (POVS_GRE_VPORT)GetOvsVportPriv(vport); > > + ASSERT(vportGre); > > + > > + /* If we didn't split the packet above, make a copy now */ > > + if (*newNbl == NULL) { > > + *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom, > > + FALSE /*NBL info*/); > > + if (*newNbl == NULL) { > > + OVS_LOG_ERROR("Unable to copy NBL"); > > + return NDIS_STATUS_FAILURE; > > + } > > + /* > > + * To this point we do not have GRE hardware offloading. > > + * Apply defined checksums > > + */ > > + curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); > > + curMdl = NET_BUFFER_CURRENT_MDL(curNb); > > + bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > > + > > LowPagePriority); > > + if (!bufferStart) { > > + status = NDIS_STATUS_RESOURCES; > > + goto ret_error; > > + } > > + > > + NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > > + csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, > > + > > + TcpIpChecksumNetBufferListInfo); > > + > > + bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > > + > > + if (layers->isIPv4) { > > + IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); > > + > > + if (csumInfo.Transmit.IpHeaderChecksum) { > > + ip->check = 0; > > + ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); > > + } > > + > > + if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { > > + UINT16 csumLength = (UINT16)(packetLength - > > layers->l4Offset); > > + TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); > > + tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, > > + IPPROTO_TCP, csumLength); > > + tcp->check = CalculateChecksumNB(curNb, csumLength, > > + > > (UINT32)(layers->l4Offset)); > > + } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { > > + UINT16 csumLength = (UINT16)(packetLength - > > layers->l4Offset); > > + UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); > > + udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, > > + IPPROTO_UDP, csumLength); > > + udp->check = CalculateChecksumNB(curNb, csumLength, > > + > > (UINT32)(layers->l4Offset)); > > + } > > + } else if (layers->isIPv6) { > > + IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + > > + layers->l3Offset); > > + > > + if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { > > + UINT16 csumLength = (UINT16)(packetLength - > > layers->l4Offset); > > + TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); > > + tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, > > + (UINT32 *) &ip->daddr, > > + IPPROTO_TCP, csumLength); > > + tcp->check = CalculateChecksumNB(curNb, csumLength, > > + > > (UINT32)(layers->l4Offset)); > > + } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { > > + UINT16 csumLength = (UINT16)(packetLength - > > layers->l4Offset); > > + UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); > > + udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, > > + (UINT32 *) &ip->daddr, > > + IPPROTO_UDP, csumLength); > > + udp->check = CalculateChecksumNB(curNb, csumLength, > > + > > (UINT32)(layers->l4Offset)); > > + } > > + } > > + /* Clear out TcpIpChecksumNetBufferListInfo flag */ > > + NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) > = 0; > > + } > > + > > + curNbl = *newNbl; > > + for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL; > > + curNb = curNb->Next) { > > +#if DBG > > + counterHeadRoom = headRoom; > > +#endif > > + status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); > > + if (status != NDIS_STATUS_SUCCESS) { > > + goto ret_error; > > + } > > + > > + curMdl = NET_BUFFER_CURRENT_MDL(curNb); > > + bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > > + > > LowPagePriority); > > + if (!bufferStart) { > > + status = NDIS_STATUS_RESOURCES; > > + goto ret_error; > > + } > > + > > + bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > > + if (NET_BUFFER_NEXT_NB(curNb)) { > > + OVS_LOG_TRACE("nb length %u next %u", > > + NET_BUFFER_DATA_LENGTH(curNb), > > + NET_BUFFER_DATA_LENGTH(curNb->Next)); > > + } > > + > > + /* L2 header */ > > + ethHdr = (EthHdr *)bufferStart; > > + ASSERT(((PCHAR)&fwdInfo->dstMacAddr + sizeof fwdInfo- > >dstMacAddr) == > > + (PCHAR)&fwdInfo->srcMacAddr); > > + NdisMoveMemory(ethHdr->Destination, fwdInfo->dstMacAddr, > > + sizeof ethHdr->Destination + sizeof ethHdr->Source); > > + ethHdr->Type = htons(ETH_TYPE_IPV4); #if DBG > > + counterHeadRoom -= sizeof *ethHdr; #endif > > + > > + /* IP header */ > > + ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); > > + > > + ipHdr->ihl = sizeof *ipHdr / 4; > > + ipHdr->version = IPPROTO_IPV4; > > + ipHdr->tos = tunKey->tos; > > + ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof > *ethHdr); > > + ipHdr->id = (uint16)atomic_add64(&vportGre->ipId, > > + NET_BUFFER_DATA_LENGTH(curNb)); > > + ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ? > > + IP_DF_NBO : 0; > > + ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64; > > + ipHdr->protocol = IPPROTO_GRE; > > + ASSERT(tunKey->dst == fwdInfo->dstIpAddr); > > + ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0); > > + ipHdr->saddr = fwdInfo->srcIpAddr; > > + ipHdr->daddr = fwdInfo->dstIpAddr; > > + > > + ipHdr->check = 0; > > + ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0); > > +#if DBG > > + counterHeadRoom -= sizeof *ipHdr; #endif > > + > > + /* GRE header */ > > + greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr); > > + greHdr->flags = OvsTunnelFlagsToGreFlags(tunKey->flags); > > + greHdr->protocolType = GRE_NET_TEB; #if DBG > > + counterHeadRoom -= sizeof *greHdr; #endif > > + > > + PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr; > > + > > + if (tunKey->flags & OVS_TNL_F_CSUM) { > > + RtlZeroMemory(currentOffset, 4); > > + currentOffset += 4; > > +#if DBG > > + counterHeadRoom -= 4; > > +#endif > > + } > > + > > + if (tunKey->flags & OVS_TNL_F_KEY) { > > + RtlZeroMemory(currentOffset, 4); > > + UINT32 key = (tunKey->tunnelId >> 32); > > + RtlCopyMemory(currentOffset, &key, sizeof key); > > + currentOffset += 4; > > +#if DBG > > + counterHeadRoom -= 4; > > +#endif > > + } > > + > > +#if DBG > > + ASSERT(counterHeadRoom == 0); #endif > > + > > + } > > + return STATUS_SUCCESS; > > + > > +ret_error: > > + OvsCompleteNBL(switchContext, *newNbl, TRUE); > > + *newNbl = NULL; > > + return status; > > +} > > + > > +NDIS_STATUS > > +OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, > > + PNET_BUFFER_LIST curNbl, > > + OvsIPv4TunnelKey *tunKey, > > + PNET_BUFFER_LIST *newNbl) { > > + PNET_BUFFER curNb; > > + PMDL curMdl; > > + EthHdr *ethHdr; > > + IPHdr *ipHdr; > > + GREHdr *greHdr; > > + UINT32 tunnelSize = 0, packetLength = 0; > > + UINT32 headRoom = 0; > > + PUINT8 bufferStart; > > + NDIS_STATUS status; > > + > > + curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > > + packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > + tunnelSize = GreTunHdrSize(tunKey->flags); > > + if (packetLength <= tunnelSize) { > > + return NDIS_STATUS_INVALID_LENGTH; > > + } > > + > > + /* > > + * Create a copy of the NBL so that we have all the headers in one MDL. > > + */ > > + *newNbl = OvsPartialCopyNBL(switchContext, curNbl, > > + tunnelSize + OVS_DEFAULT_COPY_SIZE, 0, > > + TRUE /*copy NBL info */); > > + > > + if (*newNbl == NULL) { > > + return NDIS_STATUS_RESOURCES; > > + } > > + > > + curNbl = *newNbl; > > + curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > > + curMdl = NET_BUFFER_CURRENT_MDL(curNb); > > + bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > LowPagePriority) + > > + NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > > + if (!bufferStart) { > > + status = NDIS_STATUS_RESOURCES; > > + goto dropNbl; > > + } > > + > > + ethHdr = (EthHdr *)bufferStart; > > + headRoom += sizeof *ethHdr; > > + > > + ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); > > + tunKey->src = ipHdr->saddr; > > + tunKey->dst = ipHdr->daddr; > > + tunKey->tos = ipHdr->tos; > > + tunKey->ttl = ipHdr->ttl; > > + tunKey->pad = 0; > > + headRoom += sizeof *ipHdr; > > + > > + greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr); > > + headRoom += sizeof *greHdr; > > + > > + /* Validate if GRE header protocol type. */ > > + if (greHdr->protocolType != GRE_NET_TEB) { > > + status = STATUS_NDIS_INVALID_PACKET; > > + goto dropNbl; > > + } > > + > > + PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr; > > + > > + if (greHdr->flags & GRE_CSUM) { > > + tunKey->flags |= OVS_TNL_F_CSUM; > > + currentOffset += 4; > > + headRoom += 4; > > + } > > + > > + if (greHdr->flags & GRE_KEY) { > > + tunKey->flags |= OVS_TNL_F_KEY; > > + UINT32 key = 0; > > + RtlCopyMemory(&key, currentOffset, 4); > > + tunKey->tunnelId = (UINT64)key << 32; > > + currentOffset += 4; > > + headRoom += 4; > > + } > > + > > + /* Clear out the receive flag for the inner packet. */ > > + NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0; > > + NdisAdvanceNetBufferDataStart(curNb, GreTunHdrSize(tunKey->flags), > FALSE, > > + NULL); > > + ASSERT(headRoom == GreTunHdrSize(tunKey->flags)); > > + return NDIS_STATUS_SUCCESS; > > + > > +dropNbl: > > + OvsCompleteNBL(switchContext, *newNbl, TRUE); > > + *newNbl = NULL; > > + return status; > > +} > > diff --git a/datapath-windows/ovsext/Gre.h > > b/datapath-windows/ovsext/Gre.h new file mode 100644 index > > 0000000..d2472d9 > > --- /dev/null > > +++ b/datapath-windows/ovsext/Gre.h > > @@ -0,0 +1,100 @@ > > +/* > > + * Copyright (c) 2015 Cloudbase Solutions Srl > > + * > > + * Licensed under the Apache License, Version 2.0 (the "License"); > > + * you may not use this file except in compliance with the License. > > + * You may obtain a copy of the License at > > + * > > + * http://www.apache.org/licenses/LICENSE-2.0 > > + * > > + * Unless required by applicable law or agreed to in writing, > > +software > > + * distributed under the License is distributed on an "AS IS" BASIS, > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express > or implied. > > + * See the License for the specific language governing permissions > > +and > > + * limitations under the License. > > + */ > > + > > +#ifndef __GRE_H_ > > +#define __GRE_H_ 1 > > + > > +#include "NetProto.h" > > +#include "Flow.h" > > + > > +typedef struct _OVS_GRE_VPORT { > > + UINT64 ipId; > > + /* > > + * To be filled > > + */ > > +} OVS_GRE_VPORT, *POVS_GRE_VPORT; > > + > > + > > +/* GRE RFC 2890 header based on http://tools.ietf.org/html/rfc2890 > > + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 > > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > + * |C| |K|S| Reserved0 | Ver | Protocol Type | > > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > + * | Checksum (optional) | Reserved1 (Optional) | > > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > + * | Key (optional) | > > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > + * | Sequence Number (Optional) | > > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > + */ > > + > > +typedef struct GREHdr { > > + UINT16 flags; > > + UINT16 protocolType; > > +} GREHdr, *PGREHdr; > > + > > +/* Transparent Ethernet Bridging */ > > +#define GRE_NET_TEB 0x5865 > > +/* GRE Flags*/ > > +#define GRE_CSUM 0x0080 > > +#define GRE_KEY 0x0020 > > + > > +NTSTATUS OvsInitGreTunnel(POVS_VPORT_ENTRY vport); > > + > > +VOID OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport); > > + > > + > > +void OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport); > > + > > +NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport, > > + PNET_BUFFER_LIST curNbl, > > + OvsIPv4TunnelKey *tunKey, > > + POVS_SWITCH_CONTEXT switchContext, > > + POVS_PACKET_HDR_INFO layers, > > + PNET_BUFFER_LIST *newNbl); > > + > > +NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, > > + PNET_BUFFER_LIST curNbl, > > + OvsIPv4TunnelKey *tunKey, > > + PNET_BUFFER_LIST *newNbl); > > + > > +static __inline UINT16 > > +OvsTunnelFlagsToGreFlags(UINT16 tunnelflags) { > > + UINT16 flags = 0; > > + > > + if (tunnelflags & OVS_TNL_F_CSUM) > > + flags |= GRE_CSUM; > > + > > + if (tunnelflags & OVS_TNL_F_KEY) > > + flags |= GRE_KEY; > > + > > + return flags; > > +} > > + > > +static __inline UINT32 > > +GreTunHdrSize(UINT16 flags) > > +{ > > + UINT32 sum = sizeof(EthHdr) + sizeof(IPHdr) + sizeof(GREHdr); > > + sum += (flags & OVS_TNL_F_CSUM) ? > > + 4 : 0; > > + sum += (flags & OVS_TNL_F_KEY) ? > > + 4 : 0; > > + > > + return sum; > > +} > > + > > +#endif /*__GRE_H_ */ > > diff --git a/datapath-windows/ovsext/Util.h > > b/datapath-windows/ovsext/Util.h index e5ba72b..a81c723 100644 > > --- a/datapath-windows/ovsext/Util.h > > +++ b/datapath-windows/ovsext/Util.h > > @@ -34,6 +34,7 @@ > > #define OVS_USER_POOL_TAG 'USVO' > > #define OVS_VPORT_POOL_TAG 'PSVO' > > #define OVS_STT_POOL_TAG 'RSVO' > > +#define OVS_GRE_POOL_TAG 'GSVO' > > #define OVS_TUNFLT_POOL_TAG 'WSVO' > > > > VOID *OvsAllocateMemory(size_t size); > > diff --git a/datapath-windows/ovsext/Vport.c > > b/datapath-windows/ovsext/Vport.c index a7576d3..7b0103d 100644 > > --- a/datapath-windows/ovsext/Vport.c > > +++ b/datapath-windows/ovsext/Vport.c > > @@ -15,16 +15,18 @@ > > */ > > > > #include "precomp.h" > > + > > +#include "Datapath.h" > > +#include "Event.h" > > +#include "Gre.h" > > +#include "IpHelper.h" > > #include "Jhash.h" > > +#include "Oid.h" > > +#include "Stt.h" > > #include "Switch.h" > > -#include "Vport.h" > > -#include "Event.h" > > #include "User.h" > > +#include "Vport.h" > > #include "Vxlan.h" > > -#include "Stt.h" > > -#include "IpHelper.h" > > -#include "Oid.h" > > -#include "Datapath.h" > > > > #ifdef OVS_DBG_MOD > > #undef OVS_DBG_MOD > > @@ -700,6 +702,24 @@ > OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext, > > return NULL; > > } > > > > +POVS_VPORT_ENTRY > > +OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT > switchContext, > > + OVS_VPORT_TYPE ovsPortType) { > > + POVS_VPORT_ENTRY vport; > > + PLIST_ENTRY head, link; > > + UINT16 dstPort = 0; > > + 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 (vport->ovsType == ovsPortType) { > > + return vport; > > + } > > + } > > + return NULL; > > +} > > > > POVS_VPORT_ENTRY > > OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext, @@ - > 983,6 > > +1003,7 @@ OvsInitTunnelVport(PVOID userContext, > > vport->ovsState = OVS_STATE_PORT_CREATED; > > switch (ovsType) { > > case OVS_VPORT_TYPE_GRE: > > + status = OvsInitGreTunnel(vport); > > break; > > case OVS_VPORT_TYPE_VXLAN: > > { > > @@ -1153,6 +1174,7 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT > switchContext, > > UINT32 hash; > > > > switch(vport->ovsType) { > > + case OVS_VPORT_TYPE_GRE: > > case OVS_VPORT_TYPE_VXLAN: > > case OVS_VPORT_TYPE_STT: > > { > > @@ -1242,6 +1264,7 @@ OvsRemoveAndDeleteVport(PVOID > usrParamsContext, > > OvsCleanupSttTunnel(vport); > > break; > > case OVS_VPORT_TYPE_GRE: > > + OvsCleanupGreTunnel(vport); > > break; > > case OVS_VPORT_TYPE_NETDEV: > > if (vport->isExternal) { > > @@ -1299,7 +1322,8 @@ OvsRemoveAndDeleteVport(PVOID > usrParamsContext, > > RemoveEntryList(&vport->portNoLink); > > InitializeListHead(&vport->portNoLink); > > if (OVS_VPORT_TYPE_VXLAN == vport->ovsType || > > - OVS_VPORT_TYPE_STT == vport->ovsType) { > > + OVS_VPORT_TYPE_STT == vport->ovsType || > > + OVS_VPORT_TYPE_GRE == vport->ovsType) { > > RemoveEntryList(&vport->tunnelVportLink); > > InitializeListHead(&vport->tunnelVportLink); > > } > > @@ -2190,6 +2214,8 @@ > OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > > UINT16 transportPortDest = 0; > > > > switch (portType) { > > + case OVS_VPORT_TYPE_GRE: > > + break; > > case OVS_VPORT_TYPE_VXLAN: > > transportPortDest = VXLAN_UDP_PORT; > > break; > > diff --git a/datapath-windows/ovsext/Vport.h > > b/datapath-windows/ovsext/Vport.h index e9f3b03..373896d 100644 > > --- a/datapath-windows/ovsext/Vport.h > > +++ b/datapath-windows/ovsext/Vport.h > > @@ -17,9 +17,10 @@ > > #ifndef __VPORT_H_ > > #define __VPORT_H_ 1 > > > > +#include "Gre.h" > > +#include "Stt.h" > > #include "Switch.h" > > #include "VxLan.h" > > -#include "Stt.h" > > > > #define OVS_MAX_DPPORTS MAXUINT16 > > #define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS > > @@ -147,6 +148,8 @@ POVS_VPORT_ENTRY > > OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchConte > POVS_VPORT_ENTRY > OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext, > > UINT16 dstPort, > > OVS_VPORT_TYPE > > ovsVportType); > > +POVS_VPORT_ENTRY > OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext, > > + OVS_VPORT_TYPE > > +ovsPortType); > > > > NDIS_STATUS OvsAddConfiguredSwitchPorts(struct > _OVS_SWITCH_CONTEXT > > *switchContext); NDIS_STATUS OvsInitConfiguredSwitchNics(struct > > _OVS_SWITCH_CONTEXT *switchContext); @@ -256,16 +259,18 @@ > GetPortFromPriv(POVS_VPORT_ENTRY vport) > > /* XXX would better to have a commom tunnel "parent" structure */ > > ASSERT(vportPriv); > > switch(vport->ovsType) { > > - case OVS_VPORT_TYPE_VXLAN: > > - dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort; > > + case OVS_VPORT_TYPE_GRE: > > break; > > case OVS_VPORT_TYPE_STT: > > dstPort = ((POVS_STT_VPORT)vportPriv)->dstPort; > > break; > > + case OVS_VPORT_TYPE_VXLAN: > > + dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort; > > + break; > > default: > > ASSERT(! "Port is not a tunnel port"); > > } > > - ASSERT(dstPort); > > + ASSERT(dstPort || vport->ovsType == OVS_VPORT_TYPE_GRE); > > return dstPort; > > } > > > > diff --git a/datapath-windows/ovsext/ovsext.vcxproj > > b/datapath-windows/ovsext/ovsext.vcxproj > > index 616f688..231ac83 100644 > > --- a/datapath-windows/ovsext/ovsext.vcxproj > > +++ b/datapath-windows/ovsext/ovsext.vcxproj > > @@ -80,6 +80,7 @@ > > <ClInclude Include="Ethernet.h" /> > > <ClInclude Include="Event.h" /> > > <ClInclude Include="Flow.h" /> > > + <ClInclude Include="Gre.h" /> > > <ClInclude Include="IpHelper.h" /> > > <ClInclude Include="Jhash.h" /> > > <ClInclude Include="Netlink/Netlink.h" /> @@ -172,6 +173,7 @@ > > <ClCompile Include="Driver.c" /> > > <ClCompile Include="Event.c" /> > > <ClCompile Include="Flow.c" /> > > + <ClCompile Include="Gre.c" /> > > <ClCompile Include="IpHelper.c" /> > > <ClCompile Include="Jhash.c" /> > > <ClCompile Include="Netlink/Netlink.c" /> > > -- > > 1.9.5.msysgit.0 > > _______________________________________________ > > dev mailing list > > [email protected] > > http://openvswitch.org/mailman/listinfo/dev > > _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
