summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Flow.c
diff options
context:
space:
mode:
authorldejing <ldejing@vmware.com>2022-04-11 18:07:11 +0800
committerAlin-Gabriel Serdean <aserdean@ovn.org>2022-04-22 12:08:38 +0300
commit53b75e91ded95d25c6cae5698ad242ad775ebb40 (patch)
tree913638673d2db7d164b1a07b989167d490efb670 /datapath-windows/ovsext/Flow.c
parent96dc66ddadc35475ed93b25a84874c926f4d9dd3 (diff)
downloadopenvswitch-53b75e91ded95d25c6cae5698ad242ad775ebb40.tar.gz
datapath-windows: Add IPv6 conntrack support on Windows.
Implementation on Windows: Currently, IPv4 conntrack was supported on the windows platform. In this patch we have implemented ipv6 conntrack functions according to the current logic of the IPv4 conntrack. This implementation has included TcpV6(nat and normal scenario), UdpV6(nat and normal scenario), IcmpV6 conntrack of echo request/reply packet and FtpV6(nat and normal scenario). Testing Topology: On the Windows VM runs on the ESXi host, two hyper-v ports attached to the ovs bridge; one hyper-v port worked as client and the other port worked as server. Testing Case: 1. TcpV6 a) Tcp request/reply conntrack for normal scenario. In this scenario, 20::1 as client, 20::2 as server, it will generate following conntrack entry: (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=1556), reply(src=20::2,src_port=1556,dst=20::1,dst_port=1555),protocol=tcp) b) Tcp request/reply conntrack for nat scenario. In this scenario, 20::1 as client, 20::10 as floating ip, 21::3 as server, it will generate following conntrack entry: (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=1556), reply(src=21::3, src_port=1556, dst=20::1, dst_port= 1555),protocol=tcp) 2. UdpV6 a) Udp request/reply conntrack for normal scenario. (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=1556), reply(src=20::2,src_port=1556,dst=20::1,dst_port=1555),protocol=udp) b) Udp request/reply conntrack for nat scenario. (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=1556), reply(src=21::3, src_port=1556, dst=20::1, dst_port= 1555),protocol=udp) 3. IcmpV6: a) Icmpv6 request/reply conntrack for normal scenario. Currently Icmpv6 only support to construct conntrack for echo request/reply packet, take (20::1 -> 20::2) for example, it will generate following conntrack entry: (origin(src = 20::1, dst=20::2), reply(src=20::2, dst=20::1), protocol=icmp) b) Icmp request/reply conntrack for dnat scenario, for example (20::1->20::10->21::3), 20::1 is client, 20::10 is floating ip, 21::3 is server ip. It will generate flow like below: (origin(src=20::1, dst=20::10), reply(src=21::3, dst=20::1), protocol=icmp) 4. FtpV6 a) Ftp request/reply conntrack for normal scenario. In this scenario, take 20::1 as client, 20::2 as server, it will generate two conntrack entries: Ftp active mode (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=21), reply(src=20::2, src_port=21, dst=20::1, dst_port=1555), protocol=tcp) (Origin(src=20::2, src_port=20, dst=20::1, dst_port=1556), reply(src=20::1, src_port=1556, dst=20::2, dst_port=20), protocol=tcp) Ftp passive mode (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=21), reply(src=20::2,src_port=21,dst=20::1,dst_port=1555),protocol=tcp) (Origin(src=20::1, src_port=1556, dst=20::2, dst_port=1557), reply(src=20::2,src_port=1557, dst=20::1, dst_port=1556) protocol=tcp) b) Ftp request/reply conntrack for nat scenario. Ftp passive mode, In this secnario, 20::1 as client, 20::10 as floating ip, 21::3 as server ip. It will generate following flow: (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=21), reply(src=21::3, src_port=21, dst=20::1, dst_port= 1555),protocol=tcp) (Origin(src=20::1, src_port=1556, dst=20::10, dst_port=1557), reply(src=21::3, src_port=1557, dst=20::1, dst_port= 1556),protocol=tcp) 5. Regression test for IpV4 in Antrea project (about 60 test case) Future work: 1) IcmpV6 redirect packet conntrack. 2) IpV6 fragment support on Udp. 3) Support napt for IPv6. 4) FtpV6 active mode for nat. Signed-off-by: ldejing <ldejing@vmware.com> Signed-off-by: Alin-Gabriel Serdean <aserdean@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Flow.c')
-rw-r--r--datapath-windows/ovsext/Flow.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c
index 0a7b2b1d4..08fba4c4d 100644
--- a/datapath-windows/ovsext/Flow.c
+++ b/datapath-windows/ovsext/Flow.c
@@ -186,6 +186,10 @@ const NL_POLICY nlFlowKeyPolicy[] = {
[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {.type = NL_A_UNSPEC,
.minLen = sizeof(struct ovs_key_ct_tuple_ipv4),
.maxLen = sizeof(struct ovs_key_ct_tuple_ipv4),
+ .optional = TRUE},
+ [OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {.type = NL_A_UNSPEC,
+ .minLen = OVS_TUPLE_IPV6,
+ .maxLen = OVS_TUPLE_IPV6,
.optional = TRUE}
};
const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
@@ -1580,6 +1584,13 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
sizeof(struct ovs_key_ct_tuple_ipv4));
}
+ if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {
+ const struct ovs_key_ct_tuple_ipv6 *tuple_ipv6;
+ tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
+ NdisMoveMemory(&destKey->ct.tuple_ipv6, tuple_ipv6,
+ sizeof(struct ovs_key_ct_tuple_ipv6));
+ }
+
/* ===== L2 headers ===== */
if (keyAttrs[OVS_KEY_ATTR_IN_PORT]) {
destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
@@ -2170,6 +2181,13 @@ OvsGetFlowMetadata(OvsFlowKey *key,
sizeof(struct ovs_key_ct_tuple_ipv4));
}
+ if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {
+ const struct ovs_key_ct_tuple_ipv6 *tuple_ipv6;
+ tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
+ NdisMoveMemory(&key->ct.tuple_ipv6, tuple_ipv6,
+ sizeof(struct ovs_key_ct_tuple_ipv6));
+ }
+
return status;
}
@@ -2292,6 +2310,7 @@ OvsExtractLayers(const NET_BUFFER_LIST *packet,
if (icmp) {
layers->l7Offset = layers->l4Offset + sizeof *icmp;
}
+ layers->isIcmp = 1;
}
}
} else {
@@ -2651,6 +2670,8 @@ FlowEqual(OvsFlow *srcFlow,
sizeof(struct ovs_key_ct_labels)) &&
!memcmp(&srcFlow->key.ct.tuple_ipv4, &dstKey->ct.tuple_ipv4,
sizeof(struct ovs_key_ct_tuple_ipv4)) &&
+ !memcmp(&srcFlow->key.ct.tuple_ipv6, &dstKey->ct.tuple_ipv6,
+ sizeof(struct ovs_key_ct_tuple_ipv6)) &&
FlowMemoryEqual((UINT64 *)((UINT8 *)&srcFlow->key + offset),
(UINT64 *) dstStart,
size));
@@ -2763,13 +2784,20 @@ OvsLookupFlow(OVS_DATAPATH *datapath,
0);
*hash = OvsJhashWords((UINT32*)hash, 1, lblHash);
}
- if (key->ct.tuple_ipv4.ipv4_src) {
+ if (key->ct.tuple_ipv4.ipv4_proto) {
UINT32 tupleHash = OvsJhashBytes(
&key->ct.tuple_ipv4,
sizeof(struct ovs_key_ct_tuple_ipv4),
0);
*hash = OvsJhashWords((UINT32*)hash, 1, tupleHash);
}
+
+ if (key->ct.tuple_ipv6.ipv6_proto) {
+ UINT32 tupleHash = OvsJhashBytes(&key->ct.tuple_ipv6,
+ sizeof(struct ovs_key_ct_tuple_ipv6),
+ 0);
+ *hash = OvsJhashWords((UINT32*)hash, 1, tupleHash);
+ }
}
head = &datapath->flowTable[HASH_BUCKET(*hash)];
@@ -2945,7 +2973,9 @@ ReportFlowInfo(OvsFlow *flow,
NdisMoveMemory(&info->key.ct.tuple_ipv4,
&flow->key.ct.tuple_ipv4,
sizeof(struct ovs_key_ct_tuple_ipv4));
-
+ NdisMoveMemory(&info->key.ct.tuple_ipv6,
+ &flow->key.ct.tuple_ipv6,
+ sizeof(struct ovs_key_ct_tuple_ipv6));
return status;
}
@@ -3339,6 +3369,13 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
OVS_LOG_ERROR("Invalid ct_tuple_ipv4.");
status = STATUS_INVALID_PARAMETER;
}
+ } else if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {
+ const struct ovs_key_ct_tuple_ipv6 *ct_tuple_ipv6;
+ ct_tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
+ if (!ct_tuple_ipv6) {
+ OVS_LOG_ERROR("Invalid ct_tuple_ipv6.");
+ status = STATUS_INVALID_PARAMETER;
+ }
} else {
OVS_LOG_ERROR("Feature not supported.");
status = STATUS_INVALID_PARAMETER;