TSNsched-based Gate Scheduling¶
Goals¶
This showcase demonstrates the TSNsched gate schedule configurator that solves the autoconfiguration problem with an external SAT solver tool.
4.4
The Model¶
The TSNschedGateScheduleConfigurator module provides a gate scheduling configurator that uses the TSNsched tool that is available at https://github.com/ACassimiro/TSNsched (check the NED documentation of the configurator for installation instructions). The module has the same parameters as the other gate schedule configurators.
The simulation uses the same network as the showcases for the Eager and SAT configurators:

Here is the configuration:
[General]
network = inet.networks.tsn.TsnDumbbellNetwork
description = "TSN sched based gate scheduling"
sim-time-limit = 0.2s
#record-eventlog = true
#emulation = true
*.switch1.typename = "TsnSwitch1"
*.switch2.typename = "TsnSwitch2"
# client applications
*.client*.numApps = 2
*.client*.app[*].typename = "UdpSourceApp"
*.client*.app[0].display-name = "best effort"
*.client*.app[1].display-name = "video"
*.client*.app[0].io.destAddress = "server1"
*.client*.app[1].io.destAddress = "server2"
*.client1.app[0].io.destPort = 1000
*.client1.app[1].io.destPort = 1002
*.client2.app[0].io.destPort = 1001
*.client2.app[1].io.destPort = 1003
*.client*.app[*].source.packetNameFormat = "%M-%m-%c"
*.client*.app[0].source.packetLength = 1000B
*.client*.app[1].source.packetLength = 500B
*.client*.app[0].source.productionInterval = 1000us # ~8Mbps
*.client*.app[1].source.productionInterval = 500us # ~8Mbps
# server applications
*.server*.numApps = 4
*.server*.app[*].typename = "UdpSinkApp"
*.server*.app[0..1].display-name = "best effort"
*.server*.app[2..3].display-name = "video"
*.server*.app[0].io.localPort = 1000
*.server*.app[1].io.localPort = 1001
*.server*.app[2].io.localPort = 1002
*.server*.app[3].io.localPort = 1003
# enable outgoing streams
*.client*.hasOutgoingStreams = true
# client stream identification
*.client*.bridging.streamIdentifier.identifier.mapping = [{stream: "best effort", packetFilter: expr(udp.destPort == 1000)},
{stream: "video", packetFilter: expr(udp.destPort == 1002)},
{stream: "best effort", packetFilter: expr(udp.destPort == 1001)},
{stream: "video", packetFilter: expr(udp.destPort == 1003)}]
# client stream encoding
*.client*.bridging.streamCoder.encoder.mapping = [{stream: "best effort", pcp: 0},
{stream: "video", pcp: 4}]
# enable streams
*.switch*.hasIncomingStreams = true
*.switch*.hasOutgoingStreams = true
*.switch*.bridging.streamCoder.decoder.mapping = [{pcp: 0, stream: "best effort"},
{pcp: 4, stream: "video"}]
*.switch*.bridging.streamCoder.encoder.mapping = [{stream: "best effort", pcp: 0},
{stream: "video", pcp: 4}]
# enable incoming streams
*.server*.hasIncomingStreams = true
# enable egress traffic shaping
*.switch*.hasEgressTrafficShaping = true
# time-aware traffic shaping with 2 queues
*.switch*.eth[*].macLayer.queue.numTrafficClasses = 2
*.switch*.eth[*].macLayer.queue.queue[0].display-name = "best effort"
*.switch*.eth[*].macLayer.queue.queue[1].display-name = "video"
# automatic gate scheduling
*.gateScheduleConfigurator.typename = "TSNschedGateScheduleConfigurator"
*.gateScheduleConfigurator.gateCycleDuration = 1ms
# 58B = 8B (UDP) + 20B (IP) + 4B (802.1 Q-TAG) + 14B (ETH MAC) + 4B (ETH FCS) + 8B (ETH PHY)
*.gateScheduleConfigurator.configuration =
[{pcp: 0, gateIndex: 0, application: "app[0]", source: "client1", destination: "server1", packetLength: 1000B + 58B + 12B, packetInterval: 1000us, maxLatency: 500us},
{pcp: 4, gateIndex: 1, application: "app[1]", source: "client1", destination: "server2", packetLength: 500B + 58B + 12B, packetInterval: 500us, maxLatency: 500us},
{pcp: 0, gateIndex: 0, application: "app[0]", source: "client2", destination: "server1", packetLength: 1000B + 58B + 12B, packetInterval: 1000us, maxLatency: 500us},
{pcp: 4, gateIndex: 1, application: "app[1]", source: "client2", destination: "server2", packetLength: 500B + 58B + 12B, packetInterval: 500us, maxLatency: 500us}]
# gate scheduling visualization
*.visualizer.gateScheduleVisualizer.displayGateSchedules = true
*.visualizer.gateScheduleVisualizer.displayDuration = 100us
*.visualizer.gateScheduleVisualizer.gateFilter = "*.switch1.eth[2].** or *.switch2.eth[0].**.transmissionGate[0] or *.switch2.eth[1].**.transmissionGate[1]"
*.visualizer.gateScheduleVisualizer.height = 16
Note
There are two changes in this configuration compared to the Eager and SAT configurator showcases, due to limitations in the SAT solver tool:
The traffic is half as dense as in the Eager and SAT configurator showcases. Currently, the tool can only find a solution to the autoconfiguration problem if all transmissions are completed within the gate cycle (though it should be possible for the individual frame transmissions to overlap).
12 Bytes need to be added to the packet size in the XML configuration to account for the inter-frame gap.
Results¶
The following sequence chart shows a gate cycle period (1ms):

Note that the frames are forwarded immediatelly by the switches.
The following sequence chart shows frame transmissions, with the best effort gate state displayed on the axes for the two switches.

Note that the gates are open so that two frames can be transmitted, and the frame transmissions and the send window are closely aligned in time.
The following figure shows application end-to-end delay for the four streams:

All streams have the minimal possible delay, as they are forwarded immediatelly.
Sources: omnetpp.ini