单主时钟环境下INET gPTP与TAS集成报错及解决方案咨询
TAS与gPTP集成单主时钟网络的数据包过滤错误解决思路
集成场景与代码
我尝试将TAS(时间感知整形)和gPTP(通用精确时间协议)两个示例集成到单主时钟网络环境中,以下是对应的配置文件和网络拓扑代码:
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++; }
报错信息
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
问题发生在tsnDevice1发送GptpPdelayReq数据包经过桥接模块时。
解决思路
问题根源
gPTP的PdelayReq属于二层以太网帧(以太网类型为0x88F7),不包含UDP/IP头部。当前流识别规则直接用udp.destPort匹配所有数据包,当gPTP帧经过桥接模块时,代码尝试读取不存在的UDP头部destPort字段,导致空指针错误。
修复方案
方案1:限制流识别规则仅匹配UDP数据包
修改tsnDevice1.bridging.streamIdentifier.identifier.mapping中的过滤表达式,先通过hasUdpHeader()判断数据包是否包含UDP头部,再匹配端口:
*.tsnDevice1.bridging.streamIdentifier.identifier.mapping = [{stream: "best effort", packetFilter: expr(hasUdpHeader() && udp.destPort == 1000)}, {stream: "video", packetFilter: expr(hasUdpHeader() && udp.destPort == 1001)}]
这样gPTP等非UDP数据包会跳过流识别逻辑,不会触发错误。
方案2:为gPTP流量添加单独流规则(可选)
如果需要对gPTP流量做优先级标记等处理,可以添加一条匹配gPTP的规则,确保协议流量被正确识别:
*.tsnDevice1.bridging.streamIdentifier.identifier.mapping = [{stream: "gptp", packetFilter: expr(etherType == 0x88F7)}, {stream: "best effort", packetFilter: expr(udp.destPort == 1000)}, {stream: "video", packetFilter: expr(udp.destPort == 1001)}]
同时可以在流编码部分为gPTP设置高优先级PCP值:
*.tsnDevice1.bridging.streamCoder.encoder.mapping = [{stream: "gptp", pcp: 7}, {stream: "best effort", pcp: 0}, {stream: "video", pcp: 4}]
验证要点
修改后运行仿真,确认:
- gPTP时间同步正常(各节点时钟差值稳定)
- TAS流量整形正常(业务流量按配置的门控周期发送)
- 无类似空指针错误抛出
内容的提问来源于stack exchange,提问作者How-Hang Liu
相关产品推荐
相关产品推荐

