IN XENVIF_VIF_OFFLOAD_OPTIONS Options
);
+/*! \typedef XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE
+ \brief Set the required receive backfill size (free space before
+ packet payload).
+
+ \param Interface The interface header
+ \param Size The required size
+*/
+typedef VOID
+(*XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE)(
+ IN PINTERFACE Interface,
+ IN ULONG Size
+ );
+
/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
\brief Query the maximum size of packet containing a TCP large segment
that can be handled by the transmit side
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-
/*! \struct _XENVIF_VIF_INTERFACE_V2
\brief VIF interface version 2
\ingroup interfaces
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+/*! \struct _XENVIF_VIF_INTERFACE_V3
+ \brief VIF interface version 3
+ \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V3 {
+ INTERFACE Interface;
+ XENVIF_VIF_ACQUIRE Acquire;
+ XENVIF_VIF_RELEASE Release;
+ XENVIF_VIF_ENABLE Enable;
+ XENVIF_VIF_DISABLE Disable;
+ XENVIF_VIF_QUERY_STATISTIC QueryStatistic;
+ XENVIF_VIF_RECEIVER_RETURN_PACKETS ReceiverReturnPackets;
+ XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
+ XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE ReceiverSetBackfillSize;
+ XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
+ XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS TransmitterGetPacketHeaders;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2 TransmitterQueuePackets;
+ XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions;
+ XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize;
+ XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
+ XENVIF_VIF_MAC_QUERY_STATE MacQueryState;
+ XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE MacQueryMaximumFrameSize;
+ XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS MacQueryPermanentAddress;
+ XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS MacQueryCurrentAddress;
+ XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES MacQueryMulticastAddresses;
+ XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES MacSetMulticastAddresses;
+ XENVIF_VIF_MAC_SET_FILTER_LEVEL MacSetFilterLevel;
+ XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V3 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
/*! \def XENVIF_VIF
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENVIF_VIF_INTERFACE_VERSION_MIN 1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX 2
+#define XENVIF_VIF_INTERFACE_VERSION_MAX 3
#endif // _XENVIF_INTERFACE_H
HKR, Ndi\params\LROIPv6\enum, "0", 0, %Disabled%
HKR, Ndi\params\LROIPv6\enum, "1", 0, %Enabled%
+HKR, Ndi\params\*HeaderDataSplit, ParamDesc, 0, %HeaderDataSplit%
+HKR, Ndi\params\*HeaderDataSplit, Type, 0, "enum"
+HKR, Ndi\params\*HeaderDataSplit, Default, 0, "0"
+HKR, Ndi\params\*HeaderDataSplit, Optional, 0, "0"
+HKR, Ndi\params\*HeaderDataSplit\enum, "0", 0, %Disabled%
+HKR, Ndi\params\*HeaderDataSplit\enum, "1", 0, %Enabled%
+
[XenNet_Inst.Services]
AddService=xennet,0x02,XenNet_Service,XenNet_EventLog
LSOV2IPv6="Large Send Offload V2 (IPv6)"
LROIPv4="Large Receive Offload (IPv4)"
LROIPv6="Large Receive Offload (IPv6)"
+HeaderDataSplit="Header Data Split"
Disabled="Disabled"
Enabled="Enabled"
Enabled-Rx="Rx Enabled"
#include "dbg_print.h"
#include "assert.h"
+typedef struct _PROPERTIES {
+ int ipv4_csum;
+ int tcpv4_csum;
+ int udpv4_csum;
+ int tcpv6_csum;
+ int udpv6_csum;
+ int need_csum_value;
+ int lsov4;
+ int lsov6;
+ int lrov4;
+ int lrov6;
+ ULONG HeaderDataSplit;
+} PROPERTIES, *PPROPERTIES;
+
struct _XENNET_ADAPTER {
XENVIF_VIF_INTERFACE VifInterface;
XENBUS_CACHE_INTERFACE CacheInterface;
OID_PNP_CAPABILITIES,
OID_PNP_QUERY_POWER,
OID_PNP_SET_POWER,
+ OID_GEN_HD_SPLIT_PARAMETERS,
};
#define ADAPTER_POOL_TAG 'AteN'
TxOptions->OffloadIpVersion6UdpChecksum = 1;
RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
-
RxOptions->Value = 0;
RxOptions->OffloadTagManipulation = 1;
#undef TX_ENABLED
#undef CHANGE
+static NDIS_STATUS
+AdapterGetHeaderDataSplitParameters(
+ IN PXENNET_ADAPTER Adapter,
+ IN PNDIS_HD_SPLIT_PARAMETERS Split
+ )
+{
+ if (Split->HDSplitCombineFlags == NDIS_HD_SPLIT_COMBINE_ALL_HEADERS)
+ ReceiverSplitHeaderData(Adapter->Receiver, 0);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
static NDIS_STATUS
AdapterQueryGeneralStatistics(
IN PXENNET_ADAPTER Adapter,
}
break;
+ case OID_GEN_HD_SPLIT_PARAMETERS:
+ BytesNeeded = sizeof(NDIS_HD_SPLIT_PARAMETERS);
+ if (BufferLength >= BytesNeeded) {
+ ndisStatus = AdapterGetHeaderDataSplitParameters(Adapter,
+ (PNDIS_HD_SPLIT_PARAMETERS)Buffer);
+ if (ndisStatus == NDIS_STATUS_SUCCESS)
+ BytesRead = sizeof(NDIS_HD_SPLIT_PARAMETERS);
+ }
+ break;
+
case OID_GEN_INTERRUPT_MODERATION:
case OID_GEN_MACHINE_NAME:
Warn = FALSE;
READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle);
READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle);
READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle);
+ READ_PROPERTY(Adapter->Properties.HeaderDataSplit, L"*HeaderDataSplit", 1, Handle);
NdisCloseConfiguration(Handle);
return ndisStatus;
}
+static NDIS_STATUS
+AdapterSetHeaderDataSplitAttributes(
+ IN PXENNET_ADAPTER Adapter
+ )
+{
+ NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES Attribs;
+ NDIS_HD_SPLIT_ATTRIBUTES Split;
+ NDIS_STATUS NdisStatus;
+
+ RtlZeroMemory(&Attribs, sizeof(Attribs));
+
+ Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;
+ Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
+ Attribs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
+
+ RtlZeroMemory(&Split, sizeof(Split));
+
+ Split.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;
+ Split.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1;
+ Split.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;
+ Split.HardwareCapabilities =
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT |
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS |
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS |
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;
+
+ if (Adapter->Properties.HeaderDataSplit != 0)
+ Split.CurrentCapabilities = Split.HardwareCapabilities;
+
+ Attribs.HDSplitAttributes = &Split;
+
+ NdisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ goto fail1;
+
+ if (Split.HDSplitFlags == NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) {
+ ASSERT(Split.CurrentCapabilities & NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT);
+
+ Info("BackfillSize = %u\n", Split.BackfillSize);
+ Info("MaxHeaderSize = %u\n", Split.MaxHeaderSize);
+
+ XENVIF_VIF(ReceiverSetBackfillSize,
+ &Adapter->VifInterface,
+ Split.BackfillSize);
+
+ ReceiverSplitHeaderData(Adapter->Receiver, Split.MaxHeaderSize);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", NdisStatus);
+
+ return NdisStatus;
+}
+
NDIS_STATUS
AdapterInitialize(
IN NDIS_HANDLE Handle,
if (ndisStatus != NDIS_STATUS_SUCCESS)
goto fail11;
+ ndisStatus = AdapterSetHeaderDataSplitAttributes(*Adapter);
+ if (ndisStatus != NDIS_STATUS_SUCCESS)
+ goto fail12;
+
RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION));
Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
Dma.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
ndisStatus = AdapterEnable(*Adapter);
if (ndisStatus != NDIS_STATUS_SUCCESS)
- goto fail12;
+ goto fail13;
return NDIS_STATUS_SUCCESS;
-fail12:
+fail13:
if ((*Adapter)->NdisDmaHandle)
NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
(*Adapter)->NdisDmaHandle = NULL;
+fail12:
fail11:
fail10:
fail9:
NDIS_PACKET_TYPE_BROADCAST | \
NDIS_PACKET_TYPE_PROMISCUOUS)
-typedef struct _PROPERTIES {
- int ipv4_csum;
- int tcpv4_csum;
- int udpv4_csum;
- int tcpv6_csum;
- int udpv6_csum;
- int need_csum_value;
- int lsov4;
- int lsov6;
- int lrov4;
- int lrov6;
-} PROPERTIES, *PPROPERTIES;
-
typedef struct _XENNET_ADAPTER XENNET_ADAPTER, *PXENNET_ADAPTER;
extern NDIS_STATUS
* SUCH DAMAGE.
*/
+#include <ndis.h>
+#include <util.h>
+#include <tcpip.h>
+
#include "receiver.h"
#include "adapter.h"
-#include <util.h>
#include "dbg_print.h"
#include "assert.h"
LONG InNDIS;
LONG InNDISMax;
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
+ ULONG MaxHeaderSize;
};
#define RECEIVER_POOL_TAG 'RteN'
static PNET_BUFFER_LIST
__ReceiverReceivePacket(
- IN PXENNET_RECEIVER Receiver,
- IN PMDL Mdl,
- IN ULONG Offset,
- IN ULONG Length,
- IN XENVIF_PACKET_CHECKSUM_FLAGS Flags,
- IN USHORT TagControlInformation
+ IN PXENNET_RECEIVER Receiver,
+ IN PMDL Mdl,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN XENVIF_PACKET_CHECKSUM_FLAGS Flags,
+ IN PXENVIF_PACKET_INFO Info
)
{
PNET_BUFFER_LIST NetBufferList;
+ PNET_BUFFER NetBuffer;
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
NetBufferList = __ReceiverAllocateNetBufferList(Receiver,
if (NetBufferList == NULL)
goto fail1;
+ NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+
NetBufferList->SourceHandle = AdapterGetHandle(Receiver->Adapter);
csumInfo.Value = 0;
NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = (PVOID)(ULONG_PTR)csumInfo.Value;
- if (TagControlInformation != 0) {
+ if (Info->TagControlInformation != 0) {
NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
- UNPACK_TAG_CONTROL_INFORMATION(TagControlInformation,
+ UNPACK_TAG_CONTROL_INFORMATION(Info->TagControlInformation,
Ieee8021QInfo.TagHeader.UserPriority,
Ieee8021QInfo.TagHeader.CanonicalFormatId,
Ieee8021QInfo.TagHeader.VlanId);
NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = Ieee8021QInfo.Value;
}
+ if (Info->IpHeader.Offset != 0) {
+ ULONG NblFlags;
+ PUCHAR InfoVa;
+ PIP_HEADER IpHeader;
+ NDIS_PHYSICAL_ADDRESS DataPhysicalAddress;
+
+ NblFlags = NET_BUFFER_LIST_NBL_FLAGS(NetBufferList);
+
+ InfoVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ ASSERT(InfoVa != NULL);
+ InfoVa += Offset;
+
+ IpHeader = (PIP_HEADER)(InfoVa + Info->IpHeader.Offset);
+
+ if (IpHeader->Version == 4) {
+ NblFlags |= NDIS_NBL_FLAGS_IS_IPV4;
+ } else {
+ ASSERT3U(IpHeader->Version, ==, 6);
+ NblFlags |= NDIS_NBL_FLAGS_IS_IPV6;
+ }
+
+ if (Info->TcpHeader.Offset != 0)
+ NblFlags |= NDIS_NBL_FLAGS_IS_TCP;
+ else if (Info->UdpHeader.Offset != 0)
+ NblFlags |= NDIS_NBL_FLAGS_IS_UDP;
+
+ if (Mdl->Next != NULL && Info->Length < Receiver->MaxHeaderSize) {
+ NblFlags |= NDIS_NBL_FLAGS_HD_SPLIT;
+ if (NblFlags & (NDIS_NBL_FLAGS_IS_TCP | NDIS_NBL_FLAGS_IS_UDP))
+ NblFlags |= NDIS_NBL_FLAGS_SPLIT_AT_UPPER_LAYER_PROTOCOL_PAYLOAD;
+ else
+ NblFlags |= NDIS_NBL_FLAGS_SPLIT_AT_UPPER_LAYER_PROTOCOL_HEADER;
+
+ DataPhysicalAddress.QuadPart = (ULONGLONG)MmGetMdlPfnArray(Mdl->Next)[0] << PAGE_SHIFT;
+ DataPhysicalAddress.QuadPart += Mdl->Next->ByteOffset;
+
+ NET_BUFFER_DATA_PHYSICAL_ADDRESS(NetBuffer) = DataPhysicalAddress;
+ }
+
+ NET_BUFFER_LIST_NBL_FLAGS(NetBufferList) = NblFlags;
+ }
+
return NetBufferList;
fail2:
ULONG Offset;
ULONG Length;
XENVIF_PACKET_CHECKSUM_FLAGS Flags;
- USHORT TagControlInformation;
PNET_BUFFER_LIST NetBufferList;
if (!LowResources &&
Offset = Packet->Offset;
Length = Packet->Length;
Flags = Packet->Flags;
-
Info = Packet->Info;
- TagControlInformation = Info->TagControlInformation;
-
- NetBufferList = __ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
+ NetBufferList = __ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, Info);
if (NetBufferList != NULL) {
*TailNetBufferList = NetBufferList;
{
return &Receiver->OffloadOptions;
}
+
+VOID
+ReceiverSplitHeaderData(
+ IN PXENNET_RECEIVER Receiver,
+ IN ULONG MaxHeaderSize
+ )
+{
+ Receiver->MaxHeaderSize = MaxHeaderSize;
+}
IN PXENNET_RECEIVER Receiver
);
+extern VOID
+ReceiverSplitHeaderData(
+ IN PXENNET_RECEIVER Receiver,
+ IN ULONG MaxHeaderSize
+ );
+
#endif // _XENNET_RECEIVER_H_