简介:《S1 data forwarding测试小结.docx》是一份聚焦LTE切换场景下S1数据转发机制的笔记型文档,适合移动通信网络优化、基站测试及核心网运维人员快速梳理切换流程与信令要点。内容基于实际抓包与信令流程,系统讲解了切换前后数据流向、End Marker的作用、TEID与Sequence Number在GTP隧道中的标识意义,并逐一拆解HANDOVER REQUEST ACK、HANDOVER COMMAND、RRC重配置及HANDOVER NOTIFY等关键信令中的地址与隧道参数变化,同时给出了数据转发检查点(如源小区0x01001008到转发地址切换)的具体观察方法。资源为1个docx文件,包体约769KB,文本结构紧凑,适合作为外场测试前的速查手册。目前已有304人学习,对于需要理解LTE切换数据面转发细节的读者,可借此文档快速建立端到端排查思路,避免在信令跟踪中遗漏关键检查点。
1. S1 data forwarding测试:核心网侧最容易忽略的切换丢包关口
做LTE和5G NSA接入网测试的人,多半在切换用例里见过S1 data forwarding这个字段,但真正把它单独拎出来测过的人不多。我最早接触S1 data forwarding是在一次异站切换丢包排查里:基站侧切换成功率百分之百,核心网侧也没有告警,但业务面就是有周期性丢包。最后抓S1接口信令,发现是data forwarding的GTP-U隧道建晚了,源基站的下行数据已经发到空口,转发隧道还没就绪,丢包自然不可避免。
S1 data forwarding解决的是切换期间下行数据不中断的问题,本质是源基站把来不及发出去的下行数据通过核心网转发给目标基站,再由目标基站发给终端。它发生在S1切换流程里,直接关系VoLTE通话质量和TCP业务吞吐表现。适合做接入网测试、核心网测试以及端到端业务保障的人关注。这个测试点不算复杂,但涉及S1AP信令、GTP-U隧道、计费面协同三个层面的配合,任何一个环节配错,切换就埋雷。
2. 数据转发在S1切换路径里的位置:从信令面到用户面的完整拆解
2.1 S1切换与X2切换的转发差异:什么时候必须走S1 data forwarding
要理解S1 data forwarding,先得把切换路径讲清楚。同一基站下的小区切换不涉及核心网,两个基站之间有X2接口且配置正常时,优先走X2切换,数据转发直接通过X2的用户面完成。但一旦遇到跨MME、跨SGW的场景,或者运营商在配置里关闭了X2切换(比如为了便于话单统计和位置管理),就只能退回S1切换,此时data forwarding的路径也变了:源基站不再直接把数据发给目标基站,而是先发给源SGW,由SGW通过核心网内部路径转发给目标SGW,再到达目标基站。
这个差别直接影响测试设计。X2切换里验证data forwarding,看的是两个基站之间的GTP-U隧道建立是否及时;而S1切换里验证data forwarding,要同时盯住源基站与源SGW之间、源SGW与目标SGW之间的两条隧道。实际测试中常见一个误区:把X2切换的数据转发测试经验直接套到S1切换上,只抓空口和基站侧日志,忽略核心网内部转发路径,结果丢包定位半天找不到根因。
2.2 切换准备阶段:E-RAB建立与S1AP信令里隐藏的转发标记
S1 data forwarding从切换准备阶段就已经开始埋线索了。源基站向MME发送Handover Required消息时,消息里携带的是源侧已经分配好的S1 data forwarding隧道信息。这里注意一个细节:这个隧道信息不是在Handover Required里带的,而是在MME向目标基站发Handover Request时,由MME在消息里告诉目标基站"如果数据转发被激活,请准备好接收地址"。
实操里我习惯在S1AP的Handover Request消息里重点看两个IE:Direct Forwarding Path Availability和Data Forwarding Not Possible。前者表示源基站到核心网的直连转发路径是否可用,后者明确告诉你当前场景下能不能做数据转发。如果目标基站回复的Handover Request Acknowledge里带了Data Forwarding TEID,说明目标侧已经为转发准备好了GTP-U隧道;如果没带,后续切换流程里数据转发就会被跳过,直接走丢包窗口。
这个阶段的测试重点是确认目标基站是否根据收到的转发标记做了正确响应。我一般会在测试用例里分别构造"支持转发"和"不支持转发"两种场景,验证目标基站的行为是否符合预期。
2.3 切换执行阶段:下行数据在源基站侧停发与GTP-U路径切换
切换执行阶段的data forwarding最考验时序。当MME向源基站下发Handover Command后,源基站需要停止向终端发送下行数据,同时启动一个定时器,把尚未发送的下行数据通过S1 data forwarding隧道发给核心网。这个"停止发送"和"开始转发"之间的时间窗口,就是丢包风险最大的区间。
具体到GTP-U层,源基站发出的转发数据包使用GTP-U头里的TEID标识路径,这个TEID就是目标基站在Handover Request Acknowledge里分配的那个。数据包到达源SGW后,SGW根据TEID找到对应的转发隧道,将数据包转发给目标SGW,目标SGW再发送给目标基站。目标基站收到转发数据后,会缓冲起来,等到终端完成随机接入后按序下发。
这里有一个关键时序需要测试确认:目标基站是等终端接入后才开始下发缓冲数据,还是收到就立刻发。两种策略各有取舍,前一种保证顺序但增加时延,后一种可能乱序。当前主流实现是前者,但测试时还是要根据具体设备行为来确认。
2.4 切换完成阶段:End Marker与SGW路径切换的配合逻辑
切换完成阶段是S1 data forwarding测试里最容易测出隐性缺陷的一环。当终端在目标小区完成随机接入后,目标基站向MME发送Handover Notify,触发核心网侧的路径切换。此时SGW会把下行用户面的数据路径从源基站切换到目标基站,同时向源基站发送End Marker,告诉源基站"我已经不在旧路径上发数据了"。
这个阶段的核心检查点是End Marker是否沿着数据转发路径完整走完。End Marker从SGW发出,经过源SGW、源基站,最终到达目标基站,目标基站通过识别End Marker来判断数据流的边界。我在测试中遇到过End Marker丢失的情况,直接后果是目标基站一直等不到流结束标记,缓冲的数据无法判定完整性,最终表现为切换后业务面短暂中断甚至丢包。
测试时需要在目标基站侧同时抓两个接口:S1用户面的转发隧道数据和空口的无线数据。对照这两个接口的时间戳,确认End Marker到达目标基站后,目标基站是否立刻开始按序下发缓冲数据。如果End Marker到达时间和空口数据恢复时间有明显偏差,优先怀疑核心网的转发路径有问题。
3. 用Wireshark过滤S1接口信令:data forwarding测试的最小抓包方案
3.1 抓包位置与过滤条件:从S1-MME和S1-U两个平面分别取证
S1 data forwarding涉及控制面和用户面两个平面,抓包位置选择直接影响后续分析的效率。控制面走S1-MME接口(SCTP协议承载S1AP信令),抓包点通常镜像在基站与MME之间的传输链路上;用户面走S1-U接口(UDP承载GTP-U协议),抓包点镜像在基站与SGW之间的传输链路上。如果测试环境里有交换机镜像口,优先在镜口同时挂两个抓包进程,确保控制面和用户面时间戳对齐。
抓包长度方面,S1AP信令通常不超过几百字节,但GTP-U数据面可能是满包,建议抓包长度设置成固定字节数,够用就行,避免大文件拖慢分析速度。存储上按切换用例分组保存文件,避免一次抓包跑完所有用例、后续定位时在巨型pcap里来回找。
3.2 用python构造S1AP过滤脚本:从pcap里快速定位Handover报文
Wireshark的显示过滤器可以直接过滤S1AP协议,但遇到跨多个文件检索时效率太低。我通常会用python写一个简单的解析脚本,批量扫描pcap文件里的S1AP消息,只抽取Handover相关流程。
import pyshark def extract_s1_handover(pcap_path): """ 从pcap里抽取S1AP Handover相关消息,只保留关键字段 """ cap = pyshark.FileCapture(pcap_path, display_filter='s1ap') results = [] for pkt in cap: try: if hasattr(pkt, 's1ap'): proc_code = pkt.s1ap.procedureCode # 3=Handover Preparation, 4=Handover Resource Allocation, 5=Handover Notification if proc_code not in ['3', '4', '5']: continue info = { 'time': pkt.frame_info.time_relative, 'src': pkt.ip.src, 'dst': pkt.ip.dst, 'procedure': proc_code } # 尝试提取Data Forwarding相关的IE if hasattr(pkt.s1ap, 'dataForwardingNotPossible'): info['df_not_possible'] = pkt.s1ap.dataForwardingNotPossible if hasattr(pkt.s1ap, 'bearers_forwarding_teid'): info['forwarding_teid'] = pkt.s1ap.bearers_forwarding_teid results.append(info) except AttributeError: continue cap.close() return results if __name__ == '__main__': events = extract_s1_handover('s1_switch_test.pcap') for ev in events[:20]: print(ev)这个脚本依赖pyshark库,底层调用了tshark解析引擎。procedureCode是判断S1AP消息类型的关键字段,3对应Handover Required,4对应Handover Request和Handover Request Acknowledge,5对应Handover Notify。实际使用注意pyshark解析大文件时内存占用较高,超过2GB的pcap建议先用Wireshark做好初步过滤再导入python。
参数调整时,如果只想看Handover准备阶段的信令,可以把过滤条件改成只保留procedureCode 3和4。如果关注的是切换完成后的路径切换,只看procedureCode 5即可。我一般同时导出到CSV文件,方便在Excel里做跨文件的时序对齐。
3.3 从信令时间戳判断转发隧道是否建晚:一个三节点时序对照法
拿到抓包文件后,判断data forwarding隧道是否建晚,核心是看三个时间点:目标基站发送Handover Request Acknowledge的时刻、源基站收到Handover Command的时刻、以及SGW向源基站发送End Marker的时刻。
正常的时序是:Handover Request Acknowledge携带目标基站的转发TEID返回MME,MME再发送Handover Command给源基站。因此Handover Request Acknowledge的时间必须早于或等于Handover Command的时间,中间的时间差就是MME处理信令的开销。如果出现反向时序,说明MME在下发命令时没有等目标基站确认转发隧道就绪,此时源基站只能先停发数据,等隧道建好后补发,丢失窗口自然放大。
实际排障时我会把这三个时间点记录到一张表里,以Handover Request Acknowledge为基准算偏差。偏差超过100毫秒就要进一步抓核心网内部日志,看是SGW处理慢还是MME转发出问题。
4. S1 data forwarding的4个必调参数:从设备配置到核心网协商规则
4.1 源基站侧:转发优先级与缓存时长的设置关系
源基站在切换命令下发后,既要停发空口数据,又要决定哪些数据需要走转发隧道。这里有两个参数直接影响转发行为:转发数据缓存时长和转发优先级。缓存时长决定了源基站在切换命令下发后,等待转发隧道建立的最大容忍时间。如果隧道在缓存时长内没建立成功,源基站直接丢弃数据,不再尝试转发。
转发优先级一般复用QoS参数里的优先级标识(ARP),但需要和设备实现确认是否真正参与调度。有些基站实现了基于优先级的转发丢弃策略,低优先级业务缓存更短、更早被丢弃;有些只是透传。测试前我建议先发一个短ping流验证基础转发,再用满带宽TCP流压测低优先级业务,确认优先级参数真的生效。
4.2 MME侧:Data Forwarding Not Possible与直接转发路径协商
MME在整个S1 data forwarding流程里的角色是信令转发和路径决策。核心网配置里有两个参数需要关注:是否允许数据转发和是否启用直接转发路径。前者是一个总开关,关闭后MME不会在切换准备阶段向目标基站请求转发资源;后者决定转发数据是走SGW间接路径,还是允许源基站直接向目标基站转发。
这两个参数在2G/3G时代可能都默认开启,但4G时代直接转发路径存在争议,因为涉及安全性和计费一致性问题。测试时需要分别验证三种组合:全关、开转发但关直接路径、全开。如果设备支持的是非标准实现,实际转发路径可能和文档描述不符,需要从摘要里确认。
4.3 SGW侧:转发隧道超时与End Marker重发机制
SGW是数据转发路径上的中转站,它的行为直接决定转发数据能否按序到达。SGW上的关键参数是转发隧道超时时间和End Marker重发次数。当SGW把下行数据路径切换到目标基站后,源基站侧的旧转发隧道就处于半开状态,SGW需要维护一个超时定时器,超时后回收隧道资源。
End Marker重发次数则是应对丢包的最后防线。标准规定SGW发送End Marker后不再重发,实际测试发现部分核心网实现支持配置重发次数,这个功能在空口质量差的场景下有实际作用。
4.4 目标基站侧:缓冲队列长度与数据序号的冲突处理
目标基站接收转发数据后,需要做缓冲和排序。这里两个参数最关键:缓冲队列长度和数据序号连续性检查机制。缓冲队列长度决定目标基站能容忍多少转发数据的到达抖动,如果队列溢出,目标基站直接丢弃后续到达的数据。
数据序号连续性检查则处理"转发数据和目标基站直接接收的数据之间的序号空洞"问题。正常流程里,切换命令下发后目标基站从转发隧道收到数据,但终端在目标小区接入后,核心网直接发送的新数据和转发数据之间可能存在一定时间差,此时目标基站需要缓存转发数据,等新数据到达后做排序。
5. S1 data forwarding测试避坑:切换成功率100%不代表没丢包
5.1 信令面全绿但业务面周期性丢包:先查GTP-U层TEID是否复用
现象:S1AP信令全部正常,切换成功率100%,但业务面每隔几次切换就出现一次短暂丢包,丢包时长在数十毫秒量级。
原因:目标基站分配的转发TEID被提前复用。基站侧转发隧道资源管理不严谨时,前一次切换的转发隧道还没完全释放,新一次切换又分配了相同TEID,导致数据被路由到错误隧道路径上。
解决:抓S1-U报文对比相邻两次切换的TEID分配记录,如果发现TEID相同,进一步等待隧道释放完成后再触发下一次切换。必要时向设备厂商提单确认隧道资源回收逻辑。这个坑在异厂商组网里最容易出现。
5.2 Handover Command先于转发隧道就绪:MME时序缺陷导致的必丢窗口
现象:从S1AP报文看,Handover Command的发送时间早于Handover Request Acknowledge的接收时间。
原因:MME在实现切换流程时,没有严格等待目标基站完成转发资源预留就提前向源基站下发了切换命令。源基站收到命令后立即执行切换动作,停发空口数据,此时转发隧道尚未建立,数据无处可去。
解决:核心网升级后回归必测项。遇到这个时序问题先确认MME版本是否支持转发资源预留等待机制,确认SGW与MME之间是否存在消息串行处理的bug。
5.3 目标基站缓冲数据不按序下发:终端TCP性能骤降
现象:切换完成后空口没有丢包,但在终端侧抓TCP抓包看到序列号乱序严重,TCP吞吐下降一半以上,需要几秒才能恢复到切换前水平。
原因:目标基站收到转发数据和收到核心网新数据的先后顺序与标准不完全一致,但目标基站没有做完整的排序,直接把先到的数据先发了出去。
解决:检查目标基站的切换缓冲管理参数,确认是否有"等待End Marker后再统一下发"的开关。如果没有该开关或者开关被关闭,需要协调基站厂商开启按序下发策略。这个坑在VoLTE语音业务上更隐蔽——语音不重传,乱序直接产生杂音。
5.4 切换后GTP-U序号断开:用序号连续性检查区分漏发还是乱序
现象:核心网下发的GTP-U报文序号出现规律性跳变,但不是每次切换都发生,和业务速率强相关。
原因:SGW路径切换时,新路径和旧路径上的数据存在时间重叠,但SGW没有把两段数据做序号连续性处理,或者GTP-U头里的序号字段本身没有启用。
解决:在SGW侧同时抓切换前后两段S1-U报文,按GTP-U序号字段排序对比。如果设备没有实现GTP-U序号扩展头,需要通过数据面的PDCP序号或者应用层TCP序号来做数据完整性核对。
6. 把S1 data forwarding测试做成自动校验脚本:把经验固化成一条命令
6.1 用python搭建一个pcap自动比对脚本:核心逻辑与实现要点
前面step by step的抓包分析解决的是单次问题定位,但如果S1 data forwarding测试要作为常规回归项,人工分析pcap的方式不可持续。我习惯把整个分析流程固化成python脚本,自动输出一份"切换数据转发质量报告",直接判断测试是否通过。
import pyshark from collections import defaultdict def analyze_s1_forwarding(pcap_control, pcap_user): """ 自动化分析S1 data forwarding关键路径时延 输入: 控制面pcap和用户面pcap镜像文件 输出: 转发就绪时延、End Marker时延、丢包窗口判断 """ # 第一步: 解析控制面信令, 提取关键时间点 cap_ctrl = pyshark.FileCapture(pcap_control, display_filter='s1ap') handover_ack_time = None handover_cmd_time = None notify_time = None for pkt in cap_ctrl: try: proc_code = pkt.s1ap.procedureCode if proc_code == '4': # Handover Request Acknowledge handover_ack_time = pkt.frame_info.time_relative elif proc_code == '3': # Handover Command handover_cmd_time = pkt.frame_info.time_relative elif proc_code == '5': # Handover Notify notify_time = pkt.frame_info.time_relative except AttributeError: continue cap_ctrl.close() # 第二步: 解析用户面数据, 计算转发数据包数量与End Marker到达时间 cap_user = pyshark.FileCapture(pcap_user, display_filter='gtp') end_marker_time = None forward_packet_count = 0 for pkt in cap_user: try: if hasattr(pkt, 'gtp'): # End Marker是GTP-U头里length为0的特殊报文 if int(pkt.gtp.length) == 0: end_marker_time = pkt.frame_info.time_relative else: forward_packet_count += 1 except AttributeError: continue cap_user.close() report = { 'handover_ack_to_cmd_ms': _time_diff(handover_ack_time, handover_cmd_time), 'cmd_to_notify_ms': _time_diff(handover_cmd_time, notify_time), 'end_marker_delay_ms': _time_diff(handover_ack_time, end_marker_time), 'forwarded_packets': forward_packet_count } return report def _time_diff(t1, t2): if t1 and t2: return round((float(t2) - float(t1)) * 1000, 2) return None if __name__ == '__main__': result = analyze_s1_forwarding('ctrl.pcap', 'user.pcap') print(result) # 自动判定: 转发就绪时延超过100ms给出警告 if result['handover_ack_to_cmd_ms'] and result['handover_ack_to_cmd_ms'] > 100: print('WARNING: forwarding tunnel setup too slow')脚本的核心判断逻辑就三个数值:Handover Request Acknowledge到Handover Command之间的时延,这个值越小说明转发隧道预留越及时;Handover Command到Handover Notify之间的时延,反映空口切换的执行时长;End Marker相对转发隧道建立的时延,反映SGW路径切换的响应快慢。
参数阈值需要根据测试环境的设备能力标定。我在现网测试里常用的阈值是:转发就绪时延不超过100毫秒,End Marker时延不超过50毫秒,转发数据包数不能为0。如果连续多组数据都超出阈值,直接把报告发给核心网团队定位SGW或MME的处理瓶颈。
6.2 把这个脚本嵌入CI/CD:让每次核心网版本升级都自动跑一遍
这个脚本适合嵌入持续集成流程。在核心网或基站升级前,先在隔离环境触发一轮S1切换测试,自动抓包、自动分析、自动输出对比基线。升级后再跑一遍,对比两次报告的转发时延和End Marker时延,超过预设阈值就直接标记为主版本回退候选。
实际落地时建议做一个简单的封装脚本,把抓包命令和分析脚本串联起来,保证每次测试的执行参数一致。抓包时长控制在单次切换流程即可,脚本分析也只需要几秒钟。
6.3 从S1 data forwarding延伸:5G N2切换里的数据转发验证思路
S1 data forwarding的经验可以直接往5G迁移。5G NSA和SA架构里没有S1接口,对应的是N2和N3接口,但转发链路的基本逻辑相似。SA切换里,数据转发路径变成了gNB与UPF之间的N3隧道,且引入了PLMN间切换场景,转发可能要跨多个UPF节点。
做5G切换测试时,我习惯沿用S1 data forwarding的思路,但调整关注点:在N2接口的Handover Request消息里检查转发TEID字段,在N3接口抓GTP-U数据进行发包计数,在UDM或AMF侧确认路径切换是否涉及UPF重新选择。核心验证维度不变:转发隧道是否及时建立、数据是否完整转发、End Marker是否到达。只要这三个维度通过,S1和N2的切换数据面质量就有基本保障。
做S1 data forwarding测试这几年,我最深的感触是:切换信令流程里的每个毫秒都可能成为丢包窗口的黑匣子。测试不能只满足于信令流程走通,还要把每个信令点之间的时间差记录下来,形成自己的基线数据。希望这份经验能帮你在S1 data forwarding测试里少踩几个坑。
本文还有配套的精品资源,点击获取