[ovs-dev] [PATCH] datapath-windows: Refactor sofware offloads and mss

Nithin Raju nithin at vmware.com
Thu Feb 11 03:50:36 UTC 2016


Thanks for taking care of the comments.

Acked-by: Nithin Raju <nithin at vmware.com>


-----Original Message-----
From: dev <dev-bounces at openvswitch.org> on behalf of Alin Serdean
<aserdean at cloudbasesolutions.com>
Date: Wednesday, February 10, 2016 at 5:38 PM
To: "dev at openvswitch.org" <dev at 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 <aserdean at 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 at openvswitch.org
>http://openvswitch.org/mailman/listinfo/dev




More information about the dev mailing list