You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单主时钟环境下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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:45:33