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

[win-pv-devel] [PATCH 2/2] Add header/data split support



Now that XENNET is using NDIS 6.1, implement header/data split. See
NDIS documentation for more details. This requires using version 3 of the
VIF interface from XENVIF to support the requirements for data MDL
backfill.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/vif_interface.h |  48 ++++++++++++++++++++--
 src/xennet.inf          |   8 ++++
 src/xennet/adapter.c    | 105 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/xennet/adapter.h    |  13 ------
 src/xennet/receiver.c   |  82 ++++++++++++++++++++++++++++++-------
 src/xennet/receiver.h   |   6 +++
 6 files changed, 229 insertions(+), 33 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index d083fd1..e5f8534 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -564,6 +564,19 @@ typedef VOID
     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
@@ -760,7 +773,6 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-
 /*! \struct _XENVIF_VIF_INTERFACE_V2
     \brief VIF interface version 2
     \ingroup interfaces
@@ -790,7 +802,37 @@ struct _XENVIF_VIF_INTERFACE_V2 {
     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
@@ -801,6 +843,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V2 
XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
 #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
diff --git a/src/xennet.inf b/src/xennet.inf
index 7e9d9e6..5aa8c6c 100644
--- a/src/xennet.inf
+++ b/src/xennet.inf
@@ -159,6 +159,13 @@ HKR, Ndi\params\LROIPv6,                          
Optional,   0, "0"
 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
 
@@ -202,6 +209,7 @@ LSOV2IPv4="Large Send Offload V2 (IPv4)"
 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"
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index a1460c7..1e88754 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -44,6 +44,20 @@
 #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;
@@ -115,6 +129,7 @@ static NDIS_OID XennetSupportedOids[] =
     OID_PNP_CAPABILITIES,
     OID_PNP_QUERY_POWER,
     OID_PNP_SET_POWER,
+    OID_GEN_HD_SPLIT_PARAMETERS,
 };
 
 #define ADAPTER_POOL_TAG    'AteN'
@@ -510,7 +525,6 @@ AdapterGetOffloadEncapsulation(
         TxOptions->OffloadIpVersion6UdpChecksum = 1;
 
     RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
-
     RxOptions->Value = 0;
     RxOptions->OffloadTagManipulation = 1;
 
@@ -622,6 +636,18 @@ invalid_parameter:
 #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,
     IN  PNDIS_STATISTICS_INFO   Info,
@@ -1204,6 +1230,16 @@ AdapterSetInformation(
         }
         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;
@@ -1868,6 +1904,7 @@ AdapterGetAdvancedSettings(
     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);
 
@@ -2151,6 +2188,63 @@ AdapterSetOffloadAttributes(
     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,
@@ -2235,6 +2329,10 @@ AdapterInitialize(
     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;
@@ -2252,14 +2350,15 @@ AdapterInitialize(
 
     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:
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index 042b863..3cc1d90 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -52,19 +52,6 @@
                                          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
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index 98da49b..17ab27f 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -29,9 +29,12 @@
  * 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"
 
@@ -44,6 +47,7 @@ struct _XENNET_RECEIVER {
     LONG                        InNDIS;
     LONG                        InNDISMax;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+    ULONG                       MaxHeaderSize;
 };
 
 #define RECEIVER_POOL_TAG       'RteN'
@@ -166,15 +170,16 @@ __ReceiverReturnNetBufferLists(
 
 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,
@@ -184,6 +189,8 @@ __ReceiverReceivePacket(
     if (NetBufferList == NULL)
         goto fail1;
 
+    NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+
     NetBufferList->SourceHandle = AdapterGetHandle(Receiver->Adapter);
 
     csumInfo.Value = 0;
@@ -199,10 +206,10 @@ __ReceiverReceivePacket(
 
     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);
@@ -213,6 +220,48 @@ __ReceiverReceivePacket(
         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:
@@ -394,7 +443,6 @@ again:
         ULONG                           Offset;
         ULONG                           Length;
         XENVIF_PACKET_CHECKSUM_FLAGS    Flags;
-        USHORT                          TagControlInformation;
         PNET_BUFFER_LIST                NetBufferList;
 
         if (!LowResources &&
@@ -411,12 +459,9 @@ again:
         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;
@@ -454,3 +499,12 @@ ReceiverOffloadOptions(
 {
     return &Receiver->OffloadOptions;
 }
+
+VOID
+ReceiverSplitHeaderData(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  ULONG               MaxHeaderSize
+    )
+{
+    Receiver->MaxHeaderSize = MaxHeaderSize;
+}
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
index fb69b96..b2cc809 100644
--- a/src/xennet/receiver.h
+++ b/src/xennet/receiver.h
@@ -66,4 +66,10 @@ ReceiverOffloadOptions(
     IN  PXENNET_RECEIVER    Receiver
     );
 
+extern VOID
+ReceiverSplitHeaderData(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  ULONG               MaxHeaderSize
+    );
+
 #endif // _XENNET_RECEIVER_H_
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://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®.