Index: trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
===================================================================
--- trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 30558)
+++ trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 30732)
@@ -1150,13 +1150,4 @@
     Assert(!skb_shinfo(pBuf)->frag_list);
 
-    if (fSrc & INTNETTRUNKDIR_WIRE)
-    {
-        /*
-         * The packet came from wire, ethernet header was removed by device driver.
-         * Restore it.
-         */
-        skb_push(pBuf, ETH_HLEN);
-    }
-
     if (!pGsoCtx)
         IntNetSgInitTempSegs(pSG, pBuf->len, cSegs, 0 /*cSegsUsed*/);
@@ -1246,4 +1237,5 @@
     Log3(("vboxNetFltLinuxPacketHandler: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n",
           pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
+    Log4(("vboxNetFltLinuxPacketHandler: packet dump follows:\n%.*Rhxd\n", pBuf->len-pBuf->data_len, skb_mac_header(pBuf)));
 #else
     Log3(("vboxNetFltLinuxPacketHandler: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u tso_size=%u tso_seqs=%u frag_list=%p pkt_type=%x\n",
@@ -1288,4 +1280,5 @@
         Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n",
               pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
+        Log4(("vboxNetFltLinuxPacketHandler: packet dump follows:\n%.*Rhxd\n", pBuf->len-pBuf->data_len, skb_mac_header(pBuf)));
 # else
         Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u tso_size=%u tso_seqs=%u frag_list=%p pkt_type=%x\n",
@@ -1426,20 +1419,37 @@
         return false;
     }
+    /*
+     * It is possible to receive GSO packets from wire if GRO is enabled.
+     */
     if (RT_UNLIKELY(fSrc & INTNETTRUNKDIR_WIRE))
     {
         Log5(("vboxNetFltLinuxCanForwardAsGso: fSrc=wire\n"));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+        /*
+         * The packet came from the wire and the driver has already consumed
+         * mac header. We need to restore it back.
+         */
+        pSkb->mac_len = pSkb->network_header - pSkb->mac_header;
+        skb_push(pSkb, pSkb->mac_len);
+        Log5(("vboxNetFltLinuxCanForwardAsGso: mac_len=%d data=%p mac_header=%p network_header=%p\n",
+              pSkb->mac_len, pSkb->data, skb_mac_header(pSkb), skb_network_header(pSkb)));
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) */
+        /* Older kernels didn't have GRO. */
         return false;
-    }
-
-    /*
-     * skb_gso_segment does the following. Do we need to do it as well?
-     */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) */
+    }
+    else 
+    {
+        /*
+         * skb_gso_segment does the following. Do we need to do it as well?
+         */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-    skb_reset_mac_header(pSkb);
-    pSkb->mac_len = pSkb->network_header - pSkb->mac_header;
+        skb_reset_mac_header(pSkb);
+        pSkb->mac_len = pSkb->network_header - pSkb->mac_header;
 #else
-    pSkb->mac.raw = pSkb->data;
-    pSkb->mac_len = pSkb->nh.raw - pSkb->data;
-#endif
+        pSkb->mac.raw = pSkb->data;
+        pSkb->mac_len = pSkb->nh.raw - pSkb->data;
+#endif
+    }
 
     /*
@@ -1639,4 +1649,13 @@
         if (RT_LIKELY(pSG))
         {
+            if (fSrc & INTNETTRUNKDIR_WIRE)
+            {
+                /*
+                 * The packet came from wire, ethernet header was removed by device driver.
+                 * Restore it.
+                 */
+                skb_push(pBuf, ETH_HLEN);
+            }
+
             vboxNetFltLinuxSkBufToSG(pThis, pBuf, pSG, cSegs, fSrc, NULL /*pGsoCtx*/);
 
