Skip to content

Commit 9ecfc5c

Browse files
committed
Initial public upload
0 parents  commit 9ecfc5c

23 files changed

+3361
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
__pycache__/
2+
build/
3+
dist/
4+
*egg-info/
5+
*.py[cod]
6+
detd/ipc_pb2.py
7+
.coverage*
8+
bandit.config

LICENSE

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2020-21, Intel Corporation
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

+351
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
# Time Sensitive System Service Prototype (detd)
2+
3+
A proof-of-concept for a developer-friendly system service to handle time-sensitive applications.
4+
5+
6+
## Overview
7+
8+
### In a nutshell
9+
10+
This is a prototype of a system service to handle time-sensitive applications
11+
* **Goal**
12+
* Prototype the interface between time-sensitive applications and the underlying system facilities
13+
* **Non-goal**
14+
* Provide a production-grade, standard system service for that functionality
15+
16+
17+
### Principles
18+
19+
* Developer friendliness
20+
* Serve as enabling vehicle for developer ecosystem discussions
21+
* Hide implementation specific aspects through a high-level abstraction easy to understand for software developers
22+
* Decouple time-sensitive applications from platform or device specific aspects
23+
24+
* Flexibility for experimentation
25+
* Implemented in Python. Integration with other languages via protobuf messages
26+
* Provide a clear separation of concerns and being easily extensible
27+
* Include a unit test and integration test suite
28+
* Allow for testing on host (i.e. without actual TSN hardware) and target environments
29+
30+
31+
### Current functionality
32+
33+
The following snippet illustrates the add_talker interface:
34+
35+
```python
36+
interface_name = "eth0"
37+
interval = 2 * 1000 * 1000 # ns for 2 ms
38+
size = 1522 # Bytes
39+
40+
txoffset = 250 * 1000 # ns for 250 us
41+
addr = "7a:b9:ed:d6:d2:12"
42+
vid = 3
43+
pcp = 6
44+
45+
46+
interface = Interface(interface_name)
47+
traffic = TrafficSpecification(interval, size)
48+
stream = StreamConfiguration(addr, vid, pcp, txoffset)
49+
50+
config = Configuration(interface, stream, traffic)
51+
52+
53+
manager = Manager()
54+
manager.add_talker(config)
55+
```
56+
57+
In a little bit more detail:
58+
59+
1. **Takes stream configuration and traffic specification as an input**
60+
* Interface to use
61+
* Stream configuration: txoffset, DMAC, VID,PCP
62+
* Traffic specification: Interval in nanoseconds, Bytes to transmit
63+
2. **Integrates all the inputs and generates the gating schedule**
64+
* It is able to generate very complex taprio configurations with just the stream and traffic information
65+
3. **Generates the commands implementing that configuration**
66+
* Intel Elkhart Lake integrated TSN interface (mGBE) supported
67+
* taprio offload mode supported
68+
4. **Applies the configuration by running the commands**
69+
* When one of the commands fail, it is able to roll back the previous one to leave the system in a well-known state.
70+
5. **Provides the stream handlers to the caller application**
71+
* The basic implementation provides the VLAN interface name (e.g. eth0.3) and the socket prio to use to the calling application
72+
* The plan is to return a fully configured socket. The included client-server example is already implementing part of that flow.
73+
74+
75+
### Current Limitations
76+
77+
See [Contributing](README.md#contributing) :)
78+
79+
* Current suppport for Intel mGBE only
80+
* Code conceived to support additional devices
81+
* Current support for Linux only
82+
* Current support for talker streams only
83+
* Current taprio support restricted to offload mode
84+
* Code ready to support additional qdiscs
85+
* Launch-Time Control not supported
86+
* E.g. etf qdisc
87+
* Current support for AF_PACKET only
88+
* Basic local schedule calculation
89+
* E.g. inter-packet gap not considered
90+
91+
92+
## Examples
93+
94+
### Setup a talker stream using detd functions from python
95+
96+
This example is not setting up or connecting to the daemon. It is intended to show the functions called by the daemon to set up a talker.
97+
98+
The following code:
99+
```python
100+
interface_name = "eth0"
101+
interval = 20 * 1000 * 1000 # ns for 20 ms
102+
size = 1522 # Bytes
103+
104+
txoffset = 250 * 1000 # ns for 250 us
105+
addr = "7a:b9:ed:d6:d2:12"
106+
vid = 3
107+
pcp = 6
108+
109+
110+
interface = Interface(interface_name)
111+
traffic = TrafficSpecification(interval, size)
112+
stream = StreamConfiguration(addr, vid, pcp, txoffset)
113+
114+
config = Configuration(interface, stream, traffic)
115+
116+
117+
manager = Manager()
118+
manager.add_talker(config)
119+
```
120+
121+
Will first generate all the required commands, like e.g.:
122+
```
123+
tc qdisc replace
124+
dev eth0
125+
parent root
126+
taprio
127+
num_tc 2
128+
map 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
129+
queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7
130+
base-time <now + 2 cycles>
131+
sched-entry S 01 250000
132+
sched-entry S 02 12176
133+
sched-entry S 01 19737824
134+
flags 0x2
135+
136+
137+
ip link add
138+
link eth0
139+
name eth0.3
140+
type vlan
141+
protocol 802.1Q
142+
id 3
143+
egress 0:0 1:1 2:2 3:3 4:4 5:5 6:7 7:7
144+
145+
146+
ethtool --set-eee eth0 eee off
147+
```
148+
149+
To finally apply them.
150+
151+
152+
153+
154+
155+
156+
### Setup a talker stream for an arbitrary command, using a script that calls detd functions
157+
158+
The script [setup_qos.sh](./setup_qos.sh) allows for quick experimentation without modifying an existing application.
159+
160+
It performs the configuration using detd commands, as in the first example.
161+
162+
Then it uses the cgroup net_prio to automatically map the egress traffic from the command to a given socket prio. So all the queuing disciplines and PCP mapping in place works properly.
163+
164+
Example:
165+
```bash
166+
# 2ms period, 1522 bytes, TxOffset 250 microseconds, interface eth0
167+
# stream DMAC AB:CD:EF:FE:DC:BA, stream VID 3, stream PCP 6
168+
# Command: ping 8.8.8.8 for one second (Busybox's ping)
169+
170+
./setup_qos.sh --period 2000000 --bytes 1522 --offset 250000 --interface eth0 \
171+
--address AB:CD:EF:FE:DC:BA --vid 3 --pcp 6 \
172+
-- ping -w 1 8.8.8.8
173+
174+
```
175+
176+
177+
### Setup a talker stream through a system-wide service (without pre-configured socket)
178+
179+
Please refer to [tests/test_service.py](tests/test_service.py) for a working test case showcasing this functionality. The relevant snippets are displayed below.
180+
181+
Spawn the server and wait for the Unix-Domain socket to be available:
182+
```python
183+
def run_server():
184+
with Service() as srv:
185+
srv.run()
186+
187+
def setup_server():
188+
uds_address = '/tmp/uds_detd_server.sock'
189+
server = multiprocessing.Process(target=run_server)
190+
server.start()
191+
while not os.path.exists(uds_address):
192+
time.sleep(0.2)
193+
194+
return server
195+
```
196+
197+
Initialize the interface, stream and traffic objects to be requested.
198+
```python
199+
def setup_configuration():
200+
201+
interface_name = "eth0"
202+
interval = 20 * 1000 * 1000 # ns
203+
size = 1522 # Bytes
204+
205+
txoffset = 250 * 1000 # ns
206+
addr = "03:C0:FF:EE:FF"
207+
vid = 3
208+
pcp = 6
209+
stream = StreamConfiguration(addr, vid, pcp, txoffset)
210+
traffic = TrafficSpecification(interval, size)
211+
212+
return interface_name, stream, traffic
213+
```
214+
215+
Create a proxy object and get the configuration:
216+
```python
217+
# Both Server() and ServiceProxy() point to the same UDS by default
218+
proxy = ServiceProxy()
219+
vlan_interface, soprio = proxy.setup_talker(interface_name, stream, traffic)
220+
```
221+
222+
## Regression testing
223+
224+
225+
### Test environments
226+
227+
By default, calls to system commands are mocked, so almost every code path can be exercised without TSN target hardware.
228+
229+
The test environment is controlled by the following environment variable.
230+
```bash
231+
DETD_TESTENV
232+
```
233+
234+
Host testing is configured by default inside the test suite.
235+
236+
To override the default and setup target testing (e.g. calling actual commands):
237+
```bash
238+
DETD_TESTENV=TARGET
239+
```
240+
241+
For integration testing, the service is spawned as a different process. This prevents regular use of patch. Hence, the Server class accepts a parameter test_mode, that when set to True will patch the required methods in order to maximize coverage. This is automatically performed when running the unittests.
242+
243+
244+
### Test the example "Setup a talker stream using detd functions from python"
245+
246+
* With host test environment
247+
* Intended to be use during development to test most of the code paths on the development host
248+
* Does not require actual TSN hardware or the availability of the underlying system commands
249+
```bash
250+
python3 -m unittest tests.test_manager
251+
```
252+
253+
* With target test environment
254+
* Actual commands are issued to the OS
255+
* Requires real hardware and system environment
256+
```bash
257+
DETD_TESTENV=TARGET python3 -m unittest tests.test_manager
258+
```
259+
260+
### Run the complete test suite
261+
262+
Integration tests include a client-server example in python.
263+
264+
Run all unit and integration tests in the development host test environment:
265+
```bash
266+
python3 -m unittest discover
267+
```
268+
269+
A convenience script [test.sh](detd/test.sh) is included in the detd directory, that basically runs the above command:
270+
```bash
271+
cd detd
272+
./test.sh
273+
```
274+
275+
276+
## Getting involved
277+
278+
### Installation
279+
280+
Dependencies:
281+
* python3
282+
* python3-protobuf
283+
284+
The release process and security checks for the current release were conducted over the following specific versions:
285+
* python 3.8.10
286+
* python-protobuf 3.6.1.3
287+
288+
To install:
289+
```bash
290+
git clone https://github.com/Avnu/detd.git
291+
cd detd
292+
python3 setup.py bdist_wheel
293+
# Uninstall in case a previous version is there
294+
# We install detd system wide
295+
sudo pip3 uninstall detd
296+
sudo pip3 install dist/detd-*.whl
297+
sudo pip3 show detd
298+
```
299+
300+
Optionally, you may want to run the test suite on host to make sure everything is in place:
301+
```bash
302+
python3 -m unittest discover
303+
.....................................ss
304+
----------------------------------------------------------------------
305+
Ran 39 tests in 1.458s
306+
307+
OK (skipped=2)
308+
```
309+
310+
311+
### Contributing
312+
313+
**Junior tasks**
314+
315+
* Make setup_qos.sh interface more compact
316+
* Instead of --address AB:CD:EF:FE:DC:BA --vid 3 --pcp 6
317+
* Use --stream AB:CD:EF:FE:DC:BA/3/6 and parse inside the string
318+
* Move the UDS from /tmp to the right location
319+
* Also involves providing the installation instructions, e.g. to set the right ownerships
320+
* Split device features into rx_features and tx_features
321+
* So e.g. only tx_features are applied when setting up the talker
322+
* Deb and RPM packaging
323+
* systemd service file
324+
* Improve pep8 style compliance
325+
326+
327+
**Other improvements**
328+
329+
* Add C library implementing protobuf interaction
330+
* This will make integration with C applications straighforward
331+
* The python3 implementation can be used as an example
332+
* Add device backends
333+
* Currently mGBE EHL supported
334+
* Add device auto-identification
335+
* E.g. look for vendor/product ids for the interface provided and instantiate the right class
336+
* Add more Linux backend targets
337+
* taprio offload is already implemented
338+
* More could follow, e.g. taprio software, taprio tx-assist, launch-time support...
339+
* Add listener stream setup
340+
* VLAN tag configuration
341+
* DMAC subscription
342+
* tc and ethtool configuration
343+
* Add profiles
344+
* A layer on top of the basic interface that further elevates the level of abstraction
345+
* E.g. 60802, 61850... that provide the right mappings abstracting the developers from that
346+
* Improve platform independence
347+
* More clear separation of generic and platform specific details (e.g. subclassing per OS or platform)
348+
* Integrate time-synchronization
349+
* When a time-aware stream is requested, check if time synchronization is running and otherwise start it and initialize to the right operation values
350+
* Evaluate using netlink for consideration instead of calling tc
351+
* E.g. a programmatic interface could improve aspects like error handling, security, etc, and would make code simpler by removing all the portions devoted to templating commands

0 commit comments

Comments
 (0)