summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Actions.c
diff options
context:
space:
mode:
authorWilson Peng <pweisong@vmware.com>2022-04-06 21:18:19 +0800
committerAlin-Gabriel Serdean <aserdean@ovn.org>2022-04-10 05:18:59 +0300
commitedb2335861d629f791467f77729e743378dac15f (patch)
tree82268b884ee34ba9aa689eec2ea3708649971ee4 /datapath-windows/ovsext/Actions.c
parent9d70f4a7c3df3bb33e64d8866e3aa752d747de70 (diff)
downloadopenvswitch-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.c62
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;