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

Alin Serdean aserdean at cloudbasesolutions.com
Thu Jan 21 02:16:32 UTC 2016


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>
---
 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



More information about the dev mailing list