Thanks for taking care of the comments. Acked-by: Nithin Raju <nit...@vmware.com>
-----Original Message----- From: dev <dev-boun...@openvswitch.org> on behalf of Alin Serdean <aserd...@cloudbasesolutions.com> Date: Wednesday, February 10, 2016 at 5:38 PM To: "dev@openvswitch.org" <dev@openvswitch.org> Subject: [ovs-dev] [PATCH] datapath-windows: Refactor sofware offloads and mss >The purpose of this patch is to refactor the software offloads found in >the VXLAN and GRE code and also to refactor how the maximmum segment >size for a given NBL is obtained. > >This patch introduces two functions OvsApplySWChecksumOnNB and >OVSGetTcpMSS. > >OVSGetTcpMSS - will return the mss found in a given NBL. > >OvsApplySWChecksumOnNB - will compute and set software offloads for a >given > NBL. > >Signed-off-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> >Acked-by: Sorin Vinturis <svinturis at coudbasesolutions.com> >--- >v2: Move new functions to Checksum.c/h. Rename Checksum.c/h to >Offload.c/h.4 > Add Acked-by. >--- >--- > datapath-windows/automake.mk | 4 +- > datapath-windows/ovsext/Actions.c | 6 +- > datapath-windows/ovsext/BufferMgmt.c | ext/BufferMgmt.h | 16 +- > datapath-windows/ovsext/Checksum.c | 596 ---------------------------- > datapath-windows/ovsext/Checksum.h | 39 -- > datapath-windows/ovsext/Gre.c | 85 +--- > datapath-windows/ovsext/Offload.c | 703 >+++++++++++++++++++++++++++++++++ > datapath-windows/ovsext/Offload.h | 47 +++ > datapath-windows/ovsext/Stt.c | 24 +- > datapath-windows/ovsext/User.c | 20 +- > datapath-windows/ovsext/Vxlan.c | 98 +---- > datapath-windows/ovsext/ovsext.vcxproj | 4 +- > 13 files changed, 816 insertions(+), 841 deetions(-) > delete mode 100644 datapath-windows/ovsext/Checksum.c > delete mode 100644 datapath-windows/ovsext/Checksum.h > create mode 100644 datapath-windows/ovsext/Offload.c > create mode 100644 datapath-windows/ovsext/Offload.h > >diff --git a/datapath-windows/automake.mk b/datapath-windows/automake.mk >index fd22218..f29f548 utomake.mk >+++ b/datapath-windows/automake.mk >@@ -12,8 +12,6 @@ EXTRA_DIST += \ > datapath-windows/ovsext/Atomic.h \ > datapath-windows/ovsext/BufferMgmt.c \ > daapath-windows/ovsext/BufferMgmt.h \ >- datapath-windows/ovsext/Checksum.c \ >- datapath-windows/ovsext/Checksum.h \ > datapath-windows/ovsext/Datapath.c \ > datapath-windows/ovsext/Datapath.h \ > datapath-windows/ovsext/Debug.c \ >@@ -39,6 +37,8 @@ EXTRA_DIST += \ > datapath-windows/ovsext/Netlink/NetlinkBuf.h \ > datlinkError.h \ > datapath-windows/ovsext/Netlink/NetlinkProto.h \ >+ datapath-windows/ovsext/Offload.c \ >+ datapath-windows/ovsext/Offload.h \ > datapath-windows/ovsext/Oid.c \ > datapath-windows/ovsext/Oid.h \ > datapath-windows/ovsext/PacketIO.c \ >diff --git a/datapath-windows/ovsextActions.c >b/datapath-windows/ovsext/Actions.c >index 8e41b74..5a04541 100644 >--- a/datapath-windows/ovsext/Actions.c >+++ b/datapath-windows/ovsext/Actions.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2014 VMware, Inc. >+ * Copyright (c) 2014, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@ "precomp.h" > >-#include "Checksum.h" >+#include "Debug.h" > #include "Event.h" > #include "Flow.h" > #include "Gre.h" > #include "Mpls.h" > #include "NetProto.h" >+include "Offload.h" > #include "PacketIO.h" > #include "Stt.h" > #include "Switch.h" >@@ -33,7 +34,6 @@ > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_ACTION >-#include "Debug.h" > > typedef struct _OVS_ACTION_STATS { > UINT64 rxGre; >diff --git a/datapath-windows/ovsext/BufferMgmt.c >b/datapath-windows/ovsext/BufferMgmt.c >index 7ec073b..3189e9b 100644 >--- a/datapath-windows/ovh-windows/ovsext/BufferMgmt.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2014 VMware, Inc. >+ * Copyright (c) 2014, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the Licese. >@@ -77,18 +77,19 @@ > */ > > #include "precomp.h" >+#include "Debug.h" >+#include "Flw.h" >+#include "Offload.h" >+#include "NetProto.h" >+#include "PacketParser.h" > #include "Switch.h" >+#include "Vport.h" > > #ifdef OVS_DBG_MOD > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_BUFMGMT >-#include "Debug.h" >-#include "NetProto.h" >-#include "Flow.h" >-#include "Checksum.h" >-#include "PacketParser.h" >-#include "Vport.h" >+ > > /* > * >-------------------------------------------------------------------------- >diff --git a/datapath-windows/ovsext/BufferMgmt.h >b/datapath-windows/ovsext/BufferMgmt.h >index 79abc3d..11a05b2 100644 >--- a/datapath-windows/ovsext/BufferMgmt.h >+++ b/datapath-windows/ovsext/BufferMgmt.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2014 VMware, Inc. >+ * Copyright (c) 2014, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@@ -63,7 +63,6 @@ typedef union _OVS_BUFFER_CONTEXT { > UINT64 value[MEM_ALIGN_SIZE(16) >> 3]; > } OVS_BUFFER_CONTEXT, *POVS_BUFFER_CONTEXT; > >- > typedef struct _OVS_NBL_POOL { > NDIS_SWITCH_CONTEXT ndisContext; > NDIS_HANDLE ndisHandle; >@@ -83,11 +82,13 @@ typedef struct _OVS_NBL_POOL { > > > NDIS_STATUS OvsInitBufferPool(PVOID context); >+ > VOID OvsCleanupBufferPool(PVOID context); > > PNET_BUFFER_LIST OvsAllocateFixSizeNBL(PVOID context, > UINT32 size, > UINT32 headRoom); >+ > PNET_BUFFER_LIST OvsAllocateVariableSizeNBL(PVOID context, > UINT32 size, > UINT32 headRoom); >@@ -106,20 +107,27 @@ PNET_BUFFER_LIST OvsPartialCopyToMultipleNBLs(PVOID >context, > UINT32 copySize, > UINT32 headRoom, > BOOLEAN copyNblInfo); >+ > PNET_BUFFER_LIST OvsFullCopyNBL(PVOID context, PNET_BUFFER_LIST nbl, > UINT32 headRoom, BOOLEAN copyNblInfo); >+ > PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID context, > PNET_BUFFER_LIST nbl, > POVS_PACKET_HDR_INFO hdrInfo, > UINT32 MSS, > UINT32 headRoom); >+ > PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context, > PVOID buffer, > ULONG length); >-PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, >- PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo); >+ >+PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, >PNET_BUFFER_LIST nbl, >+ UINT32 headRoom, >+ BOOLEAN copyNblInfo); >+ > PNET_BUFFER_LIST OvsCompleteNBL(PVOID context, PNET_BUFFER_LIST nbl, > BOOLEAN updateRef); >+ > NDIS_STATUS OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 portNo); > > NDIS_STATUS OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 *portNo); >diff --git a/datapath-windows/ovsext/Checksum.c >b/datapath-windows/ovsext/Checksum.c >deleted file mode 100644 >index 5d9b035..0000000 >--- a/datapath-windows/ovsext/Checksum.c >+++ /dev/null >@@ -1,596 +0,0 @@ >-/* >- * Copyright (c) 2014 VMware, Inc. >- * >- * Licensed under the Apache License, Version 2.0 (the "License"); >- * you may not use this file except in compliance with the License. >- * You may obtain a copy of the License at: >- * >- * http://www.apache.org/licenses/LICENSE-2.0 >- * >- * Unless required by applicable law or agreed to in writing, software >- * distributed under the License is distributed on an "AS IS" BASIS, >- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >implied. >- * See the License for the specific language governing permissions and >- * limitations under the License. >- */ >- >-#include "precomp.h" >-#include "Checksum.h" >-#include "Flow.h" >- >-#ifdef OVS_DBG_MOD >-#undef OVS_DBG_MOD >-#endif >-#define OVS_DBG_MOD OVS_DBG_CHECKSUM >-#include "Debug.h" >-#include "PacketParser.h" >- >-#ifndef htons >-#define htons(_x) (((UINT16)(_x) >> 8) + (((UINT16)(_x) << 8) & 0xff00)) >-#endif >- >-#ifndef swap64 >-#define swap64(_x) ((((UINT64)(_x) >> 8) & 0x00ff00ff00ff00ff) + \ >- (((UINT64)(_x) << 8) & 0xff00ff00ff00ff00)) >-#endif >- >-#define fold64(_x) \ >- _x = ((_x) >> 32) + ((_x) & 0xffffffff); \ >- _x = (UINT32)(((_x) >> 32) + (_x)); \ >- _x = ((_x) >> 16) + ((_x) & 0xffff); \ >- _x = (UINT16)(((_x) >> 16) + (_x)) >- >-#define fold32(_x) \ >- _x = ((_x) >> 16) + ((_x) & 0xffff); \ >- _x = (UINT16)(((_x) >> 16) + (_x)) >- >- >-/* >- >*------------------------------------------------------------------------- >--- >- * CalculateOnesComplement -- >- * >- * Given the start address and buffer length, calculate the 1's >complement >- * This routine can be used when multiple buffers are used for a >packets. >- * >- * PLEASE NOTE, even though the last parameter is UINT64, but the >assumption >- * is it will not overflowed after adding the extra data. >- * ------------------------------------------------ >- * >- * Result: >- * As name indicate, the final data is not 1's complemnent >- >*------------------------------------------------------------------------- >--- >- */ >-UINT64 >-CalculateOnesComplement(UINT8 *start, >- UINT16 totalLength, >- UINT64 initial, >- BOOLEAN isEvenStart) >-{ >- UINT64 sum = 0, val; >- UINT64 *src = (UINT64 *)start; >- while (totalLength > 7) { >- val = *src; >- sum += val; >- if (sum < val) sum++; >- src++; >- totalLength -= 8; >- } >- >- start = (UINT8 *)src; >- >- if (totalLength > 3) { >- UINT32 val = *(UINT32 *)start; >- sum += val; >- if (sum < val) sum++; >- start += 4; >- totalLength -= 4; >- } >- >- if (totalLength > 1) { >- UINT16 val = *(UINT16 *)start; >- sum += val; >- if (sum < val) sum++; >- start += 2; >- totalLength -= 2; >- } >- >- if (totalLength > 0) { >- UINT8 val = *start; >- sum += val; >- if (sum < val) sum++; >- start += 1; >- totalLength -= 1; >- } >- ASSERT(totalLength == 0); >- >- if (!isEvenStart) { >- sum = _byteswap_uint64(sum); >- } >- >- sum += initial; >- if (sum < initial) sum++; >- >- return sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * CalculateChecksum -- >- * >- * Given the start point, and length, calculate the checksum >- * as 1's complement of 1's comlement. >- * >- * This assume the checksum field is initailized properly. >- * >- * Input Parameter: >- * ptr: point to the data to be checksumed >- * totalLength: total length of the data >- * initial: inital value to remit the checksum. Please note this >- * value should be network byte order value. >- * >- * The last parameter may be useful where you don't want to set >- * checksum field to zero, in that case you can pass ~checksum, >- * this is equivalent of set checksum field to zero. >- * >- * Result: >- * The result can be assigned to checksum field directly. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-CalculateChecksum(UINT8 *ptr, >- UINT16 totalLength, >- UINT16 initial) >-{ >- UINT64 sum = CalculateOnesComplement(ptr, totalLength, initial, >TRUE); >- fold64(sum); >- return (UINT16)~sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * CopyAndCalculateOnesComplement -- >- * >- * Given the start address and buffer length, calculate the 1's >complement >- * at same time, copt the data from src to dst. >- * >- * This routine can be used when multiple buffers are used for a >packets. >- * >- * PLEASE NOTE, even though the last parameter is UINT64, but the >assumption >- * is it will not overflowed after adding the extra data. >- * ------------------------------------------------ >- * >- * Result: >- * As name indicate, the final data is not 1's complemnent >- >*------------------------------------------------------------------------- >--- >- */ >-UINT64 >-CopyAndCalculateOnesComplement(UINT8 *dst, >- UINT8 *src, >- UINT16 length, >- UINT64 initial, >- BOOLEAN isEvenStart) >-{ >- UINT64 sum =0, val; >- UINT64 *src64, *dst64; >- union { >- UINT32 val; >- UINT8 b8[4]; >- } tmp; >- >- src64 = (UINT64 *)src; >- dst64 = (UINT64 *)dst; >- >- while (length > 7) { >- val = *src64; >- *dst64 = val; >- sum += (val >> 32) + (val & 0xffffffff); >- src64++; >- dst64++; >- length -= 8; >- } >- >- if (length > 3) { >- val = *(UINT32 *)src64; >- *(UINT32 *)dst64 = (UINT32)val; >- sum += (UINT32)val; >- dst64 = (UINT64 *)((UINT8 *)dst64 + 4); >- src64 = (UINT64 *)((UINT8 *)src64 + 4); >- length -= 4; >- } >- src = (UINT8 *)src64; >- dst = (UINT8 *)dst64; >- tmp.val = 0; >- switch (length) { >- case 3: >- dst[2] = src[2]; >- tmp.b8[2] = src[2]; >- case 2: >- dst[1] = src[1]; >- tmp.b8[1] = src[1]; >- case 1: >- dst[0] = src[0]; >- tmp.b8[0] = src[0]; >- sum += tmp.val; >- } >- sum = (isEvenStart ? sum : swap64(sum)) + initial; >- return sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * CopyAndCalculateChecksum -- >- * >- * This is similar to CalculateChecksum, except it will also copy data >to >- * destination address. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-CopyAndCalculateChecksum(UINT8 *dst, >- UINT8 *src, >- UINT16 length, >- UINT16 initial) >-{ >- >- UINT64 sum = CopyAndCalculateOnesComplement(dst, src, length, >initial, >- TRUE); >- fold64(sum); >- return (UINT16)~sum; >-} >- >- >-/* >- >*------------------------------------------------------------------------- >--- >- * IPChecksum -- >- * >- * Give IP header, calculate the IP checksum. >- * We assume IP checksum field is initialized properly >- * >- * Input Pramater: >- * ipHdr: IP header start point >- * length: IP header length (potentially include IP options) >- * initial: same as CalculateChecksum >- * >- * Result: >- * The result is already 1's complement, so can be assigned >- * to checksum field directly >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-IPChecksum(UINT8 *ipHdr, >- UINT16 length, >- UINT16 initial) >-{ >- UINT32 sum = initial; >- UINT16 *ptr = (UINT16 *)ipHdr; >- ASSERT((length & 0x3) == 0); >- while (length > 1) { >- sum += ptr[0]; >- ptr++; >- length -= 2; >- } >- fold32(sum); >- return (UINT16)~sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * IPPseudoChecksum -- >- * >- * Give src and dst IP address, protocol value and total >- * upper layer length(not include IP header, but include >- * upller layer protocol header, for example it include >- * TCP header for TCP checksum), calculate the pseudo >- * checksum, please note this checksum is just 1's complement >- * addition. >- * >- * Input Parameter: >- * src: please note it is in network byte order >- * dst: same as src >- * protocol: protocol value in IP header >- * totalLength: total length of upper layer data including >- * header. >- * >- * Result: >- * >- * This value should be put in TCP checksum field before >- * calculating TCP checksum using CalculateChecksum with >- * initial value of 0. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-IPPseudoChecksum(UINT32 *src, >- UINT32 *dst, >- UINT8 protocol, >- UINT16 totalLength) >-{ >- UINT32 sum = (UINT32)htons(totalLength) + htons(protocol); >- sum += (*src >> 16) + (*src & 0xffff); >- sum += (*dst >> 16) + (*dst & 0xffff); >- fold32(sum); >- return (UINT16)sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * IPv6PseudoChecksum -- >- * >- * Given IPv6 src and dst address, upper layer protocol and total >- * upper layer protocol data length including upper layer header >- * part, calculate the pseudo checksum for upper layer protocol >- * checksum. >- * >- * please note this checksum is just 1's complement addition. >- * >- * Input Parameter: >- * src: src IPv6 address in network byte order >- * dst: dst IPv6 address. >- * protocol: upper layer protocol >- * totalLength: total length of upper layer data. Please note this is >- * in host byte order. >- * >- * Result: >- * >- * Place in upper layer checksum field before calculate upper layer >- * checksum. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-IPv6PseudoChecksum(UINT32 *src, >- UINT32 *dst, >- UINT8 protocol, >- UINT16 totalLength) >-{ >- UINT64 sum = (UINT32)htons(totalLength) + htons(protocol); >- sum += (UINT64)src[0] + src[1] + src[2] + src[3]; >- sum += (UINT64)dst[0] + dst[1] + dst[2] + dst[3]; >- fold64(sum); >- return (UINT16)sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * ChecksumUpdate32 -- >- * >- * Given old checksum value (as it is in checksum field), >- * prev value of the relevant field in network byte order >- * new value of the relevant field in the network byte order >- * calculate the new checksum. >- * Please check relevant RFC for reference. >- * >- * Input Pramater: >- * oldSum: old checksum value in checksum field >- * prev: previous value of relevant 32 bit feld in network >- * byte order. >- * new: new value of the relevant 32 bit field in network >- * byte order. >- * >- * Result: >- * new checksum value to be placed in the checksum field. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-ChecksumUpdate32(UINT16 oldSum, >- UINT32 prev, >- UINT32 newValue) >-{ >- UINT32 sum = ~prev; >- sum = (sum >> 16) + (sum & 0xffff); >- sum += (newValue >> 16) + (newValue & 0xffff); >- sum += (UINT16)~oldSum; >- fold32(sum); >- return (UINT16)~sum; >-} >- >- >-/* >- >*------------------------------------------------------------------------- >--- >- * ChecksumUpdate16 -- >- * >- * Given old checksum value (as it is in checksum field), >- * prev value of the relevant field in network byte order >- * new value of the relevant field in the network byte order >- * calculate the new checksum. >- * Please check relevant RFC for reference. >- * >- * Input Pramater: >- * oldSum: old checksum value in checksum field >- * prev: previous value of relevant 32 bit feld in network >- * byte order. >- * new: new value of the relevant 32 bit field in network >- * byte order. >- * >- * Result: >- * new checksum value to be placed in the checksum field. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-ChecksumUpdate16(UINT16 oldSum, >- UINT16 prev, >- UINT16 newValue) >-{ >- UINT32 sum = (UINT16)~oldSum; >- sum += (UINT32)((UINT16)~prev) + newValue; >- fold32(sum); >- return (UINT16)~sum; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * CalculateChecksumNB -- >- * >- * Calculates checksum over a length of bytes contained in an NB. >- * >- * nb : NB which contains the packet bytes. >- * csumDataLen : Length of bytes to be checksummed. >- * offset : offset to the first bytes of the data stream to be >- * checksumed. >- * >- * Result: >- * return 0, if there is a failure. >- >*------------------------------------------------------------------------- >--- >- */ >-UINT16 >-CalculateChecksumNB(const PNET_BUFFER nb, >- UINT16 csumDataLen, >- UINT32 offset) >-{ >- ULONG mdlLen; >- UINT16 csLen; >- PUCHAR src; >- UINT64 csum = 0; >- PMDL currentMdl; >- ULONG firstMdlLen; >- /* Running count of bytes in remainder of the MDLs including >current. */ >- ULONG packetLen; >- BOOLEAN swapEnd = 1 & csumDataLen; >- >- if ((nb == NULL) || (csumDataLen == 0) >- || (offset >= NET_BUFFER_DATA_LENGTH(nb)) >- || (offset + csumDataLen > NET_BUFFER_DATA_LENGTH(nb))) { >- OVS_LOG_ERROR("Invalid parameters - csum length %u, offset %u," >- "pkt%s len %u", csumDataLen, offset, nb? "":"(null)", >- nb? NET_BUFFER_DATA_LENGTH(nb) : 0); >- return 0; >- } >- >- currentMdl = NET_BUFFER_CURRENT_MDL(nb); >- packetLen = NET_BUFFER_DATA_LENGTH(nb); >- firstMdlLen = >- MmGetMdlByteCount(currentMdl) - >NET_BUFFER_CURRENT_MDL_OFFSET(nb); >- >- firstMdlLen = MIN(firstMdlLen, packetLen); >- if (offset < firstMdlLen) { >- src = (PUCHAR) MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >- if (!src) { >- return 0; >- } >- src += (NET_BUFFER_CURRENT_MDL_OFFSET(nb) + offset); >- mdlLen = firstMdlLen - offset; >- packetLen -= firstMdlLen; >- ASSERT((INT)packetLen >= 0); >- } else { >- offset -= firstMdlLen; >- packetLen -= firstMdlLen; >- ASSERT((INT)packetLen >= 0); >- currentMdl = NDIS_MDL_LINKAGE(currentMdl); >- mdlLen = MmGetMdlByteCount(currentMdl); >- mdlLen = MIN(mdlLen, packetLen); >- >- while (offset >= mdlLen) { >- offset -= mdlLen; >- packetLen -= mdlLen; >- ASSERT((INT)packetLen >= 0); >- currentMdl = NDIS_MDL_LINKAGE(currentMdl); >- mdlLen = MmGetMdlByteCount(currentMdl); >- mdlLen = MIN(mdlLen, packetLen); >- } >- >- src = (PUCHAR)MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >- if (!src) { >- return 0; >- } >- >- src += offset; >- mdlLen -= offset; >- } >- >- while (csumDataLen && (currentMdl != NULL)) { >- ASSERT(mdlLen < 65536); >- csLen = MIN((UINT16) mdlLen, csumDataLen); >- >- csum = CalculateOnesComplement(src, csLen, csum, !(1 & >csumDataLen)); >- fold64(csum); >- >- csumDataLen -= csLen; >- currentMdl = NDIS_MDL_LINKAGE(currentMdl); >- if (csumDataLen && currentMdl) { >- src = MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >- if (!src) { >- return 0; >- } >- >- mdlLen = MmGetMdlByteCount(currentMdl); >- mdlLen = MIN(mdlLen, packetLen); >- /* packetLen does not include the current MDL from here on. >*/ >- packetLen -= mdlLen; >- ASSERT((INT)packetLen >= 0); >- } >- } >- >- fold64(csum); >- ASSERT(csumDataLen == 0); >- ASSERT((csum & ~0xffff) == 0); >- csum = (UINT16)~csum; >- if (swapEnd) { >- return _byteswap_ushort((UINT16)csum); >- } >- return (UINT16)csum; >-} >- >-/* >- * >-------------------------------------------------------------------------- >- * OvsValidateIPChecksum >- * >-------------------------------------------------------------------------- >- */ >-NDIS_STATUS >-OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, >- POVS_PACKET_HDR_INFO hdrInfo) >-{ >- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; >- uint16_t checksum, hdrChecksum; >- struct IPHdr ip_storage; >- const IPHdr *ipHdr; >- >- if (!hdrInfo->isIPv4) { >- return NDIS_STATUS_SUCCESS; >- } >- >- /* First check if NIC has indicated checksum failure. */ >- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >- >TcpIpChecksumNetBufferListInfo); >- if (csumInfo.Receive.IpChecksumFailed) { >- return NDIS_STATUS_FAILURE; >- } >- >- /* Next, check if the NIC did not validate the RX checksum. */ >- if (!csumInfo.Receive.IpChecksumSucceeded) { >- ipHdr = OvsGetIp(curNbl, hdrInfo->l3Offset, &ip_storage); >- if (ipHdr) { >- ip_storage = *ipHdr; >- hdrChecksum = ipHdr->check; >- ip_storage.check = 0; >- checksum = IPChecksum((uint8 *)&ip_storage, ipHdr->ihl * 4, >0); >- if (checksum != hdrChecksum) { >- return NDIS_STATUS_FAILURE; >- } >- } >- } >- return NDIS_STATUS_SUCCESS; >-} >- >-/* >- >*------------------------------------------------------------------------- >--- >- * OvsValidateUDPChecksum >- >*------------------------------------------------------------------------- >--- >- */ >-NDIS_STATUS >-OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, BOOLEAN udpCsumZero) >-{ >- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; >- >- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >TcpIpChecksumNetBufferListInfo); >- >- if (udpCsumZero) { >- /* Zero is valid checksum. */ >- csumInfo.Receive.UdpChecksumFailed = 0; >- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = >csumInfo.Value; >- return NDIS_STATUS_SUCCESS; >- } >- >- /* First check if NIC has indicated UDP checksum failure. */ >- if (csumInfo.Receive.UdpChecksumFailed) { >- return NDIS_STATUS_INVALID_PACKET; >- } >- >- return NDIS_STATUS_SUCCESS; >-} >diff --git a/datapath-windows/ovsext/Checksum.h >b/datapath-windows/ovsext/Checksum.h >deleted file mode 100644 >index 2378a32..0000000 >--- a/datapath-windows/ovsext/Checksum.h >+++ /dev/null >@@ -1,39 +0,0 @@ >-/* >- * Copyright (c) 2014 VMware, Inc. >- * >- * Licensed under the Apache License, Version 2.0 (the "License"); >- * you may not use this file except in compliance with the License. >- * You may obtain a copy of the License at: >- * >- * http://www.apache.org/licenses/LICENSE-2.0 >- * >- * Unless required by applicable law or agreed to in writing, software >- * distributed under the License is distributed on an "AS IS" BASIS, >- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >implied. >- * See the License for the specific language governing permissions and >- * limitations under the License. >- */ >- >-#ifndef __CHECKSUM_H_ >-#define __CHECKSUM_H_ 1 >- >-typedef union _OVS_PACKET_HDR_INFO *POVS_PACKET_HDR_INFO; >- >-UINT16 CalculateChecksum(UINT8 *ptr, UINT16 length, UINT16 initial); >-UINT16 CopyAndCalculateChecksum(UINT8 *dst, UINT8 *src, UINT16 length, >- UINT16 initial); >-UINT16 IPChecksum(UINT8 *ipHdr, UINT16 length, UINT16 initial); >-UINT16 IPPseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, >- UINT16 totalLength); >-UINT16 IPv6PseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, >- UINT16 totalLength); >-UINT16 ChecksumUpdate32(UINT16 oldSum, UINT32 prev, UINT32 newValue); >-UINT16 ChecksumUpdate16(UINT16 oldSum, UINT16 prev, UINT16 newValue); >-UINT16 CalculateChecksumNB(const PNET_BUFFER nb, UINT16 csumDataLen, >- UINT32 offset); >-NDIS_STATUS OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, >- POVS_PACKET_HDR_INFO hdrInfo); >-NDIS_STATUS OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, >- BOOLEAN udpCsumZero); >- >-#endif /* __CHECKSUM_H_ */ >diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c >index 5abd4a4..cb41593 100644 >--- a/datapath-windows/ovsext/Gre.c >+++ b/datapath-windows/ovsext/Gre.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2015 Cloudbase Solutions Srl >+ * Copyright (c) 2015, 2016 Cloudbase Solutions Srl > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@@ -17,11 +17,12 @@ > #include "precomp.h" > > #include "Atomic.h" >-#include "Checksum.h" >+#include "Debug.h" > #include "Flow.h" > #include "Gre.h" > #include "IpHelper.h" > #include "NetProto.h" >+#include "Offload.h" > #include "PacketIO.h" > #include "PacketParser.h" > #include "Switch.h" >@@ -33,7 +34,6 @@ > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_GRE >-#include "Debug.h" > > static NDIS_STATUS > OvsDoEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, >@@ -147,21 +147,8 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport, > packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > if (layers->isTcp) { >- NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; >- >- tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >- >TcpLargeSendNetBufferListInfo); >- switch (tsoInfo.Transmit.Type) { >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: >- mss = tsoInfo.LsoV1Transmit.MSS; >- break; >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: >- mss = tsoInfo.LsoV2Transmit.MSS; >- break; >- default: >- OVS_LOG_ERROR("Unknown LSO transmit type:%d", >- tsoInfo.Transmit.Type); >- } >+ mss = OVSGetTcpMSS(curNbl); >+ > OVS_LOG_TRACE("MSS %u packet len %u", mss, > packetLength); > if (mss) { >@@ -188,71 +175,15 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport, > OVS_LOG_ERROR("Unable to copy NBL"); > return NDIS_STATUS_FAILURE; > } >- /* >- * To this point we do not have GRE hardware offloading. >- * Apply defined checksums >- */ >- curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); >- curMdl = NET_BUFFER_CURRENT_MDL(curNb); >- bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, >- >LowPagePriority); >- if (!bufferStart) { >- status = NDIS_STATUS_RESOURCES; >- goto ret_error; >- } > > NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, > >TcpIpChecksumNetBufferListInfo); > >- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); >- >- if (layers->isIPv4) { >- IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); >- >- if (csumInfo.Transmit.IpHeaderChecksum) { >- ip->check = 0; >- ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); >- } >- >- if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >- tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >- IPPROTO_TCP, csumLength); >- tcp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >- udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >- IPPROTO_UDP, csumLength); >- udp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } >- } else if (layers->isIPv6) { >- IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); >- >- if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >- tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >- (UINT32 *) &ip->daddr, >- IPPROTO_TCP, csumLength); >- tcp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >- udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >- (UINT32 *) &ip->daddr, >- IPPROTO_UDP, csumLength); >- udp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } >+ status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo); >+ if (status != NDIS_STATUS_SUCCESS) { >+ goto ret_error; > } >- /* Clear out TcpIpChecksumNetBufferListInfo flag */ >- NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = >0; > } > > curNbl = *newNbl; >diff --git a/datapath-windows/ovsext/Offload.c >b/datapath-windows/ovsext/Offload.c >new file mode 100644 >index 0000000..1e43a9e >--- /dev/null >+++ b/datapath-windows/ovsext/Offload.c >@@ -0,0 +1,703 @@ >+/* >+ * Copyright (c) 2014, 2016 VMware, Inc. >+ * >+ * Licensed under the Apache License, Version 2.0 (the "License"); >+ * you may not use this file except in compliance with the License. >+ * You may obtain a copy of the License at: >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+#include "precomp.h" >+#include "Debug.h" >+#include "Flow.h" >+#include "Offload.h" >+#include "PacketParser.h" >+ >+#ifdef OVS_DBG_MOD >+#undef OVS_DBG_MOD >+#endif >+#define OVS_DBG_MOD OVS_DBG_CHECKSUM >+ >+#ifndef htons >+#define htons(_x) (((UINT16)(_x) >> 8) + (((UINT16)(_x) << 8) & 0xff00)) >+#endif >+ >+#ifndef swap64 >+#define swap64(_x) ((((UINT64)(_x) >> 8) & 0x00ff00ff00ff00ff) + \ >+ (((UINT64)(_x) << 8) & 0xff00ff00ff00ff00)) >+#endif >+ >+#define fold64(_x) \ >+ _x = ((_x) >> 32) + ((_x) & 0xffffffff); \ >+ _x = (UINT32)(((_x) >> 32) + (_x)); \ >+ _x = ((_x) >> 16) + ((_x) & 0xffff); \ >+ _x = (UINT16)(((_x) >> 16) + (_x)) >+ >+#define fold32(_x) \ >+ _x = ((_x) >> 16) + ((_x) & 0xffff); \ >+ _x = (UINT16)(((_x) >> 16) + (_x)) >+ >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * CalculateOnesComplement -- >+ * >+ * Given the start address and buffer length, calculate the 1's >complement >+ * This routine can be used when multiple buffers are used for a >packets. >+ * >+ * PLEASE NOTE, even though the last parameter is UINT64, but the >assumption >+ * is it will not overflowed after adding the extra data. >+ * ------------------------------------------------ >+ * >+ * Result: >+ * As name indicate, the final data is not 1's complemnent >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT64 >+CalculateOnesComplement(UINT8 *start, >+ UINT16 totalLength, >+ UINT64 initial, >+ BOOLEAN isEvenStart) >+{ >+ UINT64 sum = 0, val; >+ UINT64 *src = (UINT64 *)start; >+ while (totalLength > 7) { >+ val = *src; >+ sum += val; >+ if (sum < val) sum++; >+ src++; >+ totalLength -= 8; >+ } >+ >+ start = (UINT8 *)src; >+ >+ if (totalLength > 3) { >+ UINT32 val = *(UINT32 *)start; >+ sum += val; >+ if (sum < val) sum++; >+ start += 4; >+ totalLength -= 4; >+ } >+ >+ if (totalLength > 1) { >+ UINT16 val = *(UINT16 *)start; >+ sum += val; >+ if (sum < val) sum++; >+ start += 2; >+ totalLength -= 2; >+ } >+ >+ if (totalLength > 0) { >+ UINT8 val = *start; >+ sum += val; >+ if (sum < val) sum++; >+ start += 1; >+ totalLength -= 1; >+ } >+ ASSERT(totalLength == 0); >+ >+ if (!isEvenStart) { >+ sum = _byteswap_uint64(sum); >+ } >+ >+ sum += initial; >+ if (sum < initial) sum++; >+ >+ return sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * CalculateChecksum -- >+ * >+ * Given the start point, and length, calculate the checksum >+ * as 1's complement of 1's comlement. >+ * >+ * This assume the checksum field is initailized properly. >+ * >+ * Input Parameter: >+ * ptr: point to the data to be checksumed >+ * totalLength: total length of the data >+ * initial: inital value to remit the checksum. Please note this >+ * value should be network byte order value. >+ * >+ * The last parameter may be useful where you don't want to set >+ * checksum field to zero, in that case you can pass ~checksum, >+ * this is equivalent of set checksum field to zero. >+ * >+ * Result: >+ * The result can be assigned to checksum field directly. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+CalculateChecksum(UINT8 *ptr, >+ UINT16 totalLength, >+ UINT16 initial) >+{ >+ UINT64 sum = CalculateOnesComplement(ptr, totalLength, initial, >TRUE); >+ fold64(sum); >+ return (UINT16)~sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * CopyAndCalculateOnesComplement -- >+ * >+ * Given the start address and buffer length, calculate the 1's >complement >+ * at same time, copt the data from src to dst. >+ * >+ * This routine can be used when multiple buffers are used for a >packets. >+ * >+ * PLEASE NOTE, even though the last parameter is UINT64, but the >assumption >+ * is it will not overflowed after adding the extra data. >+ * ------------------------------------------------ >+ * >+ * Result: >+ * As name indicate, the final data is not 1's complemnent >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT64 >+CopyAndCalculateOnesComplement(UINT8 *dst, >+ UINT8 *src, >+ UINT16 length, >+ UINT64 initial, >+ BOOLEAN isEvenStart) >+{ >+ UINT64 sum =0, val; >+ UINT64 *src64, *dst64; >+ union { >+ UINT32 val; >+ UINT8 b8[4]; >+ } tmp; >+ >+ src64 = (UINT64 *)src; >+ dst64 = (UINT64 *)dst; >+ >+ while (length > 7) { >+ val = *src64; >+ *dst64 = val; >+ sum += (val >> 32) + (val & 0xffffffff); >+ src64++; >+ dst64++; >+ length -= 8; >+ } >+ >+ if (length > 3) { >+ val = *(UINT32 *)src64; >+ *(UINT32 *)dst64 = (UINT32)val; >+ sum += (UINT32)val; >+ dst64 = (UINT64 *)((UINT8 *)dst64 + 4); >+ src64 = (UINT64 *)((UINT8 *)src64 + 4); >+ length -= 4; >+ } >+ src = (UINT8 *)src64; >+ dst = (UINT8 *)dst64; >+ tmp.val = 0; >+ switch (length) { >+ case 3: >+ dst[2] = src[2]; >+ tmp.b8[2] = src[2]; >+ case 2: >+ dst[1] = src[1]; >+ tmp.b8[1] = src[1]; >+ case 1: >+ dst[0] = src[0]; >+ tmp.b8[0] = src[0]; >+ sum += tmp.val; >+ } >+ sum = (isEvenStart ? sum : swap64(sum)) + initial; >+ return sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * CopyAndCalculateChecksum -- >+ * >+ * This is similar to CalculateChecksum, except it will also copy data >to >+ * destination address. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+CopyAndCalculateChecksum(UINT8 *dst, >+ UINT8 *src, >+ UINT16 length, >+ UINT16 initial) >+{ >+ >+ UINT64 sum = CopyAndCalculateOnesComplement(dst, src, length, >initial, >+ TRUE); >+ fold64(sum); >+ return (UINT16)~sum; >+} >+ >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * IPChecksum -- >+ * >+ * Give IP header, calculate the IP checksum. >+ * We assume IP checksum field is initialized properly >+ * >+ * Input Pramater: >+ * ipHdr: IP header start point >+ * length: IP header length (potentially include IP options) >+ * initial: same as CalculateChecksum >+ * >+ * Result: >+ * The result is already 1's complement, so can be assigned >+ * to checksum field directly >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+IPChecksum(UINT8 *ipHdr, >+ UINT16 length, >+ UINT16 initial) >+{ >+ UINT32 sum = initial; >+ UINT16 *ptr = (UINT16 *)ipHdr; >+ ASSERT((length & 0x3) == 0); >+ while (length > 1) { >+ sum += ptr[0]; >+ ptr++; >+ length -= 2; >+ } >+ fold32(sum); >+ return (UINT16)~sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * IPPseudoChecksum -- >+ * >+ * Give src and dst IP address, protocol value and total >+ * upper layer length(not include IP header, but include >+ * upller layer protocol header, for example it include >+ * TCP header for TCP checksum), calculate the pseudo >+ * checksum, please note this checksum is just 1's complement >+ * addition. >+ * >+ * Input Parameter: >+ * src: please note it is in network byte order >+ * dst: same as src >+ * protocol: protocol value in IP header >+ * totalLength: total length of upper layer data including >+ * header. >+ * >+ * Result: >+ * >+ * This value should be put in TCP checksum field before >+ * calculating TCP checksum using CalculateChecksum with >+ * initial value of 0. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+IPPseudoChecksum(UINT32 *src, >+ UINT32 *dst, >+ UINT8 protocol, >+ UINT16 totalLength) >+{ >+ UINT32 sum = (UINT32)htons(totalLength) + htons(protocol); >+ sum += (*src >> 16) + (*src & 0xffff); >+ sum += (*dst >> 16) + (*dst & 0xffff); >+ fold32(sum); >+ return (UINT16)sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * IPv6PseudoChecksum -- >+ * >+ * Given IPv6 src and dst address, upper layer protocol and total >+ * upper layer protocol data length including upper layer header >+ * part, calculate the pseudo checksum for upper layer protocol >+ * checksum. >+ * >+ * please note this checksum is just 1's complement addition. >+ * >+ * Input Parameter: >+ * src: src IPv6 address in network byte order >+ * dst: dst IPv6 address. >+ * protocol: upper layer protocol >+ * totalLength: total length of upper layer data. Please note this is >+ * in host byte order. >+ * >+ * Result: >+ * >+ * Place in upper layer checksum field before calculate upper layer >+ * checksum. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+IPv6PseudoChecksum(UINT32 *src, >+ UINT32 *dst, >+ UINT8 protocol, >+ UINT16 totalLength) >+{ >+ UINT64 sum = (UINT32)htons(totalLength) + htons(protocol); >+ sum += (UINT64)src[0] + src[1] + src[2] + src[3]; >+ sum += (UINT64)dst[0] + dst[1] + dst[2] + dst[3]; >+ fold64(sum); >+ return (UINT16)sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * ChecksumUpdate32 -- >+ * >+ * Given old checksum value (as it is in checksum field), >+ * prev value of the relevant field in network byte order >+ * new value of the relevant field in the network byte order >+ * calculate the new checksum. >+ * Please check relevant RFC for reference. >+ * >+ * Input Pramater: >+ * oldSum: old checksum value in checksum field >+ * prev: previous value of relevant 32 bit feld in network >+ * byte order. >+ * new: new value of the relevant 32 bit field in network >+ * byte order. >+ * >+ * Result: >+ * new checksum value to be placed in the checksum field. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+ChecksumUpdate32(UINT16 oldSum, >+ UINT32 prev, >+ UINT32 newValue) >+{ >+ UINT32 sum = ~prev; >+ sum = (sum >> 16) + (sum & 0xffff); >+ sum += (newValue >> 16) + (newValue & 0xffff); >+ sum += (UINT16)~oldSum; >+ fold32(sum); >+ return (UINT16)~sum; >+} >+ >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * ChecksumUpdate16 -- >+ * >+ * Given old checksum value (as it is in checksum field), >+ * prev value of the relevant field in network byte order >+ * new value of the relevant field in the network byte order >+ * calculate the new checksum. >+ * Please check relevant RFC for reference. >+ * >+ * Input Pramater: >+ * oldSum: old checksum value in checksum field >+ * prev: previous value of relevant 32 bit feld in network >+ * byte order. >+ * new: new value of the relevant 32 bit field in network >+ * byte order. >+ * >+ * Result: >+ * new checksum value to be placed in the checksum field. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+ChecksumUpdate16(UINT16 oldSum, >+ UINT16 prev, >+ UINT16 newValue) >+{ >+ UINT32 sum = (UINT16)~oldSum; >+ sum += (UINT32)((UINT16)~prev) + newValue; >+ fold32(sum); >+ return (UINT16)~sum; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * CalculateChecksumNB -- >+ * >+ * Calculates checksum over a length of bytes contained in an NB. >+ * >+ * nb : NB which contains the packet bytes. >+ * csumDataLen : Length of bytes to be checksummed. >+ * offset : offset to the first bytes of the data stream to be >+ * checksumed. >+ * >+ * Result: >+ * return 0, if there is a failure. >+ >*------------------------------------------------------------------------- >--- >+ */ >+UINT16 >+CalculateChecksumNB(const PNET_BUFFER nb, >+ UINT16 csumDataLen, >+ UINT32 offset) >+{ >+ ULONG mdlLen; >+ UINT16 csLen; >+ PUCHAR src; >+ UINT64 csum = 0; >+ PMDL currentMdl; >+ ULONG firstMdlLen; >+ /* Running count of bytes in remainder of the MDLs including >current. */ >+ ULONG packetLen; >+ BOOLEAN swapEnd = 1 & csumDataLen; >+ >+ if ((nb == NULL) || (csumDataLen == 0) >+ || (offset >= NET_BUFFER_DATA_LENGTH(nb)) >+ || (offset + csumDataLen > NET_BUFFER_DATA_LENGTH(nb))) { >+ OVS_LOG_ERROR("Invalid parameters - csum length %u, offset %u," >+ "pkt%s len %u", csumDataLen, offset, nb? "":"(null)", >+ nb? NET_BUFFER_DATA_LENGTH(nb) : 0); >+ return 0; >+ } >+ >+ currentMdl = NET_BUFFER_CURRENT_MDL(nb); >+ packetLen = NET_BUFFER_DATA_LENGTH(nb); >+ firstMdlLen = >+ MmGetMdlByteCount(currentMdl) - >NET_BUFFER_CURRENT_MDL_OFFSET(nb); >+ >+ firstMdlLen = MIN(firstMdlLen, packetLen); >+ if (offset < firstMdlLen) { >+ src = (PUCHAR) MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >+ if (!src) { >+ return 0; >+ } >+ src += (NET_BUFFER_CURRENT_MDL_OFFSET(nb) + offset); >+ mdlLen = firstMdlLen - offset; >+ packetLen -= firstMdlLen; >+ ASSERT((INT)packetLen >= 0); >+ } else { >+ offset -= firstMdlLen; >+ packetLen -= firstMdlLen; >+ ASSERT((INT)packetLen >= 0); >+ currentMdl = NDIS_MDL_LINKAGE(currentMdl); >+ mdlLen = MmGetMdlByteCount(currentMdl); >+ mdlLen = MIN(mdlLen, packetLen); >+ >+ while (offset >= mdlLen) { >+ offset -= mdlLen; >+ packetLen -= mdlLen; >+ ASSERT((INT)packetLen >= 0); >+ currentMdl = NDIS_MDL_LINKAGE(currentMdl); >+ mdlLen = MmGetMdlByteCount(currentMdl); >+ mdlLen = MIN(mdlLen, packetLen); >+ } >+ >+ src = (PUCHAR)MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >+ if (!src) { >+ return 0; >+ } >+ >+ src += offset; >+ mdlLen -= offset; >+ } >+ >+ while (csumDataLen && (currentMdl != NULL)) { >+ ASSERT(mdlLen < 65536); >+ csLen = MIN((UINT16) mdlLen, csumDataLen); >+ >+ csum = CalculateOnesComplement(src, csLen, csum, !(1 & >csumDataLen)); >+ fold64(csum); >+ >+ csumDataLen -= csLen; >+ currentMdl = NDIS_MDL_LINKAGE(currentMdl); >+ if (csumDataLen && currentMdl) { >+ src = MmGetSystemAddressForMdlSafe(currentMdl, >LowPagePriority); >+ if (!src) { >+ return 0; >+ } >+ >+ mdlLen = MmGetMdlByteCount(currentMdl); >+ mdlLen = MIN(mdlLen, packetLen); >+ /* packetLen does not include the current MDL from here on. >*/ >+ packetLen -= mdlLen; >+ ASSERT((INT)packetLen >= 0); >+ } >+ } >+ >+ fold64(csum); >+ ASSERT(csumDataLen == 0); >+ ASSERT((csum & ~0xffff) == 0); >+ csum = (UINT16)~csum; >+ if (swapEnd) { >+ return _byteswap_ushort((UINT16)csum); >+ } >+ return (UINT16)csum; >+} >+ >+/* >+ * >-------------------------------------------------------------------------- >+ * OvsValidateIPChecksum >+ * >-------------------------------------------------------------------------- >+ */ >+NDIS_STATUS >+OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, >+ POVS_PACKET_HDR_INFO hdrInfo) >+{ >+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; >+ uint16_t checksum, hdrChecksum; >+ struct IPHdr ip_storage; >+ const IPHdr *ipHdr; >+ >+ if (!hdrInfo->isIPv4) { >+ return NDIS_STATUS_SUCCESS; >+ } >+ >+ /* First check if NIC has indicated checksum failure. */ >+ csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >+ >TcpIpChecksumNetBufferListInfo); >+ if (csumInfo.Receive.IpChecksumFailed) { >+ return NDIS_STATUS_FAILURE; >+ } >+ >+ /* Next, check if the NIC did not validate the RX checksum. */ >+ if (!csumInfo.Receive.IpChecksumSucceeded) { >+ ipHdr = OvsGetIp(curNbl, hdrInfo->l3Offset, &ip_storage); >+ if (ipHdr) { >+ ip_storage = *ipHdr; >+ hdrChecksum = ipHdr->check; >+ ip_storage.check = 0; >+ checksum = IPChecksum((uint8 *)&ip_storage, ipHdr->ihl * 4, >0); >+ if (checksum != hdrChecksum) { >+ return NDIS_STATUS_FAILURE; >+ } >+ } >+ } >+ return NDIS_STATUS_SUCCESS; >+} >+ >+/* >+ >*------------------------------------------------------------------------- >--- >+ * OvsValidateUDPChecksum >+ >*------------------------------------------------------------------------- >--- >+ */ >+NDIS_STATUS >+OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, BOOLEAN udpCsumZero) >+{ >+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; >+ >+ csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >TcpIpChecksumNetBufferListInfo); >+ >+ if (udpCsumZero) { >+ /* Zero is valid checksum. */ >+ csumInfo.Receive.UdpChecksumFailed = 0; >+ NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = >csumInfo.Value; >+ return NDIS_STATUS_SUCCESS; >+ } >+ >+ /* First check if NIC has indicated UDP checksum failure. */ >+ if (csumInfo.Receive.UdpChecksumFailed) { >+ return NDIS_STATUS_INVALID_PACKET; >+ } >+ >+ return NDIS_STATUS_SUCCESS; >+} >+ >+ >+/* >+ * OvsApplySWChecksumOnNB -- >+ * >+ * This function calculates and sets the required sofware offloads given >by >+ * csumInfo for a given NBL(nbl) with a single NB. >+ * >+ */ >+NDIS_STATUS >+OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers, >+ PNET_BUFFER_LIST nbl, >+ PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO >csumInfo) >+{ >+ PNET_BUFFER curNb; >+ PMDL curMdl; >+ PUINT8 bufferStart; >+ UINT32 packetLength = 0; >+ ASSERT(nbl != NULL); >+ >+ curNb = NET_BUFFER_LIST_FIRST_NB(nbl); >+ ASSERT(curNb->Next == NULL); >+ packetLength = NET_BUFFER_DATA_LENGTH(curNb); >+ curMdl = NET_BUFFER_CURRENT_MDL(curNb); >+ bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, >+ LowPagePriority); >+ if (!bufferStart) { >+ return NDIS_STATUS_RESOURCES; >+ } >+ >+ bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); >+ >+ if (layers->isIPv4) { >+ IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); >+ >+ if (csumInfo->Transmit.IpHeaderChecksum) { >+ ip->check = 0; >+ ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); >+ } >+ >+ if (layers->isTcp && csumInfo->Transmit.TcpChecksum) { >+ UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >+ TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >+ tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >+ IPPROTO_TCP, csumLength); >+ tcp->check = CalculateChecksumNB(curNb, csumLength, >+ (UINT32)(layers->l4Offset)); >+ } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) { >+ UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >+ UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >+ udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >+ IPPROTO_UDP, csumLength); >+ udp->check = CalculateChecksumNB(curNb, csumLength, >+ (UINT32)(layers->l4Offset)); >+ } >+ } else if (layers->isIPv6) { >+ IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); >+ >+ if (layers->isTcp && csumInfo->Transmit.TcpChecksum) { >+ UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >+ TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >+ tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >+ (UINT32 *) &ip->daddr, >+ IPPROTO_TCP, csumLength); >+ tcp->check = CalculateChecksumNB(curNb, csumLength, >+ (UINT32)(layers->l4Offset)); >+ } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) { >+ UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >+ UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >+ udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >+ (UINT32 *) &ip->daddr, >+ IPPROTO_UDP, csumLength); >+ udp->check = CalculateChecksumNB(curNb, csumLength, >+ (UINT32)(layers->l4Offset)); >+ } >+ } >+ >+ return NDIS_STATUS_SUCCESS; >+} >+ >+/* >+ * OVSGetTcpMSS -- >+ * >+ * This function returns the maximum segment size of the given NBL. It >takes >+ * into consideration both LSO v1 and v2. >+ */ >+ULONG >+OVSGetTcpMSS(PNET_BUFFER_LIST nbl) >+{ >+ NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo; >+ ASSERT(nbl != NULL); >+ >+ lsoInfo.Value = NET_BUFFER_LIST_INFO(nbl, >+ TcpLargeSendNetBufferListInfo); >+ switch (lsoInfo.Transmit.Type) { >+ case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: >+ return lsoInfo.LsoV1Transmit.MSS; >+ break; >+ case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: >+ return lsoInfo.LsoV2Transmit.MSS; >+ break; >+ default: >+ OVS_LOG_ERROR("Unknown LSO transmit type:%d", >+ lsoInfo.Transmit.Type); >+ return 0; >+ } >+} >diff --git a/datapath-windows/ovsext/Offload.h >b/datapath-windows/ovsext/Offload.h >new file mode 100644 >index 0000000..b5cae2f >--- /dev/null >+++ b/datapath-windows/ovsext/Offload.h >@@ -0,0 +1,47 @@ >+/* >+ * Copyright (c) 2014, 2016 VMware, Inc. >+ * >+ * Licensed under the Apache License, Version 2.0 (the "License"); >+ * you may not use this file except in compliance with the License. >+ * You may obtain a copy of the License at: >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+#ifndef __OFFLOAD_H_ >+#define __OFFLOAD_H_ 1 >+ >+typedef union _OVS_PACKET_HDR_INFO *POVS_PACKET_HDR_INFO; >+ >+UINT16 CalculateChecksum(UINT8 *ptr, UINT16 length, UINT16 initial); >+UINT16 CopyAndCalculateChecksum(UINT8 *dst, UINT8 *src, UINT16 length, >+ UINT16 initial); >+UINT16 IPChecksum(UINT8 *ipHdr, UINT16 length, UINT16 initial); >+UINT16 IPPseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, >+ UINT16 totalLength); >+UINT16 IPv6PseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, >+ UINT16 totalLength); >+UINT16 ChecksumUpdate32(UINT16 oldSum, UINT32 prev, UINT32 newValue); >+UINT16 ChecksumUpdate16(UINT16 oldSum, UINT16 prev, UINT16 newValue); >+UINT16 CalculateChecksumNB(const PNET_BUFFER nb, UINT16 csumDataLen, >+ UINT32 offset); >+NDIS_STATUS OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, >+ POVS_PACKET_HDR_INFO hdrInfo); >+NDIS_STATUS OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, >+ BOOLEAN udpCsumZero); >+ >+ >+ULONG OVSGetTcpMSS(PNET_BUFFER_LIST nbl); >+ >+NDIS_STATUS OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers, >+ PNET_BUFFER_LIST nbl, >+ >PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO >+ >csumInfo); >+ >+#endif /* __OFFLOAD_H_ */ >diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c >index 0ae2633..dd7bf92 100644 >--- a/datapath-windows/ovsext/Stt.c >+++ b/datapath-windows/ovsext/Stt.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2015 VMware, Inc. >+ * Copyright (c) 2015, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@@ -17,10 +17,12 @@ > #include "precomp.h" > > #include "Atomic.h" >-#include "Checksum.h" >+#include "Debug.h" > #include "Flow.h" > #include "IpHelper.h" >+#include "Jhash.h" > #include "NetProto.h" >+#include "Offload.h" > #include "PacketIO.h" > #include "PacketParser.h" > #include "Stt.h" >@@ -33,8 +35,7 @@ > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_STT >-#include "Debug.h" >-#include "Jhash.h" >+ > > KSTART_ROUTINE OvsSttDefragCleaner; > static PLIST_ENTRY OvsSttPktFragHash; >@@ -163,20 +164,7 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, > BOOLEAN innerPartialChecksum = FALSE; > > if (layers->isTcp) { >- lsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >- TcpLargeSendNetBufferListInfo); >- >- switch (lsoInfo.Transmit.Type) { >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: >- mss = lsoInfo.LsoV1Transmit.MSS; >- break; >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: >- mss = lsoInfo.LsoV2Transmit.MSS; >- break; >- default: >- OVS_LOG_ERROR("Unknown LSO transmit type:%d", >- lsoInfo.Transmit.Type); >- } >+ mss = OVSGetTcpMSS(curNbl); > } > > vportStt = (POVS_STT_VPORT) GetOvsVportPriv(vport); >diff --git a/datapath-windows/ovsext/User.c >b/datapath-windows/ovsext/User.c >index 04d2294..e97f2b2 100644 >--- a/datapath-windows/ovsext/User.c >+++ b/datapath-windows/ovsext/User.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2014 VMware, Inc. >+ * Copyright (c) 2014, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@@ -22,23 +22,23 @@ > > #include "precomp.h" > >-#include "Switch.h" >-#include "Vport.h" >-#include "Event.h" >-#include "User.h" > #include "Datapath.h" >-#include "PacketIO.h" >-#include "Checksum.h" >-#include "NetProto.h" >+#include "Debug.h" >+#include "Event.h" > #include "Flow.h" >-#include "TunnelIntf.h" > #include "Jhash.h" >+#include "NetProto.h" >+#include "Offload.h" >+#include "PacketIO.h" >+#include "Switch.h" >+#include "TunnelIntf.h" >+#include "User.h" >+#include "Vport.h" > > #ifdef OVS_DBG_MOD > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_USER >-#include "Debug.h" > > POVS_PACKET_QUEUE_ELEM OvsGetNextPacket(POVS_OPEN_INSTANCE instance); > extern PNDIS_SPIN_LOCK gOvsCtrlLock; >diff --git a/datapath-windows/ovsext/Vxlan.c >b/datapath-windows/ovsext/Vxlan.c >index 2516ece..b89c032 100644 >--- a/datapath-windows/ovsext/Vxlan.c >+++ b/datapath-windows/ovsext/Vxlan.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (c) 2014 VMware, Inc. >+ * Copyright (c) 2014, 2016 VMware, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. >@@ -15,18 +15,20 @@ > */ > > #include "precomp.h" >+ > #include "Atomic.h" >-#include "NetProto.h" >-#include "Switch.h" >-#include "Vport.h" >+#include "Debug.h" >+#include "Flow.h" > #include "Flow.h" >-#include "Vxlan.h" > #include "IpHelper.h" >-#include "Checksum.h" >-#include "User.h" >+#include "NetProto.h" >+#include "Offload.h" > #include "PacketIO.h" >-#include "Flow.h" > #include "PacketParser.h" >+#include "Switch.h" >+#include "User.h" >+#include "Vport.h" >+#include "Vxlan.h" > > #pragma warning( push ) > #pragma warning( disable:4127 ) >@@ -36,7 +38,6 @@ > #undef OVS_DBG_MOD > #endif > #define OVS_DBG_MOD OVS_DBG_VXLAN >-#include "Debug.h" > > /* Helper macro to check if a VXLAN ID is valid. */ > #define VXLAN_ID_IS_VALID(vxlanID) (0 < (vxlanID) && (vxlanID) <= >0xffffff) >@@ -201,21 +202,8 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, > packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > if (layers->isTcp) { >- NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; >- >- tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, >- >TcpLargeSendNetBufferListInfo); >- switch (tsoInfo.Transmit.Type) { >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: >- mss = tsoInfo.LsoV1Transmit.MSS; >- break; >- case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: >- mss = tsoInfo.LsoV2Transmit.MSS; >- break; >- default: >- OVS_LOG_ERROR("Unknown LSO transmit type:%d", >- tsoInfo.Transmit.Type); >- } >+ mss = OVSGetTcpMSS(curNbl); >+ > OVS_LOG_TRACE("MSS %u packet len %u", mss, > packetLength); > if (mss) { >@@ -242,70 +230,14 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, > OVS_LOG_ERROR("Unable to copy NBL"); > return NDIS_STATUS_FAILURE; > } >- /* >- * To this point we do not have VXLAN offloading. >- * Apply defined checksums >- */ >- curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); >- curMdl = NET_BUFFER_CURRENT_MDL(curNb); >- bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, >LowPagePriority); >- if (!bufferStart) { >- status = NDIS_STATUS_RESOURCES; >- goto ret_error; >- } >- > NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, > >TcpIpChecksumNetBufferListInfo); >+ status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo); > >- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); >- >- if (layers->isIPv4) { >- IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); >- >- if (csumInfo.Transmit.IpHeaderChecksum) { >- ip->check = 0; >- ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); >- } >- >- if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >- tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >- IPPROTO_TCP, csumLength); >- tcp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >- udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, >- IPPROTO_UDP, csumLength); >- udp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } >- } else if (layers->isIPv6) { >- IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); >- >- if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); >- tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >- (UINT32 *) &ip->daddr, >- IPPROTO_TCP, csumLength); >- tcp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { >- UINT16 csumLength = (UINT16)(packetLength - >layers->l4Offset); >- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); >- udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, >- (UINT32 *) &ip->daddr, >- IPPROTO_UDP, csumLength); >- udp->check = CalculateChecksumNB(curNb, csumLength, >- >(UINT32)(layers->l4Offset)); >- } >+ if (status != NDIS_STATUS_SUCCESS) { >+ goto ret_error; > } >- /* Clear out TcpIpChecksumNetBufferListInfo flag */ >- NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = >0; > } > > curNbl = *newNbl; >diff --git a/datapath-windows/ovsext/ovsext.vcxproj >b/datapath-windows/ovsext/ovsext.vcxproj >index fd10809..7b0ebcf 100644 >--- a/datapath-windows/ovsext/ovsext.vcxproj >+++ b/datapath-windows/ovsext/ovsext.vcxproj >@@ -73,7 +73,6 @@ > <ClInclude Include="..\include\OvsDpInterfaceExt.h" /> > <ClInclude Include="Atomic.h" /> > <ClInclude Include="BufferMgmt.h" /> >- <ClInclude Include="Checksum.h" /> > <ClInclude Include="Datapath.h" /> > <ClInclude Include="Debug.h" /> > <ClInclude Include="DpInternal.h" /> >@@ -89,6 +88,7 @@ > <ClInclude Include="Netlink/NetlinkProto.h" /> > <ClInclude Include="Netlink\NetlinkError.h" /> > <ClInclude Include="NetProto.h" /> >+ <ClInclude Include="Offload.h" /> > <ClInclude Include="Oid.h" /> > <ClInclude Include="PacketIO.h" /> > <ClInclude Include="PacketParser.h" /> >@@ -169,7 +169,6 @@ > <ItemGroup> > <ClCompile Include="Actions.c" /> > <ClCompile Include="BufferMgmt.c" /> >- <ClCompile Include="Checksum.c" /> > <ClCompile Include="Debug.c" /> > <ClCompile Include="Driver.c" /> > <ClCompile Include="Event.c" /> >@@ -180,6 +179,7 @@ > <ClCompile Include="Netlink/Netlink.c" /> > <ClCompile Include="Netlink/NetlinkBuf.c" /> > <ClCompile Include="Datapath.c" /> >+ <ClCompile Include="Offload.c" /> > <ClCompile Include="Oid.c" /> > <ClCompile Include="PacketIO.c" /> > <ClCompile Include="PacketParser.c" /> >-- >1.9.5.msysgit.0 >_______________________________________________ >dev mailing list >dev@openvswitch.org >http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev