blob: f91e902db82d34c002df717c6713ca83a19caedf [file] [log] [blame]
Colm Donelana21620d2019-10-11 13:09:49 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matteo Martincigh65984272019-10-17 13:26:21 +01008#include <CommandHandlerRegistry.hpp>
9#include <Packet.hpp>
Rob Hughes25b74362020-01-13 11:14:59 +000010#include <NetworkSockets.hpp>
Matteo Martincigh65984272019-10-17 13:26:21 +010011
Colm Donelanb682d842019-10-16 12:24:20 +010012#include <atomic>
Colm Donelana21620d2019-10-11 13:09:49 +010013#include <string>
14#include <thread>
Colm Donelana21620d2019-10-11 13:09:49 +010015
Colm Donelana21620d2019-10-11 13:09:49 +010016namespace armnn
17{
18
19namespace gatordmock
20{
21
22enum class TargetEndianness
23{
Colm Donelanb682d842019-10-16 12:24:20 +010024 BeWire,
25 LeWire
Colm Donelana21620d2019-10-11 13:09:49 +010026};
27
28enum class PacketDirection
29{
Colm Donelanb682d842019-10-16 12:24:20 +010030 Sending,
31 ReceivedHeader,
32 ReceivedData
Colm Donelana21620d2019-10-11 13:09:49 +010033};
34
35/// A class that implements a Mock Gatord server. It will listen on a specified Unix domain socket (UDS)
36/// namespace for client connections. It will then allow opertaions to manage coutners while receiving counter data.
37class GatordMockService
38{
39public:
Colm Donelana21620d2019-10-11 13:09:49 +010040 /// @param registry reference to a command handler registry.
41 /// @param echoPackets if true the raw packets will be printed to stdout.
42 GatordMockService(armnn::profiling::CommandHandlerRegistry& registry, bool echoPackets)
43 : m_HandlerRegistry(registry)
44 , m_EchoPackets(echoPackets)
Colm Donelan02705242019-11-14 14:19:07 +000045 , m_CloseReceivingThread(false)
Colm Donelana21620d2019-10-11 13:09:49 +010046 {
47 m_PacketsReceivedCount.store(0, std::memory_order_relaxed);
48 }
49
50 ~GatordMockService()
51 {
52 // We have set SOCK_CLOEXEC on these sockets but we'll close them to be good citizens.
Rob Hughes25b74362020-01-13 11:14:59 +000053 armnnUtils::Sockets::Close(m_ClientConnection);
54 armnnUtils::Sockets::Close(m_ListeningSocket);
Colm Donelana21620d2019-10-11 13:09:49 +010055 }
56
57 /// Establish the Unix domain socket and set it to listen for connections.
58 /// @param udsNamespace the namespace (socket address) associated with the listener.
59 /// @return true only if the socket has been correctly setup.
60 bool OpenListeningSocket(std::string udsNamespace);
61
62 /// Block waiting to accept one client to connect to the UDS.
63 /// @return the file descriptor of the client connection.
Rob Hughes25b74362020-01-13 11:14:59 +000064 armnnUtils::Sockets::Socket BlockForOneClient();
Colm Donelana21620d2019-10-11 13:09:49 +010065
66 /// Once the connection is open wait to receive the stream meta data packet from the client. Reading this
67 /// packet differs from others as we need to determine endianness.
68 /// @return true only if a valid stream met data packet has been received.
69 bool WaitForStreamMetaData();
70
71 /// Send a connection acknowledged packet back to the client.
72 void SendConnectionAck();
73
Finn Williams15db7452019-10-15 14:22:13 +010074 /// Send a request counter directory packet back to the client.
75 void SendRequestCounterDir();
76
Colm Donelana21620d2019-10-11 13:09:49 +010077 /// Start the thread that will receive all packets and print them nicely to stdout.
78 bool LaunchReceivingThread();
79
80 /// Return the total number of periodic counter capture packets received since the receive thread started.
81 /// @return number of periodic counter capture packets received.
82 uint32_t GetPacketsReceivedCount()
83 {
84 return m_PacketsReceivedCount.load(std::memory_order_acquire);
85 }
86
87 /// This is a placeholder method to prevent main exiting. It can be removed once the
88 /// command handling code is added.
89 void WaitForReceivingThread();
90
Colm Donelan02705242019-11-14 14:19:07 +000091 // @return true only if the receive thread is closed or closing.
92 bool ReceiveThreadRunning()
93 {
94 return !m_CloseReceivingThread.load();
95 }
96
Colm Donelana21620d2019-10-11 13:09:49 +010097 /// Send the counter list to ArmNN.
Colm Donelanb682d842019-10-16 12:24:20 +010098 void SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters);
Colm Donelana21620d2019-10-11 13:09:49 +010099
100 /// Execute the WAIT command from the comamnd file.
Rob Hughes270233f2019-11-13 11:53:48 +0000101 void WaitCommand(uint32_t timeout);
Colm Donelana21620d2019-10-11 13:09:49 +0100102
103 uint32_t GetStreamMetadataVersion()
104 {
105 return m_StreamMetaDataVersion;
106 }
107
108 uint32_t GetStreamMetadataMaxDataLen()
109 {
110 return m_StreamMetaDataMaxDataLen;
111 }
112
113 uint32_t GetStreamMetadataPid()
114 {
115 return m_StreamMetaDataPid;
116 }
117
118private:
Colm Donelana21620d2019-10-11 13:09:49 +0100119 void ReceiveLoop(GatordMockService& mockService);
120
121 /// Block on the client connection until a complete packet has been received. This is a placeholder function to
122 /// enable early testing of the tool.
123 /// @return true if a valid packet has been received.
124 armnn::profiling::Packet WaitForPacket(uint32_t timeoutMs);
125
126 armnn::profiling::Packet ReceivePacket();
127
Rob Hughes270233f2019-11-13 11:53:48 +0000128 bool SendPacket(uint32_t packetFamily, uint32_t packetId, const uint8_t* data, uint32_t dataLength);
Colm Donelana21620d2019-10-11 13:09:49 +0100129
Rob Hughes270233f2019-11-13 11:53:48 +0000130 void EchoPacket(PacketDirection direction, uint8_t* packet, size_t lengthInBytes);
Colm Donelana21620d2019-10-11 13:09:49 +0100131
132 bool ReadHeader(uint32_t headerAsWords[2]);
133
Rob Hughes270233f2019-11-13 11:53:48 +0000134 bool ReadFromSocket(uint8_t* packetData, uint32_t expectedLength);
Colm Donelana21620d2019-10-11 13:09:49 +0100135
Rob Hughes270233f2019-11-13 11:53:48 +0000136 uint32_t ToUint32(uint8_t* data, TargetEndianness endianness);
Colm Donelana21620d2019-10-11 13:09:49 +0100137
Rob Hughes270233f2019-11-13 11:53:48 +0000138 void InsertU32(uint32_t value, uint8_t* data, TargetEndianness endianness);
Colm Donelana21620d2019-10-11 13:09:49 +0100139
140 static const uint32_t PIPE_MAGIC = 0x45495434;
141
142 std::atomic<uint32_t> m_PacketsReceivedCount;
Colm Donelanb682d842019-10-16 12:24:20 +0100143 TargetEndianness m_Endianness;
144 uint32_t m_StreamMetaDataVersion;
145 uint32_t m_StreamMetaDataMaxDataLen;
146 uint32_t m_StreamMetaDataPid;
Colm Donelana21620d2019-10-11 13:09:49 +0100147
148 armnn::profiling::CommandHandlerRegistry& m_HandlerRegistry;
149
150 bool m_EchoPackets;
Rob Hughes25b74362020-01-13 11:14:59 +0000151 armnnUtils::Sockets::Socket m_ListeningSocket;
152 armnnUtils::Sockets::Socket m_ClientConnection;
Colm Donelana21620d2019-10-11 13:09:49 +0100153 std::thread m_ListeningThread;
154 std::atomic<bool> m_CloseReceivingThread;
155};
Colm Donelanb682d842019-10-16 12:24:20 +0100156} // namespace gatordmock
Colm Donelana21620d2019-10-11 13:09:49 +0100157
Colm Donelanb682d842019-10-16 12:24:20 +0100158} // namespace armnn