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

[win-pv-devel] [PATCH 4/4] Send transmit side hash value to the backend



Backends capable of supporting packet hashing on the guest receive side
are also capable of accepting hash values in an extra info fragment on
the guest transmit side. This patch adds code to construct and send the
extra info fragment if the packet metadata contains hash information and
the backend is able to process it.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenvif/transmitter.c | 171 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 131 insertions(+), 40 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 18f664d..3542a09 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -78,6 +78,7 @@ typedef struct _XENVIF_TRANSMITTER_PACKET {
     ULONG                                       Offset;
     ULONG                                       Length;
     PUCHAR                                      Header;
+    XENVIF_PACKET_HASH                          Hash;
     XENVIF_PACKET_INFO                          Info;
     XENVIF_PACKET_PAYLOAD                       Payload;
 } XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
@@ -150,7 +151,7 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT {
     PXENBUS_GNTTAB_ENTRY                Entry;
     ULONG                               Offset;
     ULONG                               Length;
-    BOOLEAN                             Extra;
+    ULONG                               Extra;
 } XENVIF_TRANSMITTER_FRAGMENT, *PXENVIF_TRANSMITTER_FRAGMENT;
 
 #define XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID  0x03FF
@@ -349,6 +350,7 @@ __TransmitterPutPacket(
 
     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));
 
     XENBUS_CACHE(Put,
@@ -626,7 +628,7 @@ __TransmitterPutFragment(
     ASSERT3U(Fragment->Type, ==, XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID);
     ASSERT3P(Fragment->Context, ==, NULL);
     ASSERT3P(Fragment->Entry, ==, NULL);
-    ASSERT(!Fragment->Extra);
+    ASSERT3U(Fragment->Extra, ==, 0);
 
     XENBUS_CACHE(Put,
                  &Transmitter->CacheInterface,
@@ -2041,6 +2043,8 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER_STATE       State;
     PXENVIF_TRANSMITTER_PACKET      Packet;
     XENVIF_VIF_OFFLOAD_OPTIONS      OffloadOptions;
+    USHORT                          MaximumSegmentSize;
+    XENVIF_PACKET_HASH              Hash;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
     ULONG                           Extra;
@@ -2056,10 +2060,15 @@ __TransmitterRingPostFragments(
     State = &Ring->State;
     Packet = State->Packet;
 
-    if (Packet != NULL)
+    if (Packet != NULL) {
         OffloadOptions = Packet->OffloadOptions;
-    else
+        MaximumSegmentSize = Packet->MaximumSegmentSize;
+        Hash = Packet->Hash;
+    } else {
         OffloadOptions.Value = 0;
+        MaximumSegmentSize = 0;
+        RtlZeroMemory(&Hash, sizeof (Hash));
+    }
 
     ASSERT(!IsListEmpty(&State->List));
     ASSERT(State->Count != 0);
@@ -2073,11 +2082,20 @@ __TransmitterRingPostFragments(
                                  XENVIF_TRANSMITTER_FRAGMENT,
                                  ListEntry);
 
-    Extra = (OffloadOptions.OffloadIpVersion4LargePacket ||
-             OffloadOptions.OffloadIpVersion6LargePacket ||
-             Fragment->Type == 
XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) ?
-            1 :
-            0;
+    Extra = 0;
+
+    if (OffloadOptions.OffloadIpVersion4LargePacket ||
+        OffloadOptions.OffloadIpVersion6LargePacket)
+        Extra++;
+
+    if (Fragment->Type == XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) {
+        ASSERT(Transmitter->MulticastControl);
+        Extra++;
+    }
+
+    if (Hash.Algorithm == XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ &&
+        Hash.Type != XENVIF_PACKET_HASH_TYPE_NONE)
+        Extra++;
 
     ASSERT3U(State->Count + Extra, <=, RING_SIZE(&Ring->Front));
 
@@ -2115,6 +2133,8 @@ __TransmitterRingPostFragments(
         req->flags = NETTXF_more_data;
 
         if (FirstRequest) {
+            struct netif_extra_info *extra = NULL;
+
             FirstRequest = FALSE;
 
             if (OffloadOptions.OffloadIpVersion4TcpChecksum ||
@@ -2124,49 +2144,109 @@ __TransmitterRingPostFragments(
                 req->flags |= NETTXF_csum_blank | NETTXF_data_validated;
 
             if (OffloadOptions.OffloadIpVersion4LargePacket ||
-                OffloadOptions.OffloadIpVersion6LargePacket ||
-                Fragment->Type == 
XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) {
-                struct netif_extra_info *extra;
+                OffloadOptions.OffloadIpVersion6LargePacket) {
+                ASSERT(req->flags & (NETTXF_csum_blank | 
NETTXF_data_validated));
 
-                ASSERT(Extra != 0);
-                Fragment->Extra = TRUE;
+                Fragment->Extra++;
+
+                ASSERT(!(req->flags & NETTXF_extra_info));
+                req->flags |= NETTXF_extra_info;
 
                 extra = (struct netif_extra_info 
*)RING_GET_REQUEST(&Ring->Front, req_prod);
                 req_prod++;
                 Ring->RequestsPosted++;
 
-                if (OffloadOptions.OffloadIpVersion4LargePacket ||
-                    OffloadOptions.OffloadIpVersion6LargePacket) {
-                    ASSERT(Packet->MaximumSegmentSize != 0);
+                RtlZeroMemory(extra, sizeof (struct netif_extra_info));
+
+                extra->type = XEN_NETIF_EXTRA_TYPE_GSO;
+
+                extra->u.gso.type = 
(OffloadOptions.OffloadIpVersion4LargePacket) ?
+                                    XEN_NETIF_GSO_TYPE_TCPV4 :
+                                    XEN_NETIF_GSO_TYPE_TCPV6;
+                extra->u.gso.size = MaximumSegmentSize;
+            }
+
+            if (Fragment->Type == 
XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) {
+                PXENVIF_TRANSMITTER_MULTICAST_CONTROL   Control;
+
+                Fragment->Extra++;
+
+                if (req->flags & NETTXF_extra_info) {
+                    ASSERT(extra != NULL);
+                    extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
+                } else {
+                    req->flags |= NETTXF_extra_info;
+                }
+
+                extra = (struct netif_extra_info 
*)RING_GET_REQUEST(&Ring->Front, req_prod);
+                req_prod++;
+                Ring->RequestsPosted++;
+
+                RtlZeroMemory(extra, sizeof (struct netif_extra_info));
+
+                Control = Fragment->Context;
+                switch (Control->Type) {
+                case XENVIF_TRANSMITTER_MULTICAST_CONTROL_TYPE_ADD:
+                    extra->type = XEN_NETIF_EXTRA_TYPE_MCAST_ADD;
+                    break;
+
+                case XENVIF_TRANSMITTER_MULTICAST_CONTROL_TYPE_REMOVE:
+                    extra->type = XEN_NETIF_EXTRA_TYPE_MCAST_DEL;
+                    break;
+
+                default:
+                    ASSERT(FALSE);
+                    break;
+                }
 
-                    extra->type = XEN_NETIF_EXTRA_TYPE_GSO;
-                    extra->flags = 0;
+                RtlCopyMemory(&extra->u.mcast.addr,
+                              &Control->Address.Byte[0],
+                              ETHERNET_ADDRESS_LENGTH);
+            }
 
-                    extra->u.gso.type = 
(OffloadOptions.OffloadIpVersion4LargePacket) ?
-                                        XEN_NETIF_GSO_TYPE_TCPV4 :
-                                        XEN_NETIF_GSO_TYPE_TCPV6;
-                    extra->u.gso.size = Packet->MaximumSegmentSize;
-                    extra->u.gso.pad = 0;
-                    extra->u.gso.features = 0;
+            if (Hash.Algorithm == XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ &&
+                Hash.Type != XENVIF_PACKET_HASH_TYPE_NONE) {
 
-                    ASSERT(req->flags & (NETTXF_csum_blank | 
NETTXF_data_validated));
+                if (req->flags & NETTXF_extra_info) {
+                    ASSERT(extra != NULL);
+                    extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
                 } else {
-                    PXENVIF_TRANSMITTER_MULTICAST_CONTROL   Control;
+                    req->flags |= NETTXF_extra_info;
+                }
+
+                Fragment->Extra++;
+
+                extra = (struct netif_extra_info 
*)RING_GET_REQUEST(&Ring->Front, req_prod);
+                req_prod++;
+                Ring->RequestsPosted++;
 
-                    ASSERT(Fragment->Type == 
XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL);
-                    Control = Fragment->Context;
+                RtlZeroMemory(extra, sizeof (struct netif_extra_info));
 
-                    extra->type = (Control->Type == 
XENVIF_TRANSMITTER_MULTICAST_CONTROL_TYPE_ADD) ?
-                        XEN_NETIF_EXTRA_TYPE_MCAST_ADD :
-                        XEN_NETIF_EXTRA_TYPE_MCAST_DEL;
-                    extra->flags = 0;
+                extra->type = XEN_NETIF_EXTRA_TYPE_HASH;
 
-                    RtlCopyMemory(&extra->u.mcast.addr,
-                                  &Control->Address.Byte[0],
-                                  ETHERNET_ADDRESS_LENGTH);
+                switch (Hash.Type) {
+                case XENVIF_PACKET_HASH_TYPE_IPV4:
+                    extra->u.hash.type = _XEN_NETIF_CTRL_HASH_TYPE_IPV4;
+                    break;
+
+                case XENVIF_PACKET_HASH_TYPE_IPV4_TCP:
+                    extra->u.hash.type = _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP;
+                    break;
+
+                case XENVIF_PACKET_HASH_TYPE_IPV6:
+                    extra->u.hash.type = _XEN_NETIF_CTRL_HASH_TYPE_IPV6;
+                    break;
+
+                case XENVIF_PACKET_HASH_TYPE_IPV6_TCP:
+                    extra->u.hash.type = _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP;
+                    break;
+
+                default:
+                    ASSERT(FALSE);
+                    break;
                 }
 
-                req->flags |= NETTXF_extra_info;
+                *(uint32_t *)extra->u.hash.value = Hash.Value;
             }
         }
 
@@ -2245,6 +2325,7 @@ __TransmitterRingFakeResponses(
     for (id = 0; id <= XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID; id++) {
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
         netif_tx_response_t             *rsp;
+        ULONG                           Extra;
 
         Fragment = Ring->Pending[id];
 
@@ -2258,7 +2339,7 @@ __TransmitterRingFakeResponses(
         rsp->id = Fragment->Id;
         rsp->status = NETIF_RSP_DROPPED;
 
-        if (Fragment->Extra) {
+        for (Extra = 0; Extra < Fragment->Extra; Extra++) {
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_prod);
             rsp_prod++;
             Count++;
@@ -2374,6 +2455,7 @@ TransmitterRingPoll(
     for (;;) {
         RING_IDX    rsp_prod;
         RING_IDX    rsp_cons;
+        ULONG       Extra;
 
         KeMemoryBarrier();
 
@@ -2385,6 +2467,7 @@ TransmitterRingPoll(
         if (rsp_cons == rsp_prod || Retry)
             break;
 
+        Extra = 0;
         while (rsp_cons != rsp_prod && !Retry) {
             netif_tx_response_t             *rsp;
             uint16_t                        id;
@@ -2397,8 +2480,13 @@ TransmitterRingPoll(
 
             Ring->Stopped = FALSE;
 
-            if (rsp->status == NETIF_RSP_NULL)
+            if (rsp->status == NETIF_RSP_NULL) {
+                ASSERT(Extra != 0);
+                --Extra;
                 continue;
+            }
+
+            ASSERT3U(Extra, ==, 0);
 
             id = rsp->id;
 
@@ -2474,7 +2562,8 @@ TransmitterRingPoll(
                 Fragment->Entry = NULL;
             }
 
-            Fragment->Extra = FALSE;
+            Extra = Fragment->Extra;
+            Fragment->Extra = 0;
             __TransmitterPutFragment(Ring, Fragment);
 
             if (Packet == NULL)
@@ -2510,6 +2599,7 @@ TransmitterRingPoll(
             if (rsp_cons - Ring->Front.rsp_cons > 
XENVIF_TRANSMITTER_BATCH(Ring))
                 Retry = TRUE;
         }
+        ASSERT3U(Extra, ==, 0);
 
         KeMemoryBarrier();
 
@@ -4817,6 +4907,7 @@ TransmitterQueuePacket(
     Packet->OffloadOptions = OffloadOptions;
     Packet->MaximumSegmentSize = MaximumSegmentSize;
     Packet->TagControlInformation = TagControlInformation;
+    Packet->Hash = *Hash;
     Packet->Cookie = Cookie;
 
     StartVa = Packet->Header;
-- 
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®.