Index: /trunk/include/VBox/pdmnetinline.h
===================================================================
--- /trunk/include/VBox/pdmnetinline.h	(revision 31270)
+++ /trunk/include/VBox/pdmnetinline.h	(revision 31271)
@@ -40,4 +40,19 @@
 
 
+/**
+ * Checksum type.
+ */
+typedef enum RTNETCSUMTYPE
+{
+    /** No checksum. */
+    RTNETCSUMTYPE_NONE = 0,
+    /** Normal TCP checksum. */
+    RTNETCSUMTYPE_COMPLETE,
+    /** Checksum on pseudo header (used with GSO). */
+    RTNETCSUMTYPE_PSEUDO,
+    /** The usual 32-bit hack. */
+    RTNETCSUMTYPE_32_BIT_HACK = 0x7fffffff
+} RTNETCSUMTYPE;
+
 
 /**
@@ -163,13 +178,30 @@
  * @param   cbPayload           The amount of payload.
  * @param   cbHdrs              The size of all the headers.
- * @param   fPayloadChecksum    Whether to checksum the payload or not.
+ * @param   enmCsumType         Whether to checksum the payload, the pseudo
+ *                              header or nothing.
  * @internal
  */
 DECLINLINE(void) pdmNetGsoUpdateUdpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offUdpHdr,
-                                       uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs, bool fPayloadChecksum)
+                                       uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs,
+                                       RTNETCSUMTYPE enmCsumType)
 {
     PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
     pUdpHdr->uh_ulen = cbPayload + cbHdrs - offUdpHdr;
-    pUdpHdr->uh_sum  = fPayloadChecksum ? RTNetUDPChecksum(u32PseudoSum, pUdpHdr) : 0;
+    switch (enmCsumType)
+    {
+        case RTNETCSUMTYPE_NONE:
+            pUdpHdr->uh_sum = 0;
+            break;
+        case RTNETCSUMTYPE_COMPLETE:
+            pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);
+            break;
+        /* @todo: Implement:
+        case RTNETCSUMTYPE_PSEUDO:
+            pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);
+            break; */
+        default:
+            Log(("pdmNetGsoUpdateUdpHdr: Invalid checksum type: %d\n", enmCsumType));
+            break;
+    }
 }
 
@@ -188,10 +220,11 @@
  * @param   cbHdrs              The size of all the headers.
  * @param   fLastSeg            Set if this is the last segment.
- * @param   fPayloadChecksum    Whether to checksum the payload or not.
+ * @param   enmCsumType         Whether to checksum the payload, the pseudo
+ *                              header or nothing.
  * @internal
  */
 DECLINLINE(void) pdmNetGsoUpdateTcpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offTcpHdr,
                                        uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs,
-                                       bool fLastSeg, bool fPayloadChecksum)
+                                       bool fLastSeg, RTNETCSUMTYPE enmCsumType)
 {
     PRTNETTCP pTcpHdr = (PRTNETTCP)&pbSegHdrs[offTcpHdr];
@@ -199,5 +232,19 @@
     if (!fLastSeg)
         pTcpHdr->th_flags &= ~(RTNETTCP_F_FIN | RTNETTCP_F_PSH);
-    pTcpHdr->th_sum = fPayloadChecksum ? RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload) : 0;
+    switch (enmCsumType)
+    {
+        case RTNETCSUMTYPE_NONE:
+            pTcpHdr->th_sum = 0;
+            break;
+        case RTNETCSUMTYPE_COMPLETE:
+            pTcpHdr->th_sum = RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload);
+            break;
+        case RTNETCSUMTYPE_PSEUDO:
+            pTcpHdr->th_sum = ~RTNetIPv4FinalizeChecksum(u32PseudoSum);
+            break;
+        default:
+            Log(("pdmNetGsoUpdateTcpHdr: Invalid checksum type: %d\n", enmCsumType));
+            break;
+    }
 }
 
@@ -306,9 +353,9 @@
             pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV6_TCP:
@@ -316,10 +363,10 @@
                                                          pGso->offHdr2, RTNETIPV4_PROT_TCP),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV6_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs,
                                                          pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
@@ -328,5 +375,5 @@
                                                          cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
@@ -334,5 +381,5 @@
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
                                                          cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_INVALID:
@@ -399,9 +446,9 @@
             pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV6_TCP:
@@ -409,10 +456,10 @@
                                                          pGso->offHdr2, RTNETIPV4_PROT_TCP),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV6_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs,
                                                          pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
@@ -421,5 +468,5 @@
                                                          cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
                                   pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
-                                  pGso->cbHdrs, iSeg + 1 == cSegs, true);
+                                  pGso->cbHdrs, iSeg + 1 == cSegs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
@@ -427,5 +474,5 @@
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
                                                          cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true);
+                                  pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, RTNETCSUMTYPE_COMPLETE);
             break;
         case PDMNETWORKGSOTYPE_INVALID:
@@ -446,7 +493,8 @@
  * @param   pvFrame             The frame to prepare.
  * @param   cbFrame             The frame size.
- * @param   fPayloadChecksum    Whether to checksum payload.
- */
-DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, bool fPayloadChecksum)
+ * @param   enmCsumType         Whether to checksum the payload, the pseudo
+ *                              header or nothing.
+ */
+DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, RTNETCSUMTYPE enmCsumType)
 {
     /*
@@ -471,19 +519,19 @@
         case PDMNETWORKGSOTYPE_IPV4_TCP:
             pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrs, 0, pGso->cbHdrs),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_IPV4_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrs, 0, pGso->cbHdrs),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_IPV6_TCP:
             pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs,
                                                          pGso->offHdr2, RTNETIPV4_PROT_TCP),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_IPV6_UDP:
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs,
                                                          pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
@@ -491,5 +539,5 @@
             pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
                                                          cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
@@ -497,5 +545,5 @@
             pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
                                                          cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
-                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum);
+                                  pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, enmCsumType);
             break;
         case PDMNETWORKGSOTYPE_INVALID:
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 31270)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 31271)
@@ -1120,5 +1120,5 @@
 # endif
         if (!fDstWire)
-            PDMNetGsoPrepForDirectUse(&pSG->GsoCtx, pPkt->data, pSG->cbTotal, false /*fPayloadChecksum*/);
+            PDMNetGsoPrepForDirectUse(&pSG->GsoCtx, pPkt->data, pSG->cbTotal, RTNETCSUMTYPE_PSEUDO);
     }
 #endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE || VBOXNETFLT_WITH_GSO_XMIT_HOST */
Index: /trunk/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp	(revision 31270)
+++ /trunk/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp	(revision 31271)
@@ -123,5 +123,5 @@
      */
     if (pGso)
-        PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, false /*fPayloadChecksum*/);
+        PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, RTNETCSUMTYPE_NONE);
 
     /*
