summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Conntrack-nat.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/Conntrack-nat.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/Conntrack-nat.c')
-rw-r--r--datapath-windows/ovsext/Conntrack-nat.c82
1 files changed, 66 insertions, 16 deletions
diff --git a/datapath-windows/ovsext/Conntrack-nat.c b/datapath-windows/ovsext/Conntrack-nat.c
index 1607d4c4f..497354ec8 100644
--- a/datapath-windows/ovsext/Conntrack-nat.c
+++ b/datapath-windows/ovsext/Conntrack-nat.c
@@ -42,12 +42,9 @@ OvsHashNatKey(const OVS_CT_KEY *key)
static __inline BOOLEAN
OvsNatKeyAreSame(const OVS_CT_KEY *key1, const OVS_CT_KEY *key2)
{
- // XXX: Compare IPv6 key as well
#define FIELD_COMPARE(field) \
if (key1->field != key2->field) return FALSE
- FIELD_COMPARE(src.addr.ipv4_aligned);
- FIELD_COMPARE(dst.addr.ipv4_aligned);
FIELD_COMPARE(src.port);
FIELD_COMPARE(dst.port);
FIELD_COMPARE(zone);
@@ -56,6 +53,15 @@ OvsNatKeyAreSame(const OVS_CT_KEY *key1, const OVS_CT_KEY *key2)
FIELD_COMPARE(dst.icmp_type);
FIELD_COMPARE(src.icmp_code);
FIELD_COMPARE(dst.icmp_code);
+
+ if (memcmp(&(key1->src.addr), &(key2->src.addr), sizeof(struct ct_addr))) {
+ return FALSE;
+ }
+
+ if (memcmp(&(key1->dst.addr), &(key2->dst.addr), sizeof(struct ct_addr))) {
+ return FALSE;
+ }
+
return TRUE;
#undef FIELD_COMPARE
}
@@ -215,18 +221,37 @@ OvsNatPacket(OvsForwardingContext *ovsFwdCtx,
} else {
key->ipKey.nwDst = endpoint->addr.ipv4_aligned;
}
- } else if (ctKey->dl_type == htons(ETH_TYPE_IPV6)){
- // XXX: IPv6 packet not supported yet.
- return;
+ } else if (ctKey->dl_type == htons(ETH_TYPE_IPV6)) {
+ OvsUpdateAddressAndPortForIpv6(ovsFwdCtx,
+ endpoint->addr.ipv6,
+ endpoint->port, isSrcNat,
+ !reverse);
+ if (isSrcNat) {
+ key->ipv6Key.ipv6Src = endpoint->addr.ipv6;
+ } else {
+ key->ipv6Key.ipv6Dst = endpoint->addr.ipv6;
+ }
}
if (natAction & (NAT_ACTION_SRC_PORT | NAT_ACTION_DST_PORT)) {
- if (isSrcNat) {
- if (key->ipKey.l4.tpSrc != 0) {
- key->ipKey.l4.tpSrc = endpoint->port;
+ if (ctKey->dl_type == htons(ETH_TYPE_IPV4)) {
+ if (isSrcNat) {
+ if (key->ipKey.l4.tpSrc != 0) {
+ key->ipKey.l4.tpSrc = endpoint->port;
+ }
+ } else {
+ if (key->ipKey.l4.tpDst != 0) {
+ key->ipKey.l4.tpDst = endpoint->port;
+ }
}
- } else {
- if (key->ipKey.l4.tpDst != 0) {
- key->ipKey.l4.tpDst = endpoint->port;
+ } else if (ctKey->dl_type == htons(ETH_TYPE_IPV6)) {
+ if (isSrcNat) {
+ if (key->ipv6Key.l4.tpSrc != 0) {
+ key->ipv6Key.l4.tpSrc = endpoint->port;
+ }
+ } else {
+ if (key->ipv6Key.l4.tpDst != 0) {
+ key->ipv6Key.l4.tpDst = endpoint->port;
+ }
}
}
}
@@ -326,8 +351,8 @@ OvsNatTranslateCtEntry(OVS_CT_ENTRY *entry)
ctAddr.ipv4_aligned = htonl(
ntohl(entry->natInfo.minAddr.ipv4_aligned) + addrIndex);
} else {
- // XXX: IPv6 not supported
- return FALSE;
+ /** Current, only support nat single address**/
+ ctAddr.ipv6_aligned = entry->natInfo.minAddr.ipv6_aligned;
}
port = firstPort;
@@ -379,8 +404,33 @@ OvsNatTranslateCtEntry(OVS_CT_ENTRY *entry)
ctAddr.ipv4_aligned = htonl(
ntohl(ctAddr.ipv4_aligned) + 1);
} else {
- // XXX: IPv6 not supported
- return FALSE;
+ /** When all ports was used, return fails indicate exceed range. **/
+ uint32_t addr[8] = {0};
+ uint16_t *tmpAddr = (uint16_t *)&(ctAddr.ipv6_aligned);
+ for (int m = 0; m < 8; m++) {
+ addr[m] = tmpAddr[m];
+ }
+
+ uint16_t carry = 1, i = 8;
+ while (carry && i)
+ {
+ addr[i-1] += carry;
+ if (addr[i-1] > 0xffff || !addr[i-1])
+ {
+ carry = 1;
+ addr[i-1] &= 0xffff;
+ } else carry = 0;
+ i--;
+ }
+
+ if (carry) {
+ OVS_LOG_INFO("Ipv6 address incremented overflow.");
+ return FALSE;
+ }
+
+ for (int m = 0; m < 8; m++) {
+ tmpAddr[m] = (uint16_t)addr[m];
+ }
}
} else {
ctAddr = entry->natInfo.minAddr;