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