[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Add statistics for checksum validation



For the transmit side this also entails added code to perform checksum
validation. However, since this may affect performance, validation is
only performed if the registry parameter TransmitterValidateChecksums
(REG_DWORD) is present and set a non-zero value.

Since the index values of the statistics used by XENNET are left
unchanged by this patch, there is no need to bump the XENVIF_VIF
interface version.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/vif_interface.h  |  87 +++++++++++-
 src/xenvif/frontend.c    | 110 ++++++++++------
 src/xenvif/receiver.c    | 248 +++++++++++++++++++++++-----------
 src/xenvif/transmitter.c | 336 ++++++++++++++++++++++++++++++++++++-----------
 4 files changed, 584 insertions(+), 197 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 38872bc..02d9549 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -152,20 +152,20 @@ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
             ULONG   IpChecksumSucceeded:1;
             /*! IPv4 header checksum validation failed */
             ULONG   IpChecksumFailed:1;
-            /*! IPv4 header checksum is present */
-            ULONG   IpChecksumPresent:1;
+            /*! IPv4 header checksum not validated */
+            ULONG   IpChecksumNotValidated:1;
             /*! TCP checksum validation succeeded */
             ULONG   TcpChecksumSucceeded:1;
             /*! TCP checksum validation failed */
             ULONG   TcpChecksumFailed:1;
-            /*! TCP checksum is present */
-            ULONG   TcpChecksumPresent:1;
+            /*! TCP checksum not validated */
+            ULONG   TcpChecksumNotValidated:1;
             /*! UDP checksum validation succeeded */
             ULONG   UdpChecksumSucceeded:1;
             /*! UDP checksum validation failed */
             ULONG   UdpChecksumFailed:1;
-            /*! UDP checksum is present */
-            ULONG   UdpChecksumPresent:1;
+            /*! UDP checksum not validated */
+            ULONG   UdpChecksumNotValidated:1;
             ULONG   Reserved:23;
         };
         /*! Raw representation */
@@ -288,6 +288,10 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
     \brief Interface statistics
 */
 typedef enum _XENVIF_VIF_STATISTIC {
+    /*
+     * Statistics required by XENNET
+     */
+
     /*! RFC 2863 ifOutDiscards */
     XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
     /*! Backend component of RFC 2863 ifOutErrors */
@@ -324,6 +328,77 @@ typedef enum _XENVIF_VIF_STATISTIC {
     XENVIF_RECEIVER_BROADCAST_PACKETS,
     /*! Total number of octets in ifInBroadcastPkts */
     XENVIF_RECEIVER_BROADCAST_OCTETS,
+
+    /*
+     * Miscellaneous statistics
+     */
+
+    /*! Total number of outbound VLAN tagged packets */
+    XENVIF_TRANSMITTER_TAGGED_PACKETS,
+    /*! Total number of outbound LLC/SNAP packets */
+    XENVIF_TRANSMITTER_LLC_SNAP_PACKETS,
+    /*! Total number of outbound IP version 4 packets */
+    XENVIF_TRANSMITTER_IPV4_PACKETS,
+    /*! Total number of outbound IP version 6 packets */
+    XENVIF_TRANSMITTER_IPV6_PACKETS,
+    /*! Total number of outbound TCP packets */
+    XENVIF_TRANSMITTER_TCP_PACKETS,
+    /*! Total number of outbound UDP packets */
+    XENVIF_TRANSMITTER_UDP_PACKETS,
+    /*! Total number of outbound GSO packets */
+    XENVIF_TRANSMITTER_GSO_PACKETS,
+    /*! Total number of outbound IP version 4 packets with good checksum */
+    XENVIF_TRANSMITTER_IPV4_CHECKSUM_SUCCEEDED,
+    /*! Total number of outbound IP version 4 packets with bad checksum */
+    XENVIF_TRANSMITTER_IPV4_CHECKSUM_FAILED,
+    /*! Total number of outbound IP version 4 packets without validated 
checksum */
+    XENVIF_TRANSMITTER_IPV4_CHECKSUM_NOT_VALIDATED,
+    /*! Total number of outbound TCP packets with good checksum */
+    XENVIF_TRANSMITTER_TCP_CHECKSUM_SUCCEEDED,
+    /*! Total number of outbound TCP packets with bad checksum */
+    XENVIF_TRANSMITTER_TCP_CHECKSUM_FAILED,
+    /*! Total number of outbound TCP packets without validated checksum */
+    XENVIF_TRANSMITTER_TCP_CHECKSUM_NOT_VALIDATED,
+    /*! Total number of outbound UDP packets with good checksum */
+    XENVIF_TRANSMITTER_UDP_CHECKSUM_SUCCEEDED,
+    /*! Total number of outbound UDP packets with bad checksum */
+    XENVIF_TRANSMITTER_UDP_CHECKSUM_FAILED,
+    /*! Total number of outbound UDP packets without validated checksum */
+    XENVIF_TRANSMITTER_UDP_CHECKSUM_NOT_VALIDATED,
+
+
+    /*! Total number of inbound VLAN tagged packets */
+    XENVIF_RECEIVER_TAGGED_PACKETS,
+    /*! Total number of inbound LLC/SNAP packets */
+    XENVIF_RECEIVER_LLC_SNAP_PACKETS,
+    /*! Total number of inbound IP version 4 packets */
+    XENVIF_RECEIVER_IPV4_PACKETS,
+    /*! Total number of inbound IP version 6 packets */
+    XENVIF_RECEIVER_IPV6_PACKETS,
+    /*! Total number of inbound TCP packets */
+    XENVIF_RECEIVER_TCP_PACKETS,
+    /*! Total number of inbound UDP packets */
+    XENVIF_RECEIVER_UDP_PACKETS,
+    /*! Total number of inbound GSO packets */
+    XENVIF_RECEIVER_GSO_PACKETS,
+    /*! Total number of inbound IP version 4 packets with good checksum */
+    XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
+    /*! Total number of inbound IP version 4 packets with bad checksum */
+    XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
+    /*! Total number of inbound IP version 4 packets without validated 
checksum */
+    XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
+    /*! Total number of inbound TCP packets with good checksum */
+    XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
+    /*! Total number of inbound TCP packets with bad checksum */
+    XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
+    /*! Total number of inbound TCP packets without validated checksum */
+    XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
+    /*! Total number of inbound UDP packets with good checksum */
+    XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
+    /*! Total number of inbound UDP packets with bad checksum */
+    XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
+    /*! Total number of inbound UDP packets without validated checksum */
+    XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
     XENVIF_VIF_STATISTIC_COUNT
 } XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
 
diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index d21c798..f6570e8 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -1672,6 +1672,41 @@ __FrontendStatisticName(
     _FRONTEND_STATISTIC_NAME(RECEIVER_MULTICAST_OCTETS);
     _FRONTEND_STATISTIC_NAME(RECEIVER_BROADCAST_PACKETS);
     _FRONTEND_STATISTIC_NAME(RECEIVER_BROADCAST_OCTETS);
+
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_TAGGED_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_LLC_SNAP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_IPV4_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_IPV6_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_TCP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_UDP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_GSO_PACKETS);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_IPV4_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_IPV4_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_IPV4_CHECKSUM_NOT_VALIDATED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_TCP_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_TCP_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_TCP_CHECKSUM_NOT_VALIDATED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_UDP_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_UDP_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(TRANSMITTER_UDP_CHECKSUM_NOT_VALIDATED);
+
+    _FRONTEND_STATISTIC_NAME(RECEIVER_TAGGED_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_LLC_SNAP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_IPV4_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_IPV6_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_TCP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_UDP_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_GSO_PACKETS);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_IPV4_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_IPV4_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_TCP_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_TCP_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_TCP_CHECKSUM_NOT_VALIDATED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_UDP_CHECKSUM_SUCCEEDED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_UDP_CHECKSUM_FAILED);
+    _FRONTEND_STATISTIC_NAME(RECEIVER_UDP_CHECKSUM_NOT_VALIDATED);
+
     default:
         break;
     }
