summaryrefslogtreecommitdiff
path: root/network/netadaptercx/netvadapterlibrary/code/txqueue.cpp
blob: b67692b545be810346b866d05d56d2ea29a130a9 (plain)
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);
}