diff options
author | Wilson Peng <pweisong@vmware.com> | 2022-04-06 21:18:19 +0800 |
---|---|---|
committer | Alin-Gabriel Serdean <aserdean@ovn.org> | 2022-04-10 05:18:59 +0300 |
commit | edb2335861d629f791467f77729e743378dac15f (patch) | |
tree | 82268b884ee34ba9aa689eec2ea3708649971ee4 /datapath-windows/ovsext/Actions.c | |
parent | 9d70f4a7c3df3bb33e64d8866e3aa752d747de70 (diff) | |
download | openvswitch-edb2335861d629f791467f77729e743378dac15f.tar.gz |
datapath-windows: Add IPv6 Geneve tunnel support in Windows
In the first step OVS Windows will support IPv6 tunnel(Geneve IPv6 tunnel).
Implementation on Windows
-------------------------
1. For the IPv6 tunnel support, OvsIPTunnelKey will replace original
OvsIPv4TunnelKey in the related flow context handing.
2. The related src and dst address will be changed to SOCKADDR_INET type from UINT32.
3. For the IPv6 tunnel, one node running OVS-Windows could encapsulate IPv4/IPv6
Packets via IPV6 Geneve Tunnel, and the node could also encapsulate IPv4/IPv6 packet
Via IPv4 Geneve tunnel.
4. Related IPHelper data structure will be adapted to support IPv6 Tunnel. In the IPHelper
part the related Windows API(such as GetUnicastIpAddressTable/GetBestRoute2/GetIpNetEntry2/
ResolveIpNetEntry2) and Windows data structure(MIB_IPFORWARD_ROW2/MIB_IPNET_ROW2/IP_ADDRESS_PREFIX)
Have already supported both IPv4 and IPV6. Now OVS Windows has been adjusted some functions
And data structured to support IPV6 tunnel also.
5. OVS_TUNNEL_KEY_ATTR_IPV6_SRC and OVS_TUNNEL_KEY_ATTR_IPV6_DST filed will be supported in
OVS-Windows kernel for IPV6 tunnel.
Testing done.
-------------------------
Related topo, 1 Windows VM(Win2019) and 2 Ubuntu 16.04 server. Both VMs
Are running on one ESX host.
1. Setup one IPV6 Geneve Tunnel between 1 Windows VM and 1 Ubuntu server.
Windows VM, vif0( 6000::2/40.1.1.10) vif1(5000::2)—— Ubuntu VM Eth2(5000::9), name space ns1
with interface ns1_link_peer(6000::9/40.1.1.2)
Related tunnnel,
ovs-vsctl.exe add-port br-int bms-tun0 -- set interface bms-tun0 type=Geneve options:csum=true
options:key=flow options:local_ip="5000::2" options:remote_ip=flow
In this topo, traffic from Vif0(Win) to ns1_link_peer(Ubuntu) will be gone through the Geneve tunnel
(5000::2—>5000::9) for both IPv4 traffic(40.1.1.10-->40.1.1.2) and IPv6 traffic(6000::2—>6000::9)
2. Setup one IPV4 Geneve Tunnel between Windows VM and 1 Ubuntu server.
Windows VM, vif0( 6000::2/40.1.1.10) vif1(50.1.1.11)—— Ubuntu, Eth2(50.1.1.9), name space ns1
with interface ns1_link_peer(6000::19/40.1.1.9)
Related tunnnel,
ovs-vsctl.exe -- set Interface bms-tun0 type=geneve options:csum=true options:key=flow
options:local_ip="50.1.1.11" options:remote_ip=flow
In this topo, traffic from Vif0(Win) to ns1_link_peer(Ubuntu) will be gone through the Geneve Tunnel
(50.1.1.11—>50.1.1.9) for both IPv4 traffic(40.1.1.10-->40.1.1.9) and IPv6 traffic(6000::2—>6000::19).
3.Regression test for IpV4 in Antrea project (about 60 test case) is PASS
Future Work
-----------
Add other type IPv6 tunnel support for Gre/Vxlan/Stt.
Signed-off-by: Wilson Peng <pweisong@vmware.com>
Signed-off-by: Alin-Gabriel Serdean <aserdean@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Actions.c')
-rw-r--r-- | datapath-windows/ovsext/Actions.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index 218e7db81..c66ece080 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -186,19 +186,29 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx, * packets only if they are at least VXLAN header size. */ - /* - * For some of the tunnel types such as GRE, the dstPort is not applicable - * since GRE does not have a L4 port. We use '0' for convenience. - */ - if (!flowKey->ipKey.nwFrag) { - UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst); + /* + * For some of the tunnel types such as GRE, the dstPort is not applicable + * since GRE does not have a L4 port. We use '0' for convenience. + */ - ASSERT(flowKey->ipKey.nwProto != IPPROTO_GRE || dstPort == 0); + if ((flowKey->l2.dlType == htons(ETH_TYPE_IPV4) && + !flowKey->ipKey.nwFrag) || + (flowKey->l2.dlType == htons(ETH_TYPE_IPV6) && + !flowKey->ipv6Key.nwFrag)) { + UINT16 dstPort = 0; + uint8_t nwProto = 0; + if (flowKey->l2.dlType == htons(ETH_TYPE_IPV6)) { + dstPort = htons(flowKey->ipv6Key.l4.tpDst); + nwProto = flowKey->ipv6Key.nwProto; + } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) { + dstPort = htons(flowKey->ipKey.l4.tpDst); + nwProto = flowKey->ipKey.nwProto; + } + ASSERT(nwProto != IPPROTO_GRE || dstPort == 0); tunnelVport = OvsFindTunnelVportByDstPortAndNWProto(ovsFwdCtx->switchContext, - dstPort, - flowKey->ipKey.nwProto); + dstPort, nwProto); if (tunnelVport) { switch(tunnelVport->ovsType) { case OVS_VPORT_TYPE_STT: @@ -290,12 +300,12 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, (vport->ovsType != OVS_VPORT_TYPE_NETDEV && vport->ovsType != OVS_VPORT_TYPE_INTERNAL && !OvsIsTunnelVportType(vport->ovsType))) { - ovsFwdCtx->tunKey.dst = 0; + RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst)); } } /* Tunnel the packet only if tunnel context is set. */ - if (ovsFwdCtx->tunKey.dst != 0) { + if (!OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))) { switch(dstVport->ovsType) { case OVS_VPORT_TYPE_GRE: ovsActionStats.txGre++; @@ -470,7 +480,7 @@ static __inline VOID OvsClearTunTxCtx(OvsForwardingContext *ovsFwdCtx) { ovsFwdCtx->tunnelTxNic = NULL; - ovsFwdCtx->tunKey.dst = 0; + RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst)); } @@ -484,7 +494,7 @@ static __inline VOID OvsClearTunRxCtx(OvsForwardingContext *ovsFwdCtx) { ovsFwdCtx->tunnelRxNic = NULL; - ovsFwdCtx->tunKey.dst = 0; + RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst)); } @@ -540,7 +550,7 @@ OvsCompleteNBLForwardingCtx(OvsForwardingContext *ovsFwdCtx, * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS -OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) +OvsDoFlowLookupOutput(OvsForwardingContext* ovsFwdCtx) { OvsFlowKey key = { 0 }; OvsFlow *flow = NULL; @@ -557,11 +567,11 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) ASSERT(vport->nicState == NdisSwitchNicStateConnected); /* Assert that in the Rx direction, key is always setup. */ - ASSERT(ovsFwdCtx->tunnelRxNic == NULL || ovsFwdCtx->tunKey.dst != 0); + ASSERT(ovsFwdCtx->tunnelRxNic == NULL || !OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))); status = OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, &key, &ovsFwdCtx->layers, - ovsFwdCtx->tunKey.dst != 0 ? &ovsFwdCtx->tunKey : NULL); + !OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))? &(ovsFwdCtx->tunKey):NULL); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Flow extract failed"); @@ -647,6 +657,7 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) OvsDoFragmentNbl(ovsFwdCtx, ctx->mru); } OVS_FWD_INFO switchFwdInfo = { 0 }; + /* Apply the encapsulation. The encapsulation will not consume the NBL. */ switch(ovsFwdCtx->tunnelTxNic->ovsType) { case OVS_VPORT_TYPE_GRE: @@ -915,11 +926,11 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) if (ovsFwdCtx->tunnelTxNic != NULL) { status = OvsTunnelPortTx(ovsFwdCtx); ASSERT(ovsFwdCtx->tunnelTxNic == NULL); - ASSERT(ovsFwdCtx->tunKey.dst == 0); + ASSERT(OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))); } else if (ovsFwdCtx->tunnelRxNic != NULL) { status = OvsTunnelPortRx(ovsFwdCtx); ASSERT(ovsFwdCtx->tunnelRxNic == NULL); - ASSERT(ovsFwdCtx->tunKey.dst == 0); + ASSERT(OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))); } ASSERT(ovsFwdCtx->curNbl == NULL); @@ -1753,10 +1764,10 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx, case OVS_KEY_ATTR_TUNNEL: { - OvsIPv4TunnelKey tunKey; + OvsIPTunnelKey tunKey = { 0 }; tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key)); tunKey.dst_port = key->ipKey.l4.tpDst; - NTSTATUS convertStatus = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey); + NTSTATUS convertStatus = OvsTunnelAttrToIPTunnelKey((PNL_ATTR)a, &tunKey); status = SUCCEEDED(convertStatus) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE; ASSERT(status == NDIS_STATUS_SUCCESS); RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey); @@ -1874,7 +1885,7 @@ OvsOutputUserspaceAction(OvsForwardingContext *ovsFwdCtx, POVS_PACKET_HDR_INFO layers = &ovsFwdCtx->layers; BOOLEAN isRecv = FALSE; OVS_FWD_INFO fwdInfo; - OvsIPv4TunnelKey tunKey; + OvsIPTunnelKey tunKey; POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo); @@ -1894,10 +1905,11 @@ OvsOutputUserspaceAction(OvsForwardingContext *ovsFwdCtx, if (egrTunAttr) { RtlZeroMemory(&tunKey, sizeof tunKey); RtlCopyMemory(&tunKey, &ovsFwdCtx->tunKey, sizeof tunKey); - if (!tunKey.src) { - status = OvsLookupIPFwdInfo(tunKey.src, tunKey.dst, &fwdInfo); - if (status == NDIS_STATUS_SUCCESS && tunKey.dst == fwdInfo.dstIpAddr) { - tunKey.src = fwdInfo.srcIpAddr; + if (!OvsIphIsZero(&(tunKey.src))) { + status = OvsLookupIPhFwdInfo(tunKey.src, tunKey.dst, &fwdInfo); + if (status == NDIS_STATUS_SUCCESS && + OvsIphAddrEquals(&(tunKey.dst), &(fwdInfo.dstIphAddr))) { + OvsCopyIphAddress(&(tunKey.src), &fwdInfo.srcIphAddr); } } tunKey.flow_hash = tunKey.flow_hash ? tunKey.flow_hash : MAXINT16; |