inet icon indicating copy to clipboard operation
inet copied to clipboard

inet 4.5.2 the TSN Qbv cannot bind with Qbu

Open xingkaiyueying opened this issue 1 year ago • 3 comments

When I use Qbv and Qbu separately, they both work fine. I have set **.macLayer.outboundClassifier.classifierClass to "inet::queueing::PacketUserPriorityIndClassifier". However, when I combine the two, the packets get stuck at the Ieee8021qTimeAwareShaper layer and do not forward downwards. Even when I open all gates, they still do not forward.

xingkaiyueying avatar Jul 13 '24 03:07 xingkaiyueying

I have already used PacketTagger in the app to tag the packets with userPriority labels, either 0 or 1.

xingkaiyueying avatar Jul 13 '24 03:07 xingkaiyueying

If you think this is a bug then we need exact steps to reproduce it. Please attach the NED/INI files and/or the necessary changes to an existing example.

levy avatar Jul 15 '24 12:07 levy

Here is my ned file


import inet.networks.base.TsnNetworkBase;
import inet.node.contract.IEthernetNetworkNode;
import inet.node.ethernet.EthernetLink;

network python_network extends TsnNetworkBase
{
	parameters:
		*.eth[*].bitrate = default(1000Mbps);
	submodules:
		es1: <default("TsnDevice")> like IEthernetNetworkNode {}
		es2: <default("TsnDevice")> like IEthernetNetworkNode {}
		sw1: <default("TsnSwitch")> like IEthernetNetworkNode {}
		sw2: <default("TsnSwitch")> like IEthernetNetworkNode {}
		sw3: <default("TsnSwitch")> like IEthernetNetworkNode {}
		sw4: <default("TsnSwitch")> like IEthernetNetworkNode {}
	connections:
		es1.ethg++ <--> EthernetLink <--> sw4.ethg++;
		es2.ethg++ <--> EthernetLink <--> sw3.ethg++;
		sw1.ethg++ <--> EthernetLink <--> sw2.ethg++;
		sw1.ethg++ <--> EthernetLink <--> sw4.ethg++;
		sw2.ethg++ <--> EthernetLink <--> sw3.ethg++;
		sw3.ethg++ <--> EthernetLink <--> sw4.ethg++;
}

and my ini file

[General]
network = python_network
sim-time-limit = 1s
description = "Traffic shaping using time-aware shapers"


# es1 applications
*.es1.numApps = 5

# es1 client applications
*.es1.app[0].typename = "UdpSourceApp"
*.es1.app[0].display-name = "ct1_0"
*.es1.app[0].io.destAddress = "es2"
*.es1.app[0].io.destPort = 1
*.es1.app[0].source.packetLength = 1500B - 58B
*.es1.app[0].source.productionInterval = 100us
*.es1.app[0].source.initialProductionOffset = 56us

*.es1.app[1].typename = "UdpSourceApp"
*.es1.app[1].display-name = "ct2_0"
*.es1.app[1].io.destAddress = "es2"
*.es1.app[1].io.destPort = 2
*.es1.app[1].source.packetLength = 1500B - 58B
*.es1.app[1].source.productionInterval = 200us
*.es1.app[1].source.initialProductionOffset = 21us

*.es1.app[2].typename = "UdpSourceApp"
*.es1.app[2].display-name = "ct2_1"
*.es1.app[2].io.destAddress = "es2"
*.es1.app[2].io.destPort = 3
*.es1.app[2].source.packetLength = 1500B - 58B
*.es1.app[2].source.productionInterval = 200us
*.es1.app[2].source.initialProductionOffset = 35us

*.es1.app[3].typename = "UdpSourceApp"
*.es1.app[3].display-name = "bg1"
*.es1.app[3].io.destAddress = "es2"
*.es1.app[3].io.destPort = 4
*.es1.app[3].source.packetLength = 1500B - 58B
*.es1.app[3].source.productionInterval = 20us
*.es1.app[3].source.initialProductionOffset = 0us

