[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