diff mbox

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

Message ID 1453342590-6020-1-git-send-email-aserdean@cloudbasesolutions.com
State Not Applicable
Headers show

Commit Message

Alin Serdean Jan. 21, 2016, 2:16 a.m. UTC
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@cloudbasesolutions.com>
---
 datapath-windows/ovsext/BufferMgmt.c | 106 +++++++++++++++++++++++++++++++++++
 datapath-windows/ovsext/BufferMgmt.h |  21 ++++++-
 datapath-windows/ovsext/Gre.c        |  79 ++------------------------
 datapath-windows/ovsext/Stt.c        |  15 +----
 datapath-windows/ovsext/Vxlan.c      |  79 ++------------------------
 5 files changed, 135 insertions(+), 165 deletions(-)

Comments

Nithin Raju Jan. 28, 2016, 8:16 p.m. UTC | #1
Hi Alin,
Thanks for the change.

Only suggestion I had is to add the new functions to Checksum.c. If you
are concerned about the name Checksum.c, we could rename it to Offloads.c.
BufferMgmt[ch] is for NBL clone/copy/split etc.

Thanks,
-- Nithin


-----Original Message-----
From: dev <dev-bounces@openvswitch.org> on behalf of Alin Serdean
<aserdean@cloudbasesolutions.com>
Date: Wednesday, January 20, 2016 at 6:16 PM
To: "dev@openvswitch.org" <dev@openvswitch.org>
Subject: [ovs-dev] [PATCH] datapath-windows: Refactor sofware offloads
and	mss

>The purpose of this patch is to refactor the software offloads found in
>the VXLAN and GRE code and also to refactor how the maximmum segment
>size for a given NBL is obtained.
>
>This patch introduces two functions OvsApplySWChecksumOnNB and
>OVSGetTcpMSS.
>
>OVSGetTcpMSS - will return the mss found in a given NBL.
>
>OvsApplySWChecksumOnNB - will compute and set software offloads for a
>given
>                         NBL.
>
>Signed-off-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
>---
> datapath-windows/ovsext/BufferMgmt.c | 106
>+++++++++++++++++++++++++++++++++++
> datapath-windows/ovsext/BufferMgmt.h |  21 ++++++-
> datapath-windows/ovsext/Gre.c        |  79 ++------------------------
> datapath-windows/ovsext/Stt.c        |  15 +----
> datapath-windows/ovsext/Vxlan.c      |  79 ++------------------------
> 5 files changed, 135 insertions(+), 165 deletions(-)
>
>diff --git a/datapath-windows/ovsext/BufferMgmt.c
>b/datapath-windows/ovsext/BufferMgmt.c
>index 7ec073b..e9d339c 100644
>--- a/datapath-windows/ovsext/BufferMgmt.c
>+++ b/datapath-windows/ovsext/BufferMgmt.c
>@@ -1311,6 +1311,112 @@ nblcopy_error:
> }
> 
> /*
>+ * 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;
>+    }
>+}
>+
>+/*
>  * 
>--------------------------------------------------------------------------
>  * OvsAllocateNBLFromBuffer --
>  *
>diff --git a/datapath-windows/ovsext/BufferMgmt.h
>b/datapath-windows/ovsext/BufferMgmt.h
>index 79abc3d..3f44b9b 100644
>--- a/datapath-windows/ovsext/BufferMgmt.h
>+++ b/datapath-windows/ovsext/BufferMgmt.h
>@@ -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,22 +107,36 @@ 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);
> 
>+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 /* __BUFFER_MGMT_H_ */
>diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c
>index 5abd4a4..fbba930 100644
>--- a/datapath-windows/ovsext/Gre.c
>+++ b/datapath-windows/ovsext/Gre.c
>@@ -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/Stt.c b/datapath-windows/ovsext/Stt.c
>index 0ae2633..6da0ac9 100644
>--- a/datapath-windows/ovsext/Stt.c
>+++ b/datapath-windows/ovsext/Stt.c
>@@ -163,20 +163,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/Vxlan.c
>b/datapath-windows/ovsext/Vxlan.c
>index 2516ece..813fe42 100644
>--- a/datapath-windows/ovsext/Vxlan.c
>+++ b/datapath-windows/ovsext/Vxlan.c
>@@ -201,21 +201,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 +229,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;
>-- 
>1.9.5.msysgit.0
>_______________________________________________
>dev mailing list
>dev@openvswitch.org
>https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma
>n_listinfo_dev&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN
>HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=lA-zFUIHGjKzRsuCQlabvoqaPOSkhy
>LBBfCtVAO1yWg&s=CYx1ZKx7e6g6lYzTZcgMiwz3T29NwhO3E5lNyTzgF08&e=
diff mbox

Patch

diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c
index 7ec073b..e9d339c 100644
--- a/datapath-windows/ovsext/BufferMgmt.c
+++ b/datapath-windows/ovsext/BufferMgmt.c
@@ -1311,6 +1311,112 @@  nblcopy_error:
 }
 
 /*
+ * 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;
+    }
+}
+
+/*
  * --------------------------------------------------------------------------
  * OvsAllocateNBLFromBuffer --
  *
diff --git a/datapath-windows/ovsext/BufferMgmt.h b/datapath-windows/ovsext/BufferMgmt.h
index 79abc3d..3f44b9b 100644
--- a/datapath-windows/ovsext/BufferMgmt.h
+++ b/datapath-windows/ovsext/BufferMgmt.h
@@ -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,22 +107,36 @@  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);
 
+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 /* __BUFFER_MGMT_H_ */
diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c
index 5abd4a4..fbba930 100644
--- a/datapath-windows/ovsext/Gre.c
+++ b/datapath-windows/ovsext/Gre.c
@@ -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/Stt.c b/datapath-windows/ovsext/Stt.c
index 0ae2633..6da0ac9 100644
--- a/datapath-windows/ovsext/Stt.c
+++ b/datapath-windows/ovsext/Stt.c
@@ -163,20 +163,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/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index 2516ece..813fe42 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -201,21 +201,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 +229,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;