@@ -1708,7 +1743,7 @@ FrontendDebugCallback(
 
         XENBUS_DEBUG(Printf,
                      &Frontend->DebugInterface,
-                     " - %40s %lu\n",
+                     " - %40s %llu\n",
                      __FrontendStatisticName(Name),
                      Value);
     }
@@ -2139,16 +2174,9 @@ FrontendConnect(
 
     Trace("====>\n");
 
-    Frontend->StatisticsCount = 
KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
-    Frontend->Statistics = __FrontendAllocate(sizeof 
(XENVIF_FRONTEND_STATISTICS) * Frontend->StatisticsCount);
-
-    status = STATUS_NO_MEMORY;
-    if (Frontend->Statistics == NULL)
-        goto fail1;
-
     status = XENBUS_DEBUG(Acquire, &Frontend->DebugInterface);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail1;
 
     status = XENBUS_DEBUG(Register,
                           &Frontend->DebugInterface,
@@ -2157,26 +2185,26 @@ FrontendConnect(
                           Frontend,
                           &Frontend->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail2;
 
     status = MacConnect(__FrontendGetMac(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail3;
 
     FrontendSetNumQueues(Frontend);
     FrontendSetSplit(Frontend);
 
     status = ReceiverConnect(__FrontendGetReceiver(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail4;
 
     status = TransmitterConnect(__FrontendGetTransmitter(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail5;
 
     status = ControllerConnect(__FrontendGetController(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail6;
 
     Attempt = 0;
     do {
@@ -2231,7 +2259,7 @@ abort:
     } while (status == STATUS_RETRY);
 
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     State = XenbusStateUnknown;
     while (State != XenbusStateConnected) {
@@ -2270,7 +2298,7 @@ abort:
 
     status = STATUS_UNSUCCESSFUL;
     if (State != XenbusStateConnected)
-        goto fail9;
+        goto fail8;
 
     ControllerEnable(__FrontendGetController(Frontend));
 
@@ -2279,51 +2307,44 @@ abort:
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail9:
-    Error("fail9\n");
-
 fail8:
     Error("fail8\n");
 
-    ControllerDisconnect(__FrontendGetController(Frontend));
-
 fail7:
     Error("fail7\n");
 
-    TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
+    ControllerDisconnect(__FrontendGetController(Frontend));
 
 fail6:
     Error("fail6\n");
 
-    ReceiverDisconnect(__FrontendGetReceiver(Frontend));
+    TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
 
 fail5:
     Error("fail5\n");
 
+    ReceiverDisconnect(__FrontendGetReceiver(Frontend));
+
+fail4:
+    Error("fail4\n");
+
     MacDisconnect(__FrontendGetMac(Frontend));
 
     Frontend->Split = FALSE;
     Frontend->NumQueues = 0;
 
-fail4:
-    Error("fail4\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_DEBUG(Deregister,
                  &Frontend->DebugInterface,
                  Frontend->DebugCallback);
     Frontend->DebugCallback = NULL;
 
-fail3:
-    Error("fail3\n");
-
-    XENBUS_DEBUG(Release, &Frontend->DebugInterface);
-
 fail2:
     Error("fail2\n");
 
-    __FrontendFree(Frontend->Statistics);
-    Frontend->Statistics = NULL;
-    Frontend->StatisticsCount = 0;
+    XENBUS_DEBUG(Release, &Frontend->DebugInterface);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2356,10 +2377,6 @@ FrontendDisconnect(
 
     XENBUS_DEBUG(Release, &Frontend->DebugInterface);
 
-    __FrontendFree(Frontend->Statistics);
-    Frontend->Statistics = NULL;
-    Frontend->StatisticsCount = 0;
-
     Trace("<====\n");
 }
 
@@ -2837,10 +2854,25 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail11;
 
+    (*Frontend)->StatisticsCount = 
KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);
+    (*Frontend)->Statistics = __FrontendAllocate(sizeof 
(XENVIF_FRONTEND_STATISTICS) *
+                                                 (*Frontend)->StatisticsCount);
+
+    status = STATUS_NO_MEMORY;
+    if ((*Frontend)->Statistics == NULL)
+        goto fail12;
+
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail12:
+    Error("fail12\n");
+
+    ThreadAlert((*Frontend)->MibThread);
+    ThreadJoin((*Frontend)->MibThread);
+    (*Frontend)->MibThread = NULL;
+
 fail11:
     Error("fail11\n");
 
@@ -2934,6 +2966,10 @@ FrontendTeardown(
 
     ASSERT(Frontend->State == FRONTEND_UNKNOWN);
 
+    __FrontendFree(Frontend->Statistics);
+    Frontend->Statistics = NULL;
+    Frontend->StatisticsCount = 0;
+
     ThreadAlert(Frontend->MibThread);
     ThreadJoin(Frontend->MibThread);
     Frontend->MibThread = NULL;
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 042d550..568eb82 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -457,6 +457,7 @@ ReceiverRingProcessChecksum(
     )
 {
     PXENVIF_RECEIVER            Receiver;
+    PXENVIF_FRONTEND            Frontend;
     PXENVIF_PACKET_INFO         Info;
     XENVIF_PACKET_PAYLOAD       Payload;
     uint16_t                    flags;
@@ -464,6 +465,7 @@ ReceiverRingProcessChecksum(
     PIP_HEADER                  IpHeader;
 
     Receiver = Ring->Receiver;
+    Frontend = Receiver->Frontend;
 
     Info = &Packet->Info;
 
@@ -500,7 +502,6 @@ ReceiverRingProcessChecksum(
             OffloadChecksum = FALSE;
 
         // IP header checksums are always present and not validated
-
         if (OffloadChecksum) {
             USHORT  Embedded;
             USHORT  Calculated;
@@ -513,14 +514,8 @@ ReceiverRingProcessChecksum(
                 Packet->Flags.IpChecksumSucceeded = 1;
             else
                 Packet->Flags.IpChecksumFailed = 1;
-        }
-
-        if (!OffloadChecksum ||
-            Ring->OffloadOptions.NeedChecksumValue ||
-            Receiver->CalculateChecksums) { // Checksum must be present
-            Packet->Flags.IpChecksumPresent = 1;
         } else {
-            IpHeader->Version4.Checksum = 0;
+            Packet->Flags.IpChecksumNotValidated = 1;
         }
     }
 
@@ -556,21 +551,19 @@ ReceiverRingProcessChecksum(
                 else
                     Packet->Flags.TcpChecksumFailed = 1;
             }
+        } else {
+            Packet->Flags.TcpChecksumNotValidated = 1;
         }
         
-        if (!OffloadChecksum ||
-            Ring->OffloadOptions.NeedChecksumValue ||
-            Receiver->CalculateChecksums) {     // Checksum must be present
-            if (flags & NETRXF_csum_blank) {    // Checksum is not present
-                USHORT  Calculated;
-
-                Calculated = ChecksumPseudoHeader(StartVa, Info);
-                Calculated = ChecksumTcpPacket(StartVa, Info, Calculated, 
&Payload);
+        if ((Ring->OffloadOptions.NeedChecksumValue ||
+             Receiver->CalculateChecksums != 0) &&
+            (flags & NETRXF_data_validated)) {
+            USHORT  Calculated;
 
-                TcpHeader->Checksum = Calculated;
-            }
+            Calculated = ChecksumPseudoHeader(StartVa, Info);
+            Calculated = ChecksumTcpPacket(StartVa, Info, Calculated, 
&Payload);
 
-            Packet->Flags.TcpChecksumPresent = 1;
+            TcpHeader->Checksum = Calculated;
         }
     } else if (Info->UdpHeader.Length != 0 && !Info->IsAFragment) {
         PUDP_HEADER     UdpHeader;
@@ -590,46 +583,39 @@ ReceiverRingProcessChecksum(
                 Packet->Flags.UdpChecksumSucceeded = 1;
             } else {                                // Checksum is present but 
is not validated
                 USHORT  Embedded;
-                USHORT  Calculated;
 
                 ASSERT(~flags & NETRXF_csum_blank);
 
                 Embedded = UdpHeader->Checksum;
 
-                Calculated = ChecksumPseudoHeader(StartVa, Info);
-                Calculated = ChecksumUdpPacket(StartVa, Info, Calculated, 
&Payload);
-
-                if (IpHeader->Version == 4) {
-                    if (Embedded == 0) {    // Tolarate zero checksum for 
IPv4/UDP
-                        Packet->Flags.UdpChecksumSucceeded = 1;
-                    } else {
-                        if (ChecksumVerify(Calculated, Embedded))
-                            Packet->Flags.UdpChecksumSucceeded = 1;
-                        else
-                            Packet->Flags.UdpChecksumFailed = 1;
-                    }
+                // Tolarate zero checksum for IPv4/UDP
+                if (IpHeader->Version == 4 && Embedded == 0) {
+                    Packet->Flags.UdpChecksumSucceeded = 1;
                 } else {
+                    USHORT  Calculated;
+
+                    Calculated = ChecksumPseudoHeader(StartVa, Info);
+                    Calculated = ChecksumUdpPacket(StartVa, Info, Calculated, 
&Payload);
+
                     if (ChecksumVerify(Calculated, Embedded))
                         Packet->Flags.UdpChecksumSucceeded = 1;
                     else
                         Packet->Flags.UdpChecksumFailed = 1;
                 }
             }
+        } else {
+            Packet->Flags.UdpChecksumNotValidated = 1;
         }
 
-        if (!OffloadChecksum ||
-            Ring->OffloadOptions.NeedChecksumValue ||
-            Receiver->CalculateChecksums) {     // Checksum must be present
-            if (flags & NETRXF_csum_blank) {    // Checksum is not present
-                USHORT  Calculated;
-
-                Calculated = ChecksumPseudoHeader(StartVa, Info);
-                Calculated = ChecksumUdpPacket(StartVa, Info, Calculated, 
&Payload);
+        if ((Ring->OffloadOptions.NeedChecksumValue ||
+             Receiver->CalculateChecksums != 0) &&
+            (flags & NETRXF_data_validated)) {
+            USHORT  Calculated;
 
-                UdpHeader->Checksum = Calculated;
-            }
+            Calculated = ChecksumPseudoHeader(StartVa, Info);
+            Calculated = ChecksumUdpPacket(StartVa, Info, Calculated, 
&Payload);
 
-            Packet->Flags.UdpChecksumPresent = 1;
+            UdpHeader->Checksum = Calculated;
         }
     }
 }
@@ -758,6 +744,8 @@ __ReceiverRingBuildSegment(
                   Packet,
                   FIELD_OFFSET(XENVIF_RECEIVER_PACKET, Mdl));
 
+    Segment->MaximumSegmentSize = 0;
+
     // The segment contains no data as yet
     Segment->Length = 0;
 
@@ -1193,7 +1181,6 @@ ReceiverRingProcessPacket(
     PUCHAR                          StartVa;
     PETHERNET_HEADER                EthernetHeader;
     PETHERNET_ADDRESS               DestinationAddress;
-    ETHERNET_ADDRESS_TYPE           Type;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -1264,41 +1251,6 @@ ReceiverRingProcessPacket(
     if (!MacApplyFilters(Mac, DestinationAddress))
         goto fail3;
 
-    Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
-
-    switch (Type) {
-    case ETHERNET_ADDRESS_UNICAST:
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_UNICAST_PACKETS,
-                                   1);
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_UNICAST_OCTETS,
-                                   Packet->Length);
-        break;
-            
-    case ETHERNET_ADDRESS_MULTICAST:
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_MULTICAST_PACKETS,
-                                   1);
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_MULTICAST_OCTETS,
-                                   Packet->Length);
-        break;
-
-    case ETHERNET_ADDRESS_BROADCAST:
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_BROADCAST_PACKETS,
-                                   1);
-        FrontendIncrementStatistic(Frontend,
-                                   XENVIF_RECEIVER_BROADCAST_OCTETS,
-                                   Packet->Length);
-        break;
-
-    default:
-        ASSERT(FALSE);
-        break;
-    }
-
     if (Packet->MaximumSegmentSize != 0)
         ReceiverRingProcessLargePacket(Ring, Packet, List);
     else
@@ -1428,6 +1380,11 @@ __ReceiverRingReleaseLock(
     while (More) {
         PLIST_ENTRY             ListEntry;
         PXENVIF_RECEIVER_PACKET Packet;
+        PXENVIF_PACKET_INFO     Info;
+        PUCHAR                  StartVa;
+        PETHERNET_HEADER        EthernetHeader;
+        PETHERNET_ADDRESS       DestinationAddress;
+        ETHERNET_ADDRESS_TYPE   Type;
 
         ListEntry = RemoveHeadList(&List);
         ASSERT3P(ListEntry, !=, &List);
@@ -1441,6 +1398,139 @@ __ReceiverRingReleaseLock(
                                    XENVIF_RECEIVER_PACKET,
                                    ListEntry);
 
+        StartVa = MmGetSystemAddressForMdlSafe(&Packet->Mdl,
+                                               NormalPagePriority);
+        ASSERT(StartVa != NULL);
+        StartVa += Packet->Offset;
+
+        Info = &Packet->Info;
+
+        ASSERT(Info->EthernetHeader.Length != 0);
+        EthernetHeader = (PETHERNET_HEADER)(StartVa + 
Info->EthernetHeader.Offset);
+
+        DestinationAddress = &EthernetHeader->DestinationAddress;
+
+        Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
+
+        switch (Type) {
+        case ETHERNET_ADDRESS_UNICAST:
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_UNICAST_PACKETS,
+                                       1);
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_UNICAST_OCTETS,
+                                       Packet->Length);
+            break;
+
+        case ETHERNET_ADDRESS_MULTICAST:
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_MULTICAST_PACKETS,
+                                       1);
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_MULTICAST_OCTETS,
+                                       Packet->Length);
+            break;
+
+        case ETHERNET_ADDRESS_BROADCAST:
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_BROADCAST_PACKETS,
+                                       1);
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_BROADCAST_OCTETS,
+                                       Packet->Length);
+            break;
+
+        default:
+            ASSERT(FALSE);
+            break;
+        }
+
+        if (ETHERNET_HEADER_IS_TAGGED(EthernetHeader))
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_TAGGED_PACKETS,
+                                       1);
+
+        if (Info->LLCSnapHeader.Length != 0)
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_LLC_SNAP_PACKETS,
+                                       1);
+
+        if (Info->IpHeader.Length != 0) {
+            PIP_HEADER  IpHeader = (PIP_HEADER)(StartVa + 
Info->IpHeader.Offset);
+
+            if (IpHeader->Version == 4) {
+                FrontendIncrementStatistic(Frontend,
+                                           XENVIF_RECEIVER_IPV4_PACKETS,
+                                           1);
+            } else {
+                ASSERT3U(IpHeader->Version, ==, 6);
+
+                FrontendIncrementStatistic(Frontend,
+                                           XENVIF_RECEIVER_IPV6_PACKETS,
+                                           1);
+            }
+        }
+
+        if (Info->TcpHeader.Length != 0)
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_TCP_PACKETS,
+                                       1);
+
+        if (Info->UdpHeader.Length != 0)
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_UDP_PACKETS,
+                                       1);
+
+       if (Packet->MaximumSegmentSize != 0)
+            FrontendIncrementStatistic(Frontend,
+                                       XENVIF_RECEIVER_GSO_PACKETS,
+                                       1);
+
+       if (Packet->Flags.IpChecksumSucceeded != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_IPV4_CHECKSUM_SUCCEEDED,
+                                      1);
+
+       if (Packet->Flags.IpChecksumFailed != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_IPV4_CHECKSUM_FAILED,
+                                      1);
+
+       if (Packet->Flags.IpChecksumNotValidated != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      
XENVIF_RECEIVER_IPV4_CHECKSUM_NOT_VALIDATED,
+                                      1);
+
+       if (Packet->Flags.TcpChecksumSucceeded != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_TCP_CHECKSUM_SUCCEEDED,
+                                      1);
+
+       if (Packet->Flags.TcpChecksumFailed != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_TCP_CHECKSUM_FAILED,
+                                      1);
+
+       if (Packet->Flags.TcpChecksumNotValidated != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      
XENVIF_RECEIVER_TCP_CHECKSUM_NOT_VALIDATED,
+                                      1);
+
+       if (Packet->Flags.UdpChecksumSucceeded != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_UDP_CHECKSUM_SUCCEEDED,
+                                      1);
+
+       if (Packet->Flags.UdpChecksumFailed != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      XENVIF_RECEIVER_UDP_CHECKSUM_FAILED,
+                                      1);
+
+       if (Packet->Flags.UdpChecksumNotValidated != 0)
+           FrontendIncrementStatistic(Frontend,
+                                      
XENVIF_RECEIVER_UDP_CHECKSUM_NOT_VALIDATED,
+                                      1);
+
         VifReceiverQueuePacket(Context,
                                Ring->Index,
                                &Packet->Mdl,
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 88add2f..fae7b1b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -73,7 +73,6 @@ typedef struct _XENVIF_TRANSMITTER_PACKET {
     XENVIF_VIF_OFFLOAD_OPTIONS                  OffloadOptions;
     USHORT                                      MaximumSegmentSize;
     USHORT                                      TagControlInformation;
-    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
     PMDL                                        Mdl;
     ULONG                                       Offset;
     ULONG                                       Length;
@@ -81,6 +80,8 @@ typedef struct _XENVIF_TRANSMITTER_PACKET {
     XENVIF_PACKET_HASH                          Hash;
     XENVIF_PACKET_INFO                          Info;
     XENVIF_PACKET_PAYLOAD                       Payload;
+    XENVIF_PACKET_CHECKSUM_FLAGS                Flags;
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
 } XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
 
 typedef struct _XENVIF_TRANSMITTER_REQUEST_ARP_PARAMETERS {
@@ -220,6 +221,7 @@ struct _XENVIF_TRANSMITTER {
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
+    ULONG                       ValidateChecksums;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
     XENBUS_STORE_INTERFACE      StoreInterface;
@@ -338,21 +340,23 @@ __TransmitterPutPacket(
 {
     ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
     ASSERT3U(Packet->Reference, ==, 0);
+    Packet->Cookie = NULL;
 
-    Packet->Mdl = NULL;
-    Packet->Offset = 0;
-    Packet->Length = 0;
     Packet->OffloadOptions.Value = 0;
     Packet->MaximumSegmentSize = 0;
     Packet->TagControlInformation = 0;
-    RtlZeroMemory(&Packet->Completion, sizeof 
(XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO));
-    Packet->Cookie = NULL;
+    Packet->Mdl = NULL;
+    Packet->Offset = 0;
+    Packet->Length = 0;
 
     RtlZeroMemory(Packet->Header, XENVIF_TRANSMITTER_MAXIMUM_HEADER_LENGTH);
     RtlZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO));
     RtlZeroMemory(&Packet->Hash, sizeof (XENVIF_PACKET_HASH));
     RtlZeroMemory(&Packet->Payload, sizeof (XENVIF_PACKET_PAYLOAD));
 
+    Packet->Flags.Value = 0;
+    RtlZeroMemory(&Packet->Completion, sizeof 
(XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO));
+
     XENBUS_CACHE(Put,
                  &Transmitter->CacheInterface,
                  Transmitter->PacketCache,
@@ -1169,6 +1173,7 @@ __TransmitterRingPrepareHeader(
     PUCHAR                          StartVa;
     PFN_NUMBER                      Pfn;
     PETHERNET_HEADER                EthernetHeader;
+    BOOLEAN                         SquashError;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -1181,6 +1186,8 @@ __TransmitterRingPrepareHeader(
     Payload = &Packet->Payload;
     Info = &Packet->Info;
 
+    SquashError = FALSE;
+
     status = STATUS_UNSUCCESSFUL;
     if (Info->Length == 0)
         goto fail1;
@@ -1307,7 +1314,6 @@ __TransmitterRingPrepareHeader(
         Packet->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
 
         // TCP checksum calulcation must be offloaded for large packets
-        TcpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info);
         Packet->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
 
         // If the MSS is such that the payload would constitute only a single 
fragment then
@@ -1343,7 +1349,6 @@ __TransmitterRingPrepareHeader(
         IpHeader->Version6.PayloadLength = HTONS((USHORT)Length);
 
         // TCP checksum calulcation must be offloaded for large packets
-        TcpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info);
         Packet->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
 
         // If the MSS is such that the payload would constitute only a single 
fragment then
@@ -1362,24 +1367,110 @@ __TransmitterRingPrepareHeader(
         
         if (Fragment->Length > MaximumFrameSize) {
             status = STATUS_INVALID_PARAMETER;
+            SquashError = TRUE;
             goto fail5;
         }
     }
 
-    if (Packet->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+    if (Info->IpHeader.Length != 0) {
         PIP_HEADER  IpHeader;
 
-        ASSERT(Info->IpHeader.Length != 0);
         IpHeader = (PIP_HEADER)(StartVa + Info->IpHeader.Offset);
 
-        ASSERT3U(IpHeader->Version, ==, 4);
-        IpHeader->Version4.Checksum = ChecksumIpVersion4Header(StartVa, Info);
+        if (IpHeader->Version == 4) {
+            if (Packet->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+                IpHeader->Version4.Checksum = 
ChecksumIpVersion4Header(StartVa, Info);
+
+                Packet->Flags.IpChecksumNotValidated = 1;
+            } else if (Transmitter->ValidateChecksums != 0) {
+                USHORT      Embedded;
+                USHORT      Calculated;
+
+                Embedded = IpHeader->Version4.Checksum;
+
+                Calculated = ChecksumIpVersion4Header(StartVa, Info);
+
+                if (ChecksumVerify(Calculated, Embedded))
+                    Packet->Flags.IpChecksumSucceeded = 1;
+                else
+                    Packet->Flags.IpChecksumFailed = 1;
+            } else {
+                Packet->Flags.IpChecksumNotValidated = 1;
+            }
+        }
+    }
+
+    if (Info->TcpHeader.Length != 0) {
+        PTCP_HEADER TcpHeader;
+
+        TcpHeader = (PTCP_HEADER)(StartVa + Info->TcpHeader.Offset);
+
+        if (Packet->OffloadOptions.OffloadIpVersion4TcpChecksum ||
+            Packet->OffloadOptions.OffloadIpVersion6TcpChecksum) {
+            TcpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info);
+
+            Packet->Flags.TcpChecksumNotValidated = 1;
+        } else if (Transmitter->ValidateChecksums != 0) {
+            USHORT      Embedded;
+            USHORT      Calculated;
+
+            Embedded = TcpHeader->Checksum;
+
+            Calculated = ChecksumPseudoHeader(StartVa, Info);
+            Calculated = ChecksumTcpPacket(StartVa, Info, Calculated, Payload);
+
+            if (ChecksumVerify(Calculated, Embedded))
+                Packet->Flags.TcpChecksumSucceeded = 1;
+            else
+                Packet->Flags.TcpChecksumFailed = 1;
+        } else {
+            Packet->Flags.TcpChecksumNotValidated = 1;
+        }
+    }
+
+    if (Info->UdpHeader.Length != 0) {
+        PUDP_HEADER UdpHeader;
+
+        UdpHeader = (PUDP_HEADER)(StartVa + Info->UdpHeader.Offset);
+
+        if (Packet->OffloadOptions.OffloadIpVersion4UdpChecksum ||
+            Packet->OffloadOptions.OffloadIpVersion6UdpChecksum) {
+            UdpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info);
+
+            Packet->Flags.UdpChecksumNotValidated = 1;
+        } else if (Transmitter->ValidateChecksums != 0) {
+            PIP_HEADER  IpHeader;
+            USHORT      Embedded;
+
+            ASSERT(Info->IpHeader.Length != 0);
+            IpHeader = (PIP_HEADER)(StartVa + Info->IpHeader.Offset);
+
+            Embedded = UdpHeader->Checksum;
+
+            // Tolarate zero checksum for IPv4/UDP
+            if (IpHeader->Version == 4 && Embedded == 0) {
+                Packet->Flags.UdpChecksumSucceeded = 1;
+            } else {
+                USHORT  Calculated;
+
+                Calculated = ChecksumPseudoHeader(StartVa, Info);
+                Calculated = ChecksumUdpPacket(StartVa, Info, Calculated, 
Payload);
+
+                if (ChecksumVerify(Calculated, Embedded))
+                    Packet->Flags.UdpChecksumSucceeded = 1;
+                else
+                    Packet->Flags.UdpChecksumFailed = 1;
+            }
+        } else {
+            Packet->Flags.UdpChecksumNotValidated = 1;
+        }
     }
 
     return STATUS_SUCCESS;
 
 fail5:
-    Error("fail5\n");
+    if (!SquashError)
+        Error("fail5\n");
 
     ASSERT(State->Count != 0);
     --State->Count;
@@ -1398,7 +1489,8 @@ fail5:
     Fragment->Entry = NULL;
 
 fail4:
-    Error("fail4\n");
+    if (!SquashError)
+        Error("fail4\n");
 
     Fragment->Context = NULL;
     Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
@@ -1409,7 +1501,8 @@ fail4:
     __TransmitterPutFragment(Ring, Fragment);
 
 fail3:
-    Error("fail3\n");
+    if (!SquashError)
+        Error("fail3\n");
 
     --Packet->Reference;
     Buffer->Context = NULL;
@@ -1417,12 +1510,14 @@ fail3:
     __TransmitterPutBuffer(Ring, Buffer);
 
 fail2:
-    Error("fail2\n");
+    if (!SquashError)
+        Error("fail2\n");
 
     ASSERT3U(Packet->Reference, ==, 0);
 
 fail1:
-    Error("fail1 (%08x)\n", status);
+    if (!SquashError)
+        Error("fail1 (%08x)\n", status);
 
     return status;
 }
@@ -1647,13 +1742,9 @@ __TransmitterRingPreparePacket(
     return STATUS_SUCCESS;
 
 fail2:
-    Error("fail2\n");
-
     __TransmitterRingUnprepareFragments(Ring);
 
 fail1:
-    Error("fail1 (%08x)\n", status);
-
     ASSERT(IsListEmpty(&State->List));
     RtlZeroMemory(&State->List, sizeof (LIST_ENTRY));
 
@@ -2265,26 +2356,7 @@ __TransmitterRingPostFragments(
     ASSERT3U(State->Count, ==, 0);
     RtlZeroMemory(&State->List, sizeof (LIST_ENTRY));
 
-    // Set the initial completion information
     if (Packet != NULL) {
-        PUCHAR                  StartVa;
-        PXENVIF_PACKET_INFO     Info;
-        PXENVIF_PACKET_PAYLOAD  Payload;
-        PETHERNET_HEADER        Header;
-
-        StartVa = Packet->Header;
-        Info = &Packet->Info;
-        Payload = &Packet->Payload;
-
-        ASSERT(IsZeroMemory(&Packet->Completion, sizeof 
(XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO)));
-
-        ASSERT(Info->EthernetHeader.Length != 0);
-        Header = (PETHERNET_HEADER)(StartVa + Info->EthernetHeader.Offset);
-
-        Packet->Completion.Type = 
GET_ETHERNET_ADDRESS_TYPE(&Header->Untagged.DestinationAddress);
-        Packet->Completion.PacketLength = (USHORT)Packet->Length;
-        Packet->Completion.PayloadLength = (USHORT)Payload->Length;
-
         State->Packet = NULL;
 
         Ring->PacketsSent++;
@@ -2374,8 +2446,14 @@ __TransmitterRingCompletePacket(
     IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
-    PXENVIF_TRANSMITTER                 Transmitter;
-    PXENVIF_FRONTEND                    Frontend;
+    PXENVIF_TRANSMITTER             Transmitter;
+    PXENVIF_FRONTEND                Frontend;
+    PXENVIF_PACKET_PAYLOAD          Payload;
+    PXENVIF_PACKET_INFO             Info;
+    PUCHAR                          StartVa;
+    PETHERNET_HEADER                EthernetHeader;
+    PETHERNET_ADDRESS               DestinationAddress;
+    ETHERNET_ADDRESS_TYPE           Type;
 
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
@@ -2391,45 +2469,145 @@ __TransmitterRingCompletePacket(
             FrontendIncrementStatistic(Frontend,
                                        XENVIF_TRANSMITTER_BACKEND_ERRORS,
                                        1);
-    } else {
-        ULONG   Length;
 
-        Length = (ULONG)Packet->Completion.PacketLength;
+        goto done;
+    }
 
-        switch (Packet->Completion.Type) {
-        case ETHERNET_ADDRESS_UNICAST:
-            FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                                       1);
-            FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                                       Length);
-            break;
-            
-        case ETHERNET_ADDRESS_MULTICAST:
+    StartVa = Packet->Header;
+    Info = &Packet->Info;
+    Payload = &Packet->Payload;
+
+    ASSERT(Info->EthernetHeader.Length != 0);
+    EthernetHeader = (PETHERNET_HEADER)(StartVa + Info->EthernetHeader.Offset);
+
+    DestinationAddress = &EthernetHeader->DestinationAddress;
+
+    Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
+
+    switch (Type) {
+    case ETHERNET_ADDRESS_UNICAST:
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                                   1);
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                                   Packet->Length);
+        break;
+
+    case ETHERNET_ADDRESS_MULTICAST:
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                                   1);
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                                   Packet->Length);
+        break;
+
+    case ETHERNET_ADDRESS_BROADCAST:
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                                   1);
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                                   Packet->Length);
+        break;
+
+    default:
+        ASSERT(FALSE);
+        break;
+    }
+
+    if (ETHERNET_HEADER_IS_TAGGED(EthernetHeader))
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_TAGGED_PACKETS,
+                                   1);
+
+    if (Info->LLCSnapHeader.Length != 0)
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_LLC_SNAP_PACKETS,
+                                   1);
+
+    if (Info->IpHeader.Length != 0) {
+        PIP_HEADER  IpHeader = (PIP_HEADER)(StartVa + Info->IpHeader.Offset);
+
+        if (IpHeader->Version == 4) {
             FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                                       XENVIF_TRANSMITTER_IPV4_PACKETS,
                                        1);
-            FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                                       Length);
-            break;
+        } else {
+            ASSERT3U(IpHeader->Version, ==, 6);
 
-        case ETHERNET_ADDRESS_BROADCAST:
             FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                                       XENVIF_TRANSMITTER_IPV6_PACKETS,
                                        1);
-            FrontendIncrementStatistic(Frontend,
-                                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                                       Length);
-            break;
-
-        default:
-            ASSERT(FALSE);
-            break;
         }
     }
 