*.es1.app[4].typename = "UdpSourceApp"
*.es1.app[4].display-name = "bg2"
*.es1.app[4].io.destAddress = "es2"
*.es1.app[4].io.destPort = 5
*.es1.app[4].source.packetLength = 1000B - 58B
*.es1.app[4].source.productionInterval = 10us
*.es1.app[4].source.initialProductionOffset = 0us

*.es1.app[*].tagger.typename = "PacketTagger"
*.es1.app[0].tagger.userPriority = 0
*.es1.app[1].tagger.userPriority = 0
*.es1.app[2].tagger.userPriority = 0
*.es1.app[3].tagger.userPriority = 1
*.es1.app[4].tagger.userPriority = 1

# es2 applications
*.es2.numApps = 5

# es2 server applications
*.es2.app[0].typename = "UdpSinkApp"
*.es2.app[0].io.localPort = 1

*.es2.app[1].typename = "UdpSinkApp"
*.es2.app[1].io.localPort = 2

*.es2.app[2].typename = "UdpSinkApp"
*.es2.app[2].io.localPort = 3

*.es2.app[3].typename = "UdpSinkApp"
*.es2.app[3].io.localPort = 4

*.es2.app[4].typename = "UdpSinkApp"
*.es2.app[4].io.localPort = 5

# enable outgoing streams
*.*.hasOutgoingStreams = true

# enable incoming streams
*.*.hasIncomingStreams = true


# es1 stream identification
*.es1.bridging.streamIdentifier.identifier.mapping = [{stream: "ct1_0", packetFilter: expr(udp.destPort == 1)},
                                                      {stream: "ct2_0", packetFilter: expr(udp.destPort == 2)},
                                                      {stream: "ct2_1", packetFilter: expr(udp.destPort == 3)},
													  {stream: "bg1", packetFilter: expr(udp.destPort == 4)},
													  {stream: "bg2", packetFilter: expr(udp.destPort == 5)}]

# es1 stream encoding
*.es1.bridging.streamCoder.encoder.mapping = [{stream: "ct1_0", pcp: 7, vlan: 1},
                                              {stream: "ct2_0", pcp: 6, vlan: 2},
                                              {stream: "ct2_1", pcp: 6, vlan: 3},
											  {stream: "bg1", pcp: 1, vlan: 4},
											  {stream: "bg2", pcp: 0, vlan: 5}]


# disable automatic MAC forwarding table configuration
*.macForwardingTableConfigurator.typename = ""

# map destination MAC address and VLAN pairs to network interfaces
*.sw3.macTable.forwardingTable = [{address: "es2", vlan: 1, interface: "eth0"},
                                  {address: "es2", vlan: 2, interface: "eth0"},
                                  {address: "es2", vlan: 3, interface: "eth0"},
								  {address: "es2", vlan: 4, interface: "eth0"},
								  {address: "es2", vlan: 5, interface: "eth0"}]

# map destination MAC address and VLAN pairs to network interfaces
*.sw4.macTable.forwardingTable = [{address: "es2", vlan: 1, interface: "eth2"},
                                  {address: "es2", vlan: 2, interface: "eth2"},
                                  {address: "es2", vlan: 3, interface: "eth2"},
								  {address: "es2", vlan: 4, interface: "eth2"},
								  {address: "es2", vlan: 5, interface: "eth2"}]


# enable egress traffic shaping
*.*.hasEgressTrafficShaping = true

*.*.hasFramePreemption = true
**.macLayer.outboundClassifier.classifierClass = "inet::queueing::PacketUserPriorityIndClassifier"


# The duration parameter must contain an even number of values and 0ms is an unaccepted duration value
# es1->sw4 gate control list
*.es1.eth[0].macLayer.queue.numTrafficClasses = 8
*.es1.eth[0].macLayer.queue.transmissionGate[6].offset = 179us
*.es1.eth[0].macLayer.queue.transmissionGate[6].durations = [12us, 2us, 12us, 174us]
*.es1.eth[0].macLayer.queue.transmissionGate[7].offset = 44us
*.es1.eth[0].macLayer.queue.transmissionGate[7].durations = [12us, 88us]
*.es1.eth[0].macLayer.queue.transmissionGate[1].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[1].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.es1.eth[0].macLayer.queue.transmissionGate[0].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[0].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.es1.eth[0].macLayer.queue.transmissionGate[2].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[2].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.es1.eth[0].macLayer.queue.transmissionGate[3].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[3].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.es1.eth[0].macLayer.queue.transmissionGate[4].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[4].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.es1.eth[0].macLayer.queue.transmissionGate[5].offset = 167us
*.es1.eth[0].macLayer.queue.transmissionGate[5].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]

# sw3->es2 gate control list
*.sw3.eth[0].macLayer.queue.numTrafficClasses = 8
*.sw3.eth[0].macLayer.queue.transmissionGate[6].offset = 147us
*.sw3.eth[0].macLayer.queue.transmissionGate[6].durations = [12us, 2us, 12us, 174us]
*.sw3.eth[0].macLayer.queue.transmissionGate[7].offset = 12us
*.sw3.eth[0].macLayer.queue.transmissionGate[7].durations = [12us, 88us]
*.sw3.eth[0].macLayer.queue.transmissionGate[1].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[1].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]
*.sw3.eth[0].macLayer.queue.transmissionGate[0].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[0].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]
*.sw3.eth[0].macLayer.queue.transmissionGate[2].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[2].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]
*.sw3.eth[0].macLayer.queue.transmissionGate[3].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[3].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]
*.sw3.eth[0].macLayer.queue.transmissionGate[4].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[4].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]
*.sw3.eth[0].macLayer.queue.transmissionGate[5].offset = 200us
*.sw3.eth[0].macLayer.queue.transmissionGate[5].durations = [53us, 12us, 2us, 12us, 9us, 12us, 88us, 12us]

# sw4->sw3 gate control list
*.sw4.eth[2].macLayer.queue.numTrafficClasses = 8
*.sw4.eth[2].macLayer.queue.transmissionGate[6].offset = 163us
*.sw4.eth[2].macLayer.queue.transmissionGate[6].durations = [12us, 2us, 12us, 174us]
*.sw4.eth[2].macLayer.queue.transmissionGate[7].offset = 28us
*.sw4.eth[2].macLayer.queue.transmissionGate[7].durations = [12us, 88us]
*.sw4.eth[2].macLayer.queue.transmissionGate[1].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[1].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.sw4.eth[2].macLayer.queue.transmissionGate[0].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[0].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.sw4.eth[2].macLayer.queue.transmissionGate[2].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[2].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.sw4.eth[2].macLayer.queue.transmissionGate[3].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[3].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.sw4.eth[2].macLayer.queue.transmissionGate[4].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[4].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]
*.sw4.eth[2].macLayer.queue.transmissionGate[5].offset = 151us
*.sw4.eth[2].macLayer.queue.transmissionGate[5].durations = [2us, 12us, 9us, 12us, 88us, 12us, 53us, 12us]

In the ini file, I see that the default value of the classifierClass parameter of outboundClassifier in the original EthernetPreemptingMacLayer.ned file is "inet::PacketVlanReqClassifier." However, I want the packets to be tagged with my desired VLAN, so I enabled the StreamCoderLayer. In the original ini file under the framepreemption folder, the VLAN ID is used to determine whether a packet can be preempted, and a vlanreq tag is assigned. But after enabling the StreamCoderLayer, the vlanreq tag changes to vlanind tag after passing through the bridging layer, which is overridden by my defined encoder, causing errors. Therefore, I tried using userPriority to differentiate whether a packet can be preempted. As a result, when I enable both Qbv and Qbu simultaneously, packets entering the PacketQueue of Ieee8021qTimeAwareShaper stop being sent, even if the transmissionGate is open.

Additionally, if there are no issues with the current Qbu, I would like to ask how to effectively configure the preemptibility of the queues. The example only demonstrates the configuration on the sending side, without examples for switch configurations.

xingkaiyueying avatar Jul 15 '24 13:07 xingkaiyueying