1. 项目概述与TSN技术背景
在工业自动化、汽车电子和航空航天这些对时间要求极其苛刻的领域里,传统以太网“尽力而为”的传输模式已经不够用了。想象一下,一条生产线上,控制机械臂运动的指令数据包如果因为网络拥堵延迟了几十毫秒,或者跟普通文件传输的数据包挤在一起导致丢失,后果可能就是生产线停机甚至设备损坏。这就是时间敏感网络(TSN)要解决的核心问题:在标准的以太网硬件上,实现确定性的、低延迟、低抖动的数据传输,让关键流量像在专属高速公路上行驶一样,拥有绝对的优先权和通行保障。
TSN不是某一种单一的技术,而是一整套由IEEE 802.1工作组制定的标准族。它像给传统以太网加上了一套精密的交通管理系统。这套系统的基石是精准的全网时间同步(802.1AS),确保所有设备都在同一个“时钟”下工作。在此基础上,通过时间感知整形(802.1Qbv,俗称“时间门控”)、帧抢占(802.1Qbu/802.3br)、流预留协议(802.1Qcc)等一系列技术,对网络流量进行规划、调度和隔离。而本文要深入探讨的流过滤与门控,对应的正是IEEE 802.1Qci标准。你可以把它理解为这个交通管理系统中的“智能检查站和红绿灯”。
Qci的核心任务是在数据流进入网络的入口(Ingress Port)进行精细化管理。它主要包含三个关键动作:流识别、流过滤和流监管。首先,系统需要识别出哪些是重要的“特权车辆”(关键数据流),这可以通过MAC地址、VLAN ID、IP五元组等多种方式。识别出来后,“智能检查站”(流过滤器,Stream Filter)会检查这辆车是否符合通行标准,比如车身尺寸(帧长)是否超标。最后,“流量计数器”(流计量器,Flow Meter)会监控这辆车的速度(数据速率),如果超速了,就进行标记或丢弃。而“红绿灯”(流门控,Stream Gate)则根据预定义的时间表,控制车流何时可以通行。这一整套机制确保了非关键流量不会干扰关键流量,并且任何异常的、不符合规定的流量都会被及时拦截,从而保障了网络的确定性和安全性。
NXP的LS1028A处理器是一款集成了高性能Arm Cortex-A72内核和先进交换硬件的SoC,其内置的以太网交换模块原生支持包括Qci在内的多项TSN特性。这为我们提供了一个绝佳的实践平台,无需外接复杂的FPGA或专用交换芯片,就能在单芯片上构建完整的TSN节点。本文将聚焦于在LS1028A平台上,如何利用其提供的软件工具(tsntool和Linuxtc)来具体配置和验证Qci的各个功能组件。我会结合官方文档的示例和我在实际调试中的经验,带你一步步打通从理论到实践的路径,理解每一个参数背后的含义,并避开那些容易踩坑的细节。
2. 实验环境搭建与基础概念解析
在开始动手配置之前,搭建一个清晰、可控的实验环境至关重要。对于TSN实验,尤其是涉及精确时间门控的Qci,我强烈建议使用至少两台设备:一台作为被测设备,即运行LS1028A的平台;另一台作为测试仪,用于生成和接收精确可控的网络流量。专业的测试仪如思博伦TestCenter、IXIA能够提供纳秒级精度的时间戳和流量控制,是验证TSN功能的黄金标准。如果没有专业仪表,也可以使用另一台运行Linux的工控机或服务器,配合linuxptp、tc和自定义发包工具(如packeth或基于DPDK/raw socket编写的工具)来模拟,但精度和可控性会打折扣。
在我们的场景中,假设LS1028A开发板(以下简称DUT)上有多个以太网端口,例如swp0,swp1,swp2等。我们将swp0配置为入口端口,关键数据流从这里进入交换机;swp1配置为出口端口,连接接收端(测试仪或另一台主机)。swp2可能用于连接干扰流量的发生器。首先,我们需要确保基础的网络连通性和VLAN配置正确。LS1028A的交换驱动通常基于Linux的Bridge或DSA框架,因此我们可以用标准的ip和bridge命令进行配置。
一个常见的初始配置步骤如下:首先创建一个支持VLAN过滤的网桥,并将相应的端口加入其中。VLAN在TSN中经常被用作流量隔离和优先级标记的基础。
# 创建网桥并启用VLAN过滤 ip link add name br0 type bridge vlan_filtering 1 ip link set br0 up # 将交换端口加入网桥,并启动端口 ip link set swp0 master br0 ip link set swp1 master br0 ip link set swp0 up ip link set swp1 up # 配置端口的VLAN成员关系。例如,让swp0和swp1都允许VLAN 1的流量通过,并将swp0的默认PVID设为1。 bridge vlan add dev swp0 vid 1 pvid untagged bridge vlan add dev swp1 vid 1注意:在LS1028A的某些驱动版本或配置下,当端口被加入一个启用了
vlan_filtering的网桥后,该端口可能就无法再通过ifconfig或ip addr直接配置IP地址或进行三层转发了。这是因为驱动可能将端口切换到了纯粹的“交换模式”。此时,所有的路由和IP处理都需要在网桥接口br0上进行。这是实现硬件加速交换的常见方式,但在调试初期可能会带来一些困惑。
接下来,理解几个核心的Qci概念,它们直接对应到配置命令的参数:
- Stream Handle / SFID:流句柄或流过滤器标识符。这是一个本地唯一的数字,用于标识一条特定的数据流。在
tsntool的cbstreamidset和qcisfiset命令中,streamhandle和index参数都与之相关,需要仔细对应。 - Gate ID:门控标识符。关联到一个具体的流门控实例,控制着流的通行时间表。
- Flow Meter ID:流计量器标识符。关联到一个具体的流量监管策略,定义了承诺信息速率、突发大小等参数。
- Priority:优先级。在流过滤器中,可以为匹配的流分配一个优先级,影响其在交换机内部队列中的调度。
这些ID在配置时需要精心规划,避免冲突。例如,流过滤器(SFI)、流门控(SG)、流计量(FMI)通常有独立的表项空间,它们的ID可以独立分配,但在关联时需要确保一致性。
3. 基于tsntool的Qci流过滤与门控配置详解
tsntool是NXP为其TSN平台提供的一个专用配置工具,它通过命令行接口直接与交换机的硬件寄存器交互,能够高效地配置Qci等TSN特性。下面,我们按照数据流处理的逻辑顺序,拆解每一个配置步骤。
3.1 流识别与流过滤器设置
Qci处理的起点是识别出需要被特殊对待的流。在LS1028A上,我们可以通过cbstreamidset命令来定义一条流。最常用的是基于空流标识(Null Stream Identification),即通过目的MAC地址和VLAN ID来识别。
# 在入口端口swp0上,定义一条流:目的MAC为 00:01:83:fe:12:01, VLAN ID为1。 # 为其分配流句柄(streamhandle)为 1。 tsntool> cbstreamidset --device swp0 --nullstreamid --nulldmac 0x000183fe1201 --nullvid 1 --streamhandle 1参数解读与避坑指南:
--device:指定进行流识别的端口。关键点:流识别通常配置在流的入口端口。后续的过滤、门控操作也针对这个入口端口。--nullstreamid:指明使用空流识别模式。--nulldmac:目的MAC地址,需要转换为连续的十六进制数字,去掉冒号。--nullvid:VLAN ID。这里配置的是期望数据包携带的VID。如果数据包不带VLAN tag,则不会匹配。--streamhandle:这是为这条流分配的一个本地标识符,后续所有针对这条流的操作(过滤、门控)都需要引用这个值。
实操心得:
streamhandle是一个很容易混淆的概念。在cbstreamidset中它用于标识流。在后续的qcisfiset中,有两个相关参数:--index和--streamhandle。根据文档和我的测试,qcisfiset中的--index是流过滤器表项的索引,而--streamhandle需要与cbstreamidset中设置的streamhandle保持一致,这样才能将过滤器关联到正确的流。有些文档示例中它们被设置为相同的值,但逻辑上是两个东西。
定义好流之后,下一步是设置流过滤器。流过滤器决定了被识别的流接下来要经历哪些处理。
# 在端口swp0上,配置索引为1的流过滤器。 # 将其关联到流句柄为1的流,并指定使用门控1和流量计量器68。 tsntool> qcisfiset --device swp0 --index 1 --streamhandle 1 --gateid 1 --priority 0 --flowmeterid 68参数深度解析:
--index:这是流过滤器表(Stream Filter Instance Table)中的一个条目索引。你可以配置多个过滤器,每个有不同的index。--streamhandle:必须与之前cbstreamidset设置的streamhandle匹配,这是关联的关键。--gateid:指定此流要经过哪个流门控。门控决定了流在什么时间窗口可以通行。--priority:为匹配的流分配一个内部优先级。这个优先级会影响数据包在交换机内部队列的调度顺序,即使原始报文中的PCP字段可能不同。--flowmeterid:指定此流要使用哪个流量计量器进行速率监管。
一个重要的进阶功能是最大帧长检查:
# 在原有过滤器基础上,增加最大帧长(MaxSDU)检查,设置为200字节。 tsntool> qcisfiset --device swp0 --index 1 --streamhandle 1 --gateid 1 --priority 0 --flowmeterid 68 --maxsdu 200配置了--maxsdu 200后,任何帧长超过200字节的、匹配此流过滤器的数据包都会被直接丢弃。这是防止错误或恶意的大帧占用网络资源、影响关键流实时性的重要安全机制。
3.2 流门控配置:定义流的通行时刻表
流门控是Qci实现时间感知调度的核心。它就像一个按照时间表周期性开闭的闸门,只有闸门打开时,匹配的流才能被放行。配置流门控的核心是定义这个时间表。
首先,我们需要创建一个门控列表文件(例如sgi.txt),来描述闸门的操作序列。
# 创建一个门控列表文件,内容如下: # 格式解释:操作类型 门状态值 优先级 时间间隔 最大帧数 echo “t0 1b 3 50000 200” > sgi.txt这个文件定义了一个简单的周期性子时间表。t0是时间表开始的参考点(通常为0)。1b是门状态值(Gate States Value),它是一个8位的掩码,每一位对应一个优先级队列(0-7)。1b的二进制是0001 1011,表示优先级0、1、3、4的队列门是打开的(对应位为1),其他优先级队列的门是关闭的。3表示这个门状态持续的时间片索引(与更复杂的周期配置相关,在简单线性列表中可以忽略或用于内部索引)。50000表示这个状态持续的时长,单位是纳秒(这里是50微秒)。200是这个状态下允许通过的最大帧数(可选,用于更精细的控制)。
然后,我们使用qcisgiset命令将这个时间表应用到具体的门控实例上。
# 在端口swp0上,启用索引为1的流门控。 # 设置初始门状态为打开(--initgate 1),初始IPV为0,并加载上面定义的sgi.txt时间表。 tsntool> qcisgiset --device swp0 --enable --index 1 --initgate 1 --initipv 0 --gatelistfile sgi.txt --basetime 0x0关键参数剖析:
--enable:启用这个门控实例。--index:门控实例的ID,需要与流过滤器(qcisfiset)中指定的--gateid对应。--initgate:初始门状态(1为开,0为关)。在时间表开始运行前,闸门处于这个状态。--initipv:初始IPV(Internal Priority Value),影响内部优先级映射,通常设为0。--gatelistfile:指向包含门操作列表的文本文件。--basetime:基准时间,需要与整个网络的调度基准时间同步。通常设置为0,或者与802.1Qbv(时间感知整形器)的基准时间对齐。这是实现全网调度协同的关键。如果网络中有多个设备需要协同调度,它们的basetime必须基于同一个时间源(如802.1AS同步的时间)进行校准。
门控效果验证:配置完成后,我们可以通过发送测试帧来验证。例如,我们发送一个目的MAC和VLAN匹配上述流识别规则的帧。当sgi.txt中定义的门状态为打开时(如1b包含了该流的优先级),帧可以通过swp1(出口端口)被接收到。如果我们修改sgi.txt,将门状态值改为0b(所有门关闭),那么同样的测试帧将无法通过。通过ethtool -S swp1查看端口的统计计数器(如green_prio_3等),可以清晰地看到不同优先级帧的通过情况。
3.3 流计量配置:实施流量监管
流计量器负责对通过的流量进行测量和监管,确保其符合预定义的带宽合约。它通常采用双令牌桶算法,定义了承诺信息速率、承诺突发大小、超额信息速率和超额突发大小。
# 在端口swp0上,配置索引为68的流量计量器。 # 设置CIR为100,000 kbps (100 Mbps), CBS和EBS均为4000字节, EIR为100,000 kbps。 tsntool> qcifmiset --device swp0 --index 68 --cir 100000 --cbs 4000 --ebs 4000 --eir 100000参数计算与选择逻辑:
--index:计量器ID,必须与流过滤器(qcisfiset)中指定的--flowmeterid完全一致。--cir:承诺信息速率,单位是kbps。这是保证提供给流的带宽。--cbs:承诺突发大小,单位是字节。它决定了在短时间内流可以以高于CIR的速率发送多少数据而不被标记为违规。--eir:超额信息速率,单位是kbps。流可以尝试使用的额外带宽。--ebs:超额突发大小,单位是字节。
令牌桶算法的工作方式可以这样理解:有两个桶,一个C桶(承诺),一个E桶(超额)。每个桶以各自的速率(CIR/EIR)累积令牌(每个令牌代表发送一个字节的权利)。数据包到达时,先尝试从C桶中扣除等同于包长的令牌,如果够扣,则包被标记为“绿色”(符合承诺速率)。如果C桶令牌不足,则尝试从E桶中扣除,如果E桶够扣,则包被标记为“黄色”(超出承诺但在超额范围内)。如果两个桶的令牌都不够,则包被标记为“红色”,通常会被丢弃或降级。
监管行为与颜色标记:配置了流计量器后,数据包会被标记为绿、黄、红三种颜色。交换机可以根据颜色采取不同动作,例如让绿色包通过,对黄色包进行限速或标记,丢弃红色包。在LS1028A的测试中,我们通过ethtool -S查看不同颜色帧的计数器来验证效果:
- 发送速率100Mbps的流:所有帧应为绿色(
green_prio_X计数器增加)。 - 发送速率200Mbps的流:部分帧为绿色,部分为黄色(
yellow_prio_X计数器增加),因为超过了CIR但可能在EIR范围内。 - 发送速率300Mbps的流:会出现绿色、黄色和红色帧(
red_prio_X计数器增加)。
“色盲”与“色感”模式:流计量器支持--cf(Color-Aware)模式。在色盲模式下,计量器无视数据包自带的颜色标记(如DSCP中的丢包优先级),从头开始计量。在色感模式下,计量器会考虑数据包输入时的颜色。例如,一个输入就是黄色的包,即使其速率低于CIR,计量器也会直接将其视为黄色包处理,而不会尝试从C桶扣令牌。这在多跳网络中,当上游已经对流量进行过监管和着色时非常有用,可以避免重复计量。命令中增加--cf参数即可启用色感模式。
3.4 端口级默认流过滤
除了基于特定流标识的过滤,LS1028A还支持端口级的默认流过滤器。这对于处理那些未能被任何特定流识别规则匹配的“杂散”流量非常有用。
# 在端口swp0上,设置一个索引为2的流过滤器,但不指定streamhandle。 # 这意味着它将作为该端口的默认过滤器,对所有未被其他SFI匹配的流量生效。 tsntool> qcisfiset --device swp0 --index 2 --gateid 1 --flowmeterid 68配置完成后,任何从swp0进入且未被其他流识别规则匹配的流量,都会自动应用门控1和流量计量器68的策略。这是一种实现“缺省策略”的简洁方式,确保了所有流量都受到基本的监管和控制。
4. 基于Linux tc-flower的Qci配置实践
除了专用的tsntool,LS1028A的驱动也支持通过标准的Linux流量控制工具tc及其flower分类器来配置Qci功能。这种方式更贴近Linux网络栈的通用管理模型,对于熟悉tc命令的工程师来说可能更直观。
4.1 使用tc-flower配置流门控
首先,我们需要在目标网络接口(这里是swp0)上添加一个ingress排队规则,这是使用tc进行入口流量控制的前提。
# 在swp0上添加一个ingress qdisc tc qdisc add dev swp0 ingress接下来,使用tc filter命令添加具体的过滤和门控规则。flower分类器允许我们基于丰富的报文头字段进行匹配。
# 添加一条过滤规则:匹配目的MAC为CA:9C:00:BC:6D:68且VLAN ID为1的报文。 # 对其执行门控动作(gate),基准时间为0,调度条目为关闭6000纳秒。 tc filter add dev swp0 chain 30000 protocol 802.1Q parent ffff: flower skip_sw dst_mac CA:9C:00:BC:6D:68 vlan_id 1 action gate index 1 base-time 0 sched-entry CLOSE 6000 -1 -1命令拆解与注意事项:
chain 30000:指定过滤器链。使用较高的链号可以避免与系统其他规则冲突。protocol 802.1Q:指定匹配802.1Q(VLAN)封装的报文。flower skip_sw:flower是分类器。skip_sw是至关重要的参数,它指示内核将此规则卸载到交换硬件中执行。如果没有这个标志,规则将由CPU软件处理,无法实现线速性能和确定的低延迟。dst_mac CA:9C:00:BC:6D:68 vlan_id 1:匹配条件,目的MAC和VLAN ID。action gate:执行门控动作。index 1:门控实例索引。base-time 0:基准时间。sched-entry CLOSE 6000 -1 -1:定义一个调度条目。CLOSE表示门关闭,持续6000纳秒。后面的-1通常表示门状态掩码和最大帧数,在某些实现中可能被忽略或需特定格式。
重要限制:通过
tc flower配置的Qci流,其入口和出口都必须是桥接端口。这意味着流量必须是从一个交换端口进,从另一个交换端口出。如果流量需要经过CPU端口(例如被Linux网络协议栈处理),则无法成功配置Qci。这是硬件转发路径的限制。
4.2 使用tc-flower配置流计量
类似地,我们可以用tc来配置流量监管。
# 为匹配相同条件的流配置监管器,限制速率为10Mbit,突发为10000字节。 tc filter add dev swp0 chain 30000 protocol 802.1Q parent ffff: flower skip_sw dst_mac CA:9C:00:BC:6D:68 vlan_id 1 action police index 1 rate 10Mbit burst 10000这里的action police就是监管动作。rate和burst参数分别对应CIR和CBS。需要注意的是,通过tc police动作实现的流计量,其监管器资源可能与ACL(访问控制列表)的VCAP资源池共享,在复杂策略下需要注意资源是否够用。
4.3 组合门控与计量及规则管理
我们可以将门控和计量动作组合在一条规则中:
tc filter add dev swp0 chain 30000 protocol 802.1Q parent ffff: flower skip_sw dst_mac CA:9C:00:BC:6D:68 vlan_id 1 \ action gate index 1 base-time 0 sched-entry OPEN 6000 2 -1 \ action police index 1 rate 10Mbit burst 10000这条规则表示:匹配的报文先经过门控(开门6000纳秒),再经过流量监管。
规则的查看与删除:
# 查看swp0上ingress方向,链30000的所有规则 tc -s filter show dev swp0 ingress chain 30000 # 删除指定的规则。需要先通过`show`命令查看到规则的pref(优先级)句柄。 tc filter del dev swp0 ingress chain 30000 pref 49152管理要点:每个流规则只能添加一次。如果你想更新某条流的参数(比如修改速率),必须先删除旧的规则,再添加新的。直接添加重复规则会导致错误。另外,通过
tc添加的流规则,其匹配的MAC和VID必须已经存在于交换机的MAC地址表中,否则规则可能无法正确生效。这通常意味着需要先有相应的数据流通过,或者静态添加MAC表项。
5. 常见问题排查与调试技巧实录
在实际部署和调试Qci功能时,会遇到各种各样的问题。下面我整理了一些典型问题的排查思路和解决方法,这些都是从实际项目中积累下来的经验。
5.1 流规则不生效,流量未被过滤或门控
这是最常见的问题。请按照以下步骤排查:
- 检查流识别配置:首先确认
cbstreamidset命令中的目的MAC和VLAN ID是否与测试流量完全一致。注意MAC地址的格式(去冒号十六进制),以及VLAN ID是十进制数字。使用tcpdump或wireshark在入口端口抓包,确认测试帧的头部信息。 - 检查流过滤器关联:确认
qcisfiset命令中的--streamhandle与cbstreamidset中的--streamhandle数值相同。这是关联流识别和流处理的关键。 - 验证端口与方向:确保所有配置都施加在正确的入口端口上。Qci是入口控制机制。使用
bridge vlan show检查端口的VLAN成员关系,确保测试流量所在的VLAN在端口上是允许通过的。 - 查看硬件计数器:使用
ethtool -S <port_name>命令查看端口的详细统计信息。关注green_prio_X,yellow_prio_X,red_prio_X,dropped等计数器。发送测试流量后,观察对应优先级的计数器是否增加。如果没有任何计数器变化,说明流量可能根本没匹配上流识别规则。 - 检查门控状态:如果流量被识别但没通过,可能是门处于关闭状态。确认
qcisgiset命令已执行且--enable。检查门控列表文件sgi.txt中的门状态值(如1b)是否包含了该流优先级对应的位。优先级0对应最低有效位。例如,流优先级为3,则需要检查二进制掩码的第3位(从0开始数)是否为1。
5.2 流量计量结果与预期不符
如果流量颜色的统计(绿/黄/红)不符合基于CIR/EIR的计算预期,请检查:
- 参数单位:
tsntool的--cir和--eir参数单位是kbps,而tc police的rate参数单位是Mbit或kbit。务必确保单位换算正确。100 Mbps = 100,000 kbps。 - 突发大小设置:
--cbs和--ebs的单位是字节。设置过小会导致令牌桶很快被耗尽,即使平均速率不高,也可能产生大量黄色或红色帧。一个经验法则是,CBS至少应大于一个最大帧的长度(如1500字节),并考虑链路速率和延迟。例如,对于100Mbps链路,1毫秒内可传输12.5KB数据,将CBS设为4000字节(约0.32毫秒的数据量)是一个合理的起始值。 - 测试流量特性:确保测试仪生成的流量是连续的、速率稳定的。如果使用
iperf或自定义工具,注意其发包模型(如UDP突发)可能无法精确反映令牌桶算法的行为。 - 共享资源冲突:如前所述,Qci流计量器可能与ACL共享硬件资源池。如果系统中配置了大量的ACL规则,可能导致没有足够的资源分配给Qci计量器。尝试简化其他配置进行排查。
5.3 tc-flower规则添加失败或不起作用
skip_sw标志:这是最容易被忽略的一点。没有skip_sw,规则不会卸载到硬件,也就无法实现Qci的硬件加速。确保命令中包含了skip_sw。- MAC地址学习:通过
tc flower配置的流规则,要求匹配的目的MAC地址必须已经存在于交换机的MAC地址表中。如果目的主机还没有发送过数据包,它的MAC地址就不会被学习到。解决方法有两种:一是先让目的主机发送一个包(例如ping);二是在网桥上静态添加该MAC地址的表项:bridge fdb add <dst_mac> dev <egress_port> master。 - 入口/出口限制:再次强调,
tc flowerQci规则要求流量路径完全在交换芯片内部(桥接端口到桥接端口)。如果流量需要路由(经过CPU),规则不会生效。检查你的网络拓扑,确保测试流是从一个交换端口进入,从另一个交换端口出去。 - 规则优先级与冲突:使用
tc -s filter show dev swp0 ingress检查所有入口规则。可能存在多条规则匹配同一个流,优先级(pref)高的规则先执行。确保你的Qci规则有合适的优先级,且没有被其他规则(如ACL)提前拦截或覆盖。 - 驱动与内核版本:确认你使用的内核和驱动版本支持所需的Qci offload功能。查阅NXP官方发布说明和驱动文档。
5.4 时间同步与门控基准时间问题
Qci的门控依赖于精确的时间。如果basetime设置不当,或者整个网络没有进行时间同步(如使用802.1AS),门控行为可能会混乱。
- 基准时间对齐:
--basetime参数需要与网络调度周期对齐。在复杂网络中,它通常需要从全局调度器获取,并与Qbv(时间感知整形)等其它时间调度特性同步。在独立测试中,可以简单设为0。 - 门控周期:确保门控列表文件
sgi.txt中定义的时间间隔总和是合理的,并且与测试流量的发送周期没有冲突。例如,如果门关闭时间过长,可能会丢失整个发送窗口的数据。 - 系统时间同步:虽然Qci门控主要依赖硬件时钟,但确保Linux系统时间大致准确有助于调试和日志分析。可以考虑在设备上运行
ntpd或chronyd。
调试是一个迭代的过程。我的建议是从简到繁:先配置最简单的流识别和过滤,确保流量能被正确匹配和计数。然后单独测试门控,再单独测试计量。最后再将所有功能组合起来。充分利用ethtool -S和tsntool的get命令(如qcisfiget)来查询硬件状态,是定位问题最有效的手段。