+    if (Info->TcpHeader.Length != 0)
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_TCP_PACKETS,
+                                   1);
+
+    if (Info->UdpHeader.Length != 0)
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_UDP_PACKETS,
+                                   1);
+
+    if (Packet->MaximumSegmentSize != 0)
+        FrontendIncrementStatistic(Frontend,
+                                   XENVIF_TRANSMITTER_GSO_PACKETS,
+                                   1);
+
+   if (Packet->Flags.IpChecksumSucceeded != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_IPV4_CHECKSUM_SUCCEEDED,
+                                  1);
+
+   if (Packet->Flags.IpChecksumFailed != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_IPV4_CHECKSUM_FAILED,
+                                  1);
+
+   if (Packet->Flags.IpChecksumNotValidated != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  
XENVIF_TRANSMITTER_IPV4_CHECKSUM_NOT_VALIDATED,
+                                  1);
+
+   if (Packet->Flags.TcpChecksumSucceeded != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_TCP_CHECKSUM_SUCCEEDED,
+                                  1);
+
+   if (Packet->Flags.TcpChecksumFailed != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_TCP_CHECKSUM_FAILED,
+                                  1);
+
+   if (Packet->Flags.TcpChecksumNotValidated != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  
XENVIF_TRANSMITTER_TCP_CHECKSUM_NOT_VALIDATED,
+                                  1);
+
+   if (Packet->Flags.UdpChecksumSucceeded != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_UDP_CHECKSUM_SUCCEEDED,
+                                  1);
+
+   if (Packet->Flags.UdpChecksumFailed != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  XENVIF_TRANSMITTER_UDP_CHECKSUM_FAILED,
+                                  1);
+
+   if (Packet->Flags.UdpChecksumNotValidated != 0)
+       FrontendIncrementStatistic(Frontend,
+                                  
XENVIF_TRANSMITTER_UDP_CHECKSUM_NOT_VALIDATED,
+                                  1);
+
+    Packet->Completion.Type = Type;
+    Packet->Completion.PacketLength = (USHORT)Packet->Length;
+    Packet->Completion.PayloadLength = (USHORT)Payload->Length;
+
+done:
     InsertTailList(&Ring->PacketComplete, &Packet->ListEntry);
     Ring->PacketsCompleted++;
 }
@@ -2826,6 +3004,8 @@ TransmitterRingSchedule(
 
             Packet->Reference = 0;
 
+            ASSERT3U(Packet->Completion.Status, ==, 0);
+
             status = __TransmitterRingPreparePacket(Ring, Packet);
             if (!NT_SUCCESS(status)) {
                 PXENVIF_TRANSMITTER Transmitter;
@@ -2843,10 +3023,6 @@ TransmitterRingSchedule(
 
                 Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
 
-                FrontendIncrementStatistic(Frontend,
-                                           XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                                           1);
-
                 __TransmitterRingCompletePacket(Ring, Packet);
             }
 
@@ -4263,11 +4439,13 @@ TransmitterInitialize(
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
+    (*Transmitter)->ValidateChecksums = 0;
 
     if (ParametersKey != NULL) {
         ULONG   TransmitterDisableIpVersion4Gso;
         ULONG   TransmitterDisableIpVersion6Gso;
         ULONG   TransmitterAlwaysCopy;
+        ULONG   TransmitterValidateChecksums;
 
         status = RegistryQueryDwordValue(ParametersKey,
                                          "TransmitterDisableIpVersion4Gso",
@@ -4286,6 +4464,12 @@ TransmitterInitialize(
                                          &TransmitterAlwaysCopy);
         if (NT_SUCCESS(status))
             (*Transmitter)->AlwaysCopy = TransmitterAlwaysCopy;
+
+        status = RegistryQueryDwordValue(ParametersKey,
+                                         "TransmitterValidateChecksums",
+                                         &TransmitterValidateChecksums);
+        if (NT_SUCCESS(status))
+            (*Transmitter)->ValidateChecksums = TransmitterValidateChecksums;
     }
 
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
@@ -4370,6 +4554,7 @@ fail2:
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
+    (*Transmitter)->ValidateChecksums = 0;
     
     ASSERT(IsZeroMemory(*Transmitter, sizeof (XENVIF_TRANSMITTER)));
     __TransmitterFree(*Transmitter);
@@ -4783,6 +4968,7 @@ TransmitterTeardown(
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
+    Transmitter->ValidateChecksums = 0;
 
     ASSERT(IsZeroMemory(Transmitter, sizeof (XENVIF_TRANSMITTER)));
     __TransmitterFree(Transmitter);
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.