Search code examples
omnet++inet

How can I integratre INET gPTP with INET TAS?


I would like to integrate two sample codes (TAS and gPTP) into the One Master Clock network environment. The following are the .ini and .ned codes.

simpleGptp.ini

[General]
network = OneMasterClockGptpShowcase

**.displayGateSchedules = true
**.gateFilter = "**.eth[1].**"
**.gateScheduleVisualizer.height = 16
**.gateScheduleVisualizer.placementHint = "top"


# client applications
*.tsnDevice1.numApps = 2
*.tsnDevice1.app[*].typename = "UdpSourceApp"
*.tsnDevice1.app[0].display-name = "best effort"
*.tsnDevice1.app[1].display-name = "video"
*.tsnDevice1.app[*].io.destAddress = "tsnDevice2"
*.tsnDevice1.app[0].io.destPort = 1000
*.tsnDevice1.app[1].io.destPort = 1001
*.tsnDevice1.app[*].source.packetLength = 1000B - 54B # 42B = 8B (UDP) + 20B (IP) + 14B (ETH MAC) + 4B (ETH FCS) + 8B (ETH PHY)
*.tsnDevice1.app[0].source.productionInterval = exponential(200us) # ~40Mbps
*.tsnDevice1.app[1].source.productionInterval = exponential(400us) # ~20Mbps

# server applications
*.tsnDevice2.numApps = 2
*.tsnDevice2.app[*].typename = "UdpSinkApp"
*.tsnDevice2.app[0].io.localPort = 1000
*.tsnDevice2.app[1].io.localPort = 1001

# enable outgoing streams
*.tsnDevice1.hasOutgoingStreams = true

# client stream identification
*.tsnDevice1.bridging.streamIdentifier.identifier.mapping = [{stream: "best effort", packetFilter: expr(udp.destPort == 1000)},
                                                         {stream: "video", packetFilter: expr(udp.destPort == 1001)}]

# client stream encoding
*.tsnDevice1.bridging.streamCoder.encoder.mapping = [{stream: "best effort", pcp: 0},
                                                 {stream: "video", pcp: 4}]

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

# time-aware traffic shaping
*.tsnSwitch.eth[*].macLayer.queue.numTrafficClasses = 2
*.tsnSwitch.eth[*].macLayer.queue.*[0].display-name = "best effort"
*.tsnSwitch.eth[*].macLayer.queue.*[1].display-name = "video"
*.tsnSwitch.eth[*].macLayer.queue.transmissionGate[0].offset = 0ms
*.tsnSwitch.eth[*].macLayer.queue.transmissionGate[0].durations = [4ms, 6ms] # period is 10 # length of periods
*.tsnSwitch.eth[*].macLayer.queue.transmissionGate[1].offset = 6ms
*.tsnSwitch.eth[*].macLayer.queue.transmissionGate[1].durations = [2ms, 8ms]




# enable time synchronization in all network nodes
*.*.hasTimeSynchronization = true

# all oscillators have a random constant drift
**.oscillator.typename = "ConstantDriftOscillator"
**.oscillator.driftRate = uniform(-100ppm, 100ppm)

# all Ethernet interfaces have 100 Mbps speed
*.*.eth[*].bitrate = 100Mbps

*.visualizer.typename = "IntegratedMultiCanvasVisualizer"
*.visualizer.infoVisualizer.displayInfos = true



# TSN clock gPTP master ports
*.tsnClock.gptp.masterPorts = ["eth0"]

# TSN switch gPTP bridge master ports
*.tsnSwitch.gptp.masterPorts = ["eth1", "eth2"]

# Set all reference clocks to master clock so the time difference can be visualized
**.referenceClock = "tsnClock.clock"

# data link visualizer displays gPTP time synchronization packets
*.visualizer.dataLinkVisualizer[0].displayLinks = true
*.visualizer.dataLinkVisualizer[0].activityLevel = "protocol"
*.visualizer.dataLinkVisualizer[0].packetFilter = "GptpSync"
*.visualizer.dataLinkVisualizer[0].lineColor = "blue2"

*.visualizer.numInfoVisualizers = 3
*.visualizer.infoVisualizer[0].modules = "*.tsnClock.clock"
*.tsnClock.clock.displayStringTextFormat = "time: %T"
*.visualizer.infoVisualizer[1].modules = "*.tsnSwitch.clock"
*.visualizer.infoVisualizer[1].placementHint = "topLeft"
*.visualizer.infoVisualizer[2].modules = "*.tsnDevice*.clock"
*.visualizer.infoVisualizer[2].placementHint = "bottom"
*.tsnDevice*.clock.displayStringTextFormat = "diff: %d"
*.tsnSwitch.clock.displayStringTextFormat = "diff: %d"

simpleGptp.ned

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

package tsn_scalability.simulations;
import inet.common.scenario.ScenarioManager;
import inet.networks.base.TsnNetworkBase;
import inet.node.ethernet.EthernetLink;
import inet.node.tsn.TsnClock;
import inet.node.tsn.TsnDevice;
import inet.node.tsn.TsnSwitch;

network OneMasterClockGptpShowcase extends TsnNetworkBase
{
    submodules:
        tsnClock: TsnClock {
            @display("p=500,150");
        }
        tsnSwitch: TsnSwitch {
            @display("p=500,300");
        }
        tsnDevice1: TsnDevice {
            @display("p=400,450");
        }
        tsnDevice2: TsnDevice {
            @display("p=600,450");
        }
    connections:
        tsnClock.ethg++ <--> EthernetLink <--> tsnSwitch.ethg++;
        tsnSwitch.ethg++ <--> EthernetLink <--> tsnDevice1.ethg++;
        tsnSwitch.ethg++ <--> EthernetLink <--> tsnDevice2.ethg++;
}

Error message

omnetpp::common::expression::ExprNode::eval_error: Object nullptr has no member named 'destPort' -- in module (inet::queueing::PacketMultiplexer) OneMasterClockGptpShowcase.tsnDevice1.bridging.directionReverser.join (id=337), at t=0s, event #13

The problem happened when the tsnDevice1 sent the GptpPdelayReq packet passing through the bridging module. If you have any ideas, please let me know. Thank you.


Solution

  • The gPTP packet doesn't contain a UDP header, so you should avoid dereferencing the UDP header if there's none.

    For example:

    expr(has(udp) && udp.destPort == 1000)

    Ideally the gPTP packet is neither part of the video nor the best effort streams.