[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |