ULONG Offset;
ULONG Length;
PUCHAR Header;
+ XENVIF_PACKET_HASH Hash;
XENVIF_PACKET_INFO Info;
XENVIF_PACKET_PAYLOAD Payload;
} XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
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
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,
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,
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;
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);
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));
req->flags = NETTXF_more_data;
if (FirstRequest) {
+ struct netif_extra_info *extra = NULL;
+
FirstRequest = FALSE;
if (OffloadOptions.OffloadIpVersion4TcpChecksum ||
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;
}
}
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];
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++;
for (;;) {
RING_IDX rsp_prod;
RING_IDX rsp_cons;
+ ULONG Extra;
KeMemoryBarrier();
if (rsp_cons == rsp_prod || Retry)
break;
+ Extra = 0;
while (rsp_cons != rsp_prod && !Retry) {
netif_tx_response_t *rsp;
uint16_t id;
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;
Fragment->Entry = NULL;
}
- Fragment->Extra = FALSE;
+ Extra = Fragment->Extra;
+ Fragment->Extra = 0;
__TransmitterPutFragment(Ring, Fragment);
if (Packet == NULL)
if (rsp_cons - Ring->Front.rsp_cons > XENVIF_TRANSMITTER_BATCH(Ring))
Retry = TRUE;
}
+ ASSERT3U(Extra, ==, 0);
KeMemoryBarrier();
Packet->OffloadOptions = OffloadOptions;
Packet->MaximumSegmentSize = MaximumSegmentSize;
Packet->TagControlInformation = TagControlInformation;
+ Packet->Hash = *Hash;
Packet->Cookie = Cookie;
StartVa = Packet->Header;