1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
// Copyright (c) Microsoft Corporation. All rights reserved
#include "pch.hpp"
#include "netvadapter.h"
#include "txqueue.h"
NetvTxQueue::NetvTxQueue(
NETPACKETQUEUE Handle,
NetvAdapter & Adapter
) noexcept
: NetvQueue{Handle, Adapter, NetTxQueueGetRingCollection(Handle)}
{
NET_EXTENSION_QUERY extension;
NET_EXTENSION_QUERY_INIT(
&extension,
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME,
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1,
NetExtensionTypeFragment);
NetTxQueueGetExtension(m_handle, &extension, &VirtualAddressExtension);
NET_EXTENSION_QUERY_INIT(
&extension,
NET_PACKET_EXTENSION_GSO_NAME,
NET_PACKET_EXTENSION_GSO_VERSION_1,
NetExtensionTypePacket);
NetTxQueueGetExtension(m_handle, &extension, &UsoExtension);
EnlQueueHandle = EnlCreateQueue(Handle, TX);
}
_Use_decl_annotations_
void
NetvTxQueue::Destroy(
void
)
{
EnlDestroyQueue(EnlQueueHandle, TX);
}
void
NetvTxQueue::Start(
void
)
{
auto link = NetvEnlMLink[m_adapter.EnlIndex].LinkHandle[0];
auto port = &link->Ports[m_adapter.EnlPortIndex];
auto queue = &port->TxQueue[0];
NT_ASSERT(queue->State == Stopped);
queue->QueueNext = queue->QueueEnd = 0U;
EnlIndicateQueueState(EnlQueueHandle, Started);
}
void
NetvTxQueue::Stop(
void
)
{
EnlIndicateQueueState(EnlQueueHandle, Stopped);
}
_Use_decl_annotations_
void
NetvTxQueue::Advance(
void
)
{
auto pr = GetPacketRing();
auto pi = NetRingGetAllPackets(m_rings);
// drain Tx packets
for (; NetPacketIteratorHasAny(&pi); NetPacketIteratorAdvance(&pi))
{
auto packet = NetPacketIteratorGetPacket(&pi);
if (! packet->Scratch)
{
break;
}
auto fi = NetPacketIteratorGetFragments(&pi);
for (; NetFragmentIteratorHasAny(&fi); NetFragmentIteratorAdvance(&fi))
{
continue;
}
m_rings->Rings[NetRingTypeFragment]->BeginIndex =
NetFragmentIteratorGetIndex(&fi);
}
NetPacketIteratorSet(&pi);
// post Tx packets
EnlRingDoorBell(EnlQueueHandle, pr->EndIndex);
}
_Use_decl_annotations_
void
NetvTxQueue::Cancel(
void
)
{
auto ringBuffer = GetPacketRing();
EnlRingDoorBell(EnlQueueHandle, ringBuffer->EndIndex);
}
_Use_decl_annotations_
void
NetvTxQueue::SetNotify(
bool NotificationEnabled
)
{
EnlArmInterrupt(EnlQueueHandle, NotificationEnabled);
}
|