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 */
\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 */
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;
_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;
}
XENBUS_DEBUG(Printf,
&Frontend->DebugInterface,
- " - %40s %lu\n",
+ " - %40s %llu\n",
__FrontendStatisticName(Name),
Value);
}
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,
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 {
} while (status == STATUS_RETRY);
if (!NT_SUCCESS(status))
- goto fail8;
+ goto fail7;
State = XenbusStateUnknown;
while (State != XenbusStateConnected) {
status = STATUS_UNSUCCESSFUL;
if (State != XenbusStateConnected)
- goto fail9;
+ goto fail8;
ControllerEnable(__FrontendGetController(Frontend));
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);
XENBUS_DEBUG(Release, &Frontend->DebugInterface);
- __FrontendFree(Frontend->Statistics);
- Frontend->Statistics = NULL;
- Frontend->StatisticsCount = 0;
-
Trace("<====\n");
}
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");
ASSERT(Frontend->State == FRONTEND_UNKNOWN);
+ __FrontendFree(Frontend->Statistics);
+ Frontend->Statistics = NULL;
+ Frontend->StatisticsCount = 0;
+
ThreadAlert(Frontend->MibThread);
ThreadJoin(Frontend->MibThread);
Frontend->MibThread = NULL;
)
{
PXENVIF_RECEIVER Receiver;
+ PXENVIF_FRONTEND Frontend;
PXENVIF_PACKET_INFO Info;
XENVIF_PACKET_PAYLOAD Payload;
uint16_t flags;
PIP_HEADER IpHeader;
Receiver = Ring->Receiver;
+ Frontend = Receiver->Frontend;
Info = &Packet->Info;
OffloadChecksum = FALSE;
// IP header checksums are always present and not validated
-
if (OffloadChecksum) {
USHORT Embedded;
USHORT Calculated;
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;
}
}
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;
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;
}
}
}
Packet,
FIELD_OFFSET(XENVIF_RECEIVER_PACKET, Mdl));
+ Segment->MaximumSegmentSize = 0;
+
// The segment contains no data as yet
Segment->Length = 0;
PUCHAR StartVa;
PETHERNET_HEADER EthernetHeader;
PETHERNET_ADDRESS DestinationAddress;
- ETHERNET_ADDRESS_TYPE Type;
NTSTATUS status;
Receiver = Ring->Receiver;
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
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);
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,
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
USHORT MaximumSegmentSize;
USHORT TagControlInformation;
- XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion;
PMDL Mdl;
ULONG Offset;
ULONG Length;
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 {
ULONG DisableIpVersion4Gso;
ULONG DisableIpVersion6Gso;
ULONG AlwaysCopy;
+ ULONG ValidateChecksums;
KSPIN_LOCK Lock;
PXENBUS_CACHE PacketCache;
XENBUS_STORE_INTERFACE StoreInterface;
{
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,
PUCHAR StartVa;
PFN_NUMBER Pfn;
PETHERNET_HEADER EthernetHeader;
+ BOOLEAN SquashError;
NTSTATUS status;
Transmitter = Ring->Transmitter;
Payload = &Packet->Payload;
Info = &Packet->Info;
+ SquashError = FALSE;
+
status = STATUS_UNSUCCESSFUL;
if (Info->Length == 0)
goto fail1;
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
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
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;
Fragment->Entry = NULL;
fail4:
- Error("fail4\n");
+ if (!SquashError)
+ Error("fail4\n");
Fragment->Context = NULL;
Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
__TransmitterPutFragment(Ring, Fragment);
fail3:
- Error("fail3\n");
+ if (!SquashError)
+ Error("fail3\n");
--Packet->Reference;
Buffer->Context = NULL;
__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;
}
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));
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++;
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;
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++;
}
Packet->Reference = 0;
+ ASSERT3U(Packet->Completion.Status, ==, 0);
+
status = __TransmitterRingPreparePacket(Ring, Packet);
if (!NT_SUCCESS(status)) {
PXENVIF_TRANSMITTER Transmitter;
Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
- FrontendIncrementStatistic(Frontend,
- XENVIF_TRANSMITTER_FRONTEND_ERRORS,
- 1);
-
__TransmitterRingCompletePacket(Ring, Packet);
}
(*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",
&TransmitterAlwaysCopy);
if (NT_SUCCESS(status))
(*Transmitter)->AlwaysCopy = TransmitterAlwaysCopy;
+
+ status = RegistryQueryDwordValue(ParametersKey,
+ "TransmitterValidateChecksums",
+ &TransmitterValidateChecksums);
+ if (NT_SUCCESS(status))
+ (*Transmitter)->ValidateChecksums = TransmitterValidateChecksums;
}
FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
(*Transmitter)->DisableIpVersion4Gso = 0;
(*Transmitter)->DisableIpVersion6Gso = 0;
(*Transmitter)->AlwaysCopy = 0;
+ (*Transmitter)->ValidateChecksums = 0;
ASSERT(IsZeroMemory(*Transmitter, sizeof (XENVIF_TRANSMITTER)));
__TransmitterFree(*Transmitter);
Transmitter->DisableIpVersion4Gso = 0;
Transmitter->DisableIpVersion6Gso = 0;
Transmitter->AlwaysCopy = 0;
+ Transmitter->ValidateChecksums = 0;
ASSERT(IsZeroMemory(Transmitter, sizeof (XENVIF_TRANSMITTER)));
__TransmitterFree(Transmitter);