This patch introduces GRE checksum computation if the userspace requires
it on Tx. On Rx we verify the GRE checksum if the checksum bit was
specified and also inform the userspace about it.

Also fix the GRE header length as specified by the GRE flags not the
tunnel flags.

Signed-off-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com>
---
 datapath-windows/ovsext/Gre.c | 68 ++++++++++++++++++++++++++++++-------------
 datapath-windows/ovsext/Gre.h | 14 ++++-----
 2 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c
index cb41593..5fa10c3 100644
--- a/datapath-windows/ovsext/Gre.c
+++ b/datapath-windows/ovsext/Gre.c
@@ -135,7 +135,8 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
     IPHdr *ipHdr;
     PGREHdr greHdr;
     POVS_GRE_VPORT vportGre;
-    UINT32 headRoom = GreTunHdrSize(tunKey->flags);
+    PCHAR pChk = NULL;
+    UINT32 headRoom = GreTunHdrSize(OvsTunnelFlagsToGreFlags(tunKey->flags));
 #if DBG
     UINT32 counterHeadRoom;
 #endif
@@ -259,6 +260,7 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
 
         if (tunKey->flags & OVS_TNL_F_CSUM) {
             RtlZeroMemory(currentOffset, 4);
+            pChk = currentOffset;
             currentOffset += 4;
 #if DBG
             counterHeadRoom -= 4;
@@ -275,6 +277,17 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
 #endif
         }
 
+        /* Checksum needs to be done after the GRE header has been set */
+        if (tunKey->flags & OVS_TNL_F_CSUM) {
+            ASSERT(pChk);
+            UINT16 chksum =
+                CalculateChecksumNB(curNb,
+                                    (UINT16)(NET_BUFFER_DATA_LENGTH(curNb) -
+                                             sizeof *ipHdr - sizeof *ethHdr),
+                                    sizeof *ipHdr + sizeof *ethHdr);
+            RtlCopyMemory(pChk, &chksum, 2);
+        }
+
 #if DBG
         ASSERT(counterHeadRoom == 0);
 #endif
@@ -306,25 +319,12 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
 
     curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
     packetLength = NET_BUFFER_DATA_LENGTH(curNb);
-    tunnelSize = GreTunHdrSize(tunKey->flags);
+    curMdl = NET_BUFFER_CURRENT_MDL(curNb);
+    tunnelSize = GreTunHdrSize(0);
     if (packetLength <= tunnelSize) {
         return NDIS_STATUS_INVALID_LENGTH;
     }
 
-    /*
-     * Create a copy of the NBL so that we have all the headers in one MDL.
-     */
-    *newNbl = OvsPartialCopyNBL(switchContext, curNbl,
-                                tunnelSize + OVS_DEFAULT_COPY_SIZE, 0,
-                                TRUE /*copy NBL info */);
-
-    if (*newNbl == NULL) {
-        return NDIS_STATUS_RESOURCES;
-    }
-
-    curNbl = *newNbl;
-    curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
-    curMdl = NET_BUFFER_CURRENT_MDL(curNb);
     bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, 
LowPagePriority) +
                   NET_BUFFER_CURRENT_MDL_OFFSET(curNb);
     if (!bufferStart) {
@@ -346,16 +346,30 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
     greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr);
     headRoom += sizeof *greHdr;
 
+    tunnelSize = GreTunHdrSize(greHdr->flags);
+
     /* Validate if GRE header protocol type. */
     if (greHdr->protocolType != GRE_NET_TEB) {
-        status = STATUS_NDIS_INVALID_PACKET;
-        goto dropNbl;
+        *newNbl = NULL;
+        return STATUS_NDIS_INVALID_PACKET;
     }
 
     PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr;
 
     if (greHdr->flags & GRE_CSUM) {
         tunKey->flags |= OVS_TNL_F_CSUM;
+        UINT16 prevChksum = *((UINT16 *)currentOffset);
+        RtlZeroMemory(currentOffset, 2);
+        UINT16 chksum =
+            CalculateChecksumNB(curNb,
+                                (UINT16)(NET_BUFFER_DATA_LENGTH(curNb) -
+                                (ipHdr->ihl * 4 + sizeof *ethHdr)),
+                                ipHdr->ihl * 4 + sizeof *ethHdr);
+        if (prevChksum != chksum) {
+            *newNbl = NULL;
+            return STATUS_NDIS_INVALID_PACKET;
+        }
+        RtlCopyMemory(currentOffset, &prevChksum, 2);
         currentOffset += 4;
         headRoom += 4;
     }
@@ -369,11 +383,25 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
         headRoom += 4;
     }
 
+    /*
+     * Create a copy of the NBL so that we have all the headers in one MDL.
+     */
+    *newNbl = OvsPartialCopyNBL(switchContext, curNbl,
+                                tunnelSize, 0,
+                                TRUE /*copy NBL info */);
+
+    if (*newNbl == NULL) {
+        return NDIS_STATUS_RESOURCES;
+    }
+
+    curNbl = *newNbl;
+    curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
+
     /* Clear out the receive flag for the inner packet. */
     NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0;
-    NdisAdvanceNetBufferDataStart(curNb, GreTunHdrSize(tunKey->flags), FALSE,
+    NdisAdvanceNetBufferDataStart(curNb, GreTunHdrSize(greHdr->flags), FALSE,
                                   NULL);
-    ASSERT(headRoom == GreTunHdrSize(tunKey->flags));
+    ASSERT(headRoom == GreTunHdrSize(greHdr->flags));
     return NDIS_STATUS_SUCCESS;
 
 dropNbl:
diff --git a/datapath-windows/ovsext/Gre.h b/datapath-windows/ovsext/Gre.h
index d2472d9..beee86c 100644
--- a/datapath-windows/ovsext/Gre.h
+++ b/datapath-windows/ovsext/Gre.h
@@ -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.
@@ -76,11 +76,13 @@ OvsTunnelFlagsToGreFlags(UINT16 tunnelflags)
 {
     UINT16 flags = 0;
 
-    if (tunnelflags & OVS_TNL_F_CSUM)
+    if (tunnelflags & OVS_TNL_F_CSUM) {
         flags |= GRE_CSUM;
+    }
 
-    if (tunnelflags & OVS_TNL_F_KEY)
+    if (tunnelflags & OVS_TNL_F_KEY) {
         flags |= GRE_KEY;
+    }
 
     return flags;
 }
@@ -89,10 +91,8 @@ static __inline UINT32
 GreTunHdrSize(UINT16 flags)
 {
     UINT32 sum = sizeof(EthHdr) + sizeof(IPHdr) + sizeof(GREHdr);
-    sum += (flags & OVS_TNL_F_CSUM) ?
-           4 : 0;
-    sum += (flags & OVS_TNL_F_KEY) ?
-           4 : 0;
+    sum += (flags & GRE_CSUM) ? 4 : 0;
+    sum += (flags & GRE_KEY) ? 4 : 0;
 
     return sum;
 }
-- 
1.9.5.msysgit.0
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to