summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilson Peng <pweisong@vmware.com>2022-11-09 09:35:06 +0800
committerAlin-Gabriel Serdean <aserdean@ovn.org>2022-11-24 10:59:41 +0200
commitd400921d22f54a1fbca80446db6e2d69a1eb6e6e (patch)
tree27e8dc0ee237b978989c03d6a9f81b79881d501e
parent8e62f27ae7ee91f11fded34bb39b4f4e28a79808 (diff)
downloadopenvswitch-d400921d22f54a1fbca80446db6e2d69a1eb6e6e.tar.gz
datapath-windows: Check the condition to reset pseudo header checksum on Rx side
If ovs node running on Windows is processing NAT action on the RX side, it will reset pseudo header checksum only if the L4 checksum is same as the calculated pseudo header checksum before NAT action. Without the fix, if the L4 header checksum is filled with a pseudo header checksum (sourceip, dstip, protocol, tcppayloadlen+tcpheaderlen) OVS will still do the checksum update(replace some IP and port and recalculate the checksum). It will lead to incorrect L4 header checksum. Reported-at:https://github.com/openvswitch/ovs-issues/issues/265 Signed-off-by: Wilson Peng <pweisong@vmware.com> Signed-off-by: Alin-Gabriel Serdean <aserdean@ovn.org>
-rw-r--r--datapath-windows/ovsext/Actions.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 218e7db81..e3eb05d65 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -1502,6 +1502,8 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
UINT16 *checkField = NULL;
BOOLEAN l4Offload = FALSE;
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
+ UINT16 preNatPseudoChecksum = 0;
+ BOOLEAN preservePseudoChecksum = FALSE;
ASSERT(layers->value != 0);
@@ -1537,6 +1539,11 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
* case, we only update the TTL.
*/
/*Only tx direction the checksum value will be reset to be PseudoChecksum*/
+ if (!isTx) {
+ preNatPseudoChecksum = IPPseudoChecksum(&ipHdr->saddr, &ipHdr->daddr,
+ tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,
+ ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);
+ }
if (isSource) {
addrField = &ipHdr->saddr;
@@ -1553,7 +1560,12 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||
(BOOLEAN)csumInfo.Receive.UdpChecksumFailed);
}
- if (isTx && l4Offload) {
+ if (!isTx && l4Offload) {
+ if (*checkField == preNatPseudoChecksum) {
+ preservePseudoChecksum = TRUE;
+ }
+ }
+ if (isTx && l4Offload || preservePseudoChecksum) {
*checkField = IPPseudoChecksum(&newAddr, &ipHdr->daddr,
tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,
ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);
@@ -1573,8 +1585,13 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||
(BOOLEAN)csumInfo.Receive.UdpChecksumFailed);
}
+ if (!isTx && l4Offload) {
+ if (*checkField == preNatPseudoChecksum) {
+ preservePseudoChecksum = TRUE;
+ }
+ }
- if (isTx && l4Offload) {
+ if (isTx && l4Offload || preservePseudoChecksum) {
*checkField = IPPseudoChecksum(&ipHdr->saddr, &newAddr,
tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,
ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);
@@ -1583,7 +1600,8 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
if (*addrField != newAddr) {
UINT32 oldAddr = *addrField;
- if ((checkField && *checkField != 0) && (!l4Offload || !isTx)) {
+ if ((checkField && *checkField != 0) &&
+ (!l4Offload || (!isTx && !preservePseudoChecksum))) {
/* Recompute total checksum. */
*checkField = ChecksumUpdate32(*checkField, oldAddr,
newAddr);
@@ -1597,7 +1615,8 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
}
if (portField && *portField != newPort) {
- if ((checkField) && (!l4Offload || !isTx)) {
+ if ((checkField) &&
+ (!l4Offload || (!isTx && !preservePseudoChecksum))) {
/* Recompute total checksum. */
*checkField = ChecksumUpdate16(*checkField, *portField,
newPort);