1# EDTT transport for BabbleSim devices
2
3This is a description of the inner workings of the
4EDTT transport for BabbleSim (`edttt_bsim.py` and associated embedded driver)
5
6## Introduction
7
8In simulation the picture of how the communication between the EDTT and the
9devices looks as follows:
10
11```
12              _____________       __________
13             |             | --> |          |
14 ______      |             |     | Device 0 |
15|      | --> |             | <-- |__________|
16| EDTT |     | EDTT Bridge |      __________
17|______| <-- |             | --> |          |
18             |             |     | Device 1 |
19             |_____________| <-- |__________|
20
21```
22
23
24Each of the “-->” is a POSIX named pipe (FIFO) (which by default can buffer up to
2564KB in each direction).
26
27The bridge has 2 main purposes:
28
29* It routes the EDTT data to the appropriate device
30* It pauses the simulation while the EDTT is processing, so there is no asynchronous
31  behaviour
32
33This is done by having the EDTT command the brdige to either:
34
35 * read to a device
36 * write to a devices
37 * let simulation time advance
38 * terminate the simulation
39
40
411. The EDTT, will only run while the simulation itself is paused.
42   The EDTT can interact in 3 ways with the devices (thru the bridge)<br>
43   When the EDTT writes to a device, that data is piped immediately to the
44   bridge.<br>
45   When the EDTT reads from the device, it actually sends a command to the
46   bridge requesting N bytes with a timeout.<br>
47   When the EDTT does `transport.wait(time)`, it tells the bridge to just let
48   the simulation time go ahead for `<time>` without doing anything.
49
502. The Bridge will fully block the simulation until it gets a new command from
51   the EDTT
52
53    * If the bridge is commanded to write to a device, it pipes it to the
54      device immediately (without unblocking the simulation) and blocks until it
55      gets a new command again from the EDTT
56    * If it is commanded to “read” from a device, it tries to read from the
57      device pipe immediately:
58
59        * If it succeeds it sends it immediately to the EDTT
60        * If there is not enough data yet from the device, it will wait
61          `<recv_wait_us>` in simulated time, that is, it will let the
62          simulation time to advance by `<recv_wait_us>`, and try again.
63          (`<recv_wait_us>` is a bridge command line option, by default 10ms)
64
653. The embedded device transport
66
67    * When the app tries to read from the EDTT transport: it will try
68      immediately
69
70        * If there is enough data, it just returns it to the caller
71        * If it does not have enough data yet, and the read was blocking,
72          will wait for `EDTT_IF_RECHECK_DELTA` (5ms) and retry
73
74    * When told to write it will pipe it to the bridge immediately without any
75      delay
76
77
78So effectively:
79
80* Writing from the EDTT to the device can be aparent to the device only the next
81  time the device checks (up to EDTT_IF_RECHECK_DELTA later)
82* Reading from the device can take up to the next `<recv_wait_us>` boundary
83  for the EDTT bridge to read it out, apart from the simulated time it may
84  take for the device to generate it.
85
86
87## Implementation details:
88
89The named pipes are placed in /tmp/bsim_<user>/<sim_id>/
90There is 2 to communicate between the python tests and the bridge:
91
92* Device<bridge_id>.ToEDTT
93* Device<bridge_id>.ToBRIDGE
94
95And 2 from the bridge to each device
96
97* Device<device_id>.EDTTin
98* Device<device_id>.EDTTout
99
100Between the EDTT bsim transport and the bridge there is a simple protocol,
101in which the EDTT side is the master.
102Any action performed by the bridge is initiated by the EDTT transport side.
103
104The protocol with the EDTTool is as follows:
105```
106  1 byte commands are sent from the EDTTool
107  The commands are: SEND, RCV, WAIT, DISCONNECT
108  SEND is followed by:
109    1 byte : device idx
110    2 bytes: (uint16_t) number of bytes
111    N bytes: payload to forward
112  RCV is followed by:
113    1 byte : device idx
114    8 bytes: timeout time (simulated absolute time)
115    2 bytes: (uint16_t) number of bytes
116  WAIT:
117    8 bytes: (uint64_t) absolute time stamp until which to wait
118    (not the wait duration, but the end of the wait)
119  DISCONNECT:
120    - nothing
121
122 After receiving a command (and its payload) the bridge device will respond:
123   to a SEND: nothing
124   to a RCV:
125     1 byte : reception done (0) or timeout (1)
126     8 bytes: timestamp when the reception or timeout actually happened
127     0/N bytes: (0 bytes if timeout, N bytes as requested otherwise)
128   to a WAIT: nothing
129   to a DISCONNECT: nothing
130```
131
132That is, when the EDTT writtes to a DUT, a prefix starting with the SEND
133command is sent ahead of the data. The bridge looks into this header to know
134for which device this message is meant, and how many bytes the message has.
135The header is thrown away in the bridge and the message itself forwarded to
136that DUT.
137
138A read from the EDTT to a DUT is effectively a command to the bridge to let
139the simulation run until that amount of requested data has been received in
140the bridge from that DUT, or the timeout has been reached.
141
142### Notes about the transport in the EDTT side
143
144When connect() is called the FIFOs to the bridge will be created
145(if not yet there), and the EDTT will be blocked until the bridge
146connects on the other side.
147
148Immediately after the number of devices the bridge is connected to
149will be read out from the FIFO.
150
151When disconnecting, the transport will attempt to delete the FIFOs
152(the last one who disconnects from its end succeds)
153
154### Notes about the bridge
155
156At startup it will create and connect to its end of the pipes
157to the EDTT and devices.
158It will then send the number of DUTs it is connected to the EDTT
159transport side.
160After that it will as described before enter an infinite loop
161waiting for commands from the EDTT transport, and reacting accordingly.
162
163### Notes about the transport in the DUT side
164
165On the initial connection, edtt_start(), the pipes are opened,
166and the simulated device execution is blocked until the bridge
167connects to the other side.
168
169When sending and receiving data to and towards the EDTT,
170the byte stream is passed through unaltered.
171
172Reads can be blocking (EDTTT_BLOCK), waiting for the bytes to arrive,
173or non-blocking (EDTTT_NONBLOCK).
174
175Writes are always treated as non-blocking in this trasnport, assuming that
176the FIFO is large enough to queue the request. In the very unlikely case in which
177it would not be, an error would be printed.
178
179When the transport layer is closed, the EDTT Bridge FIFOs are closed and deleted.
180