深度解析 3GPP TS 29.281:Chapter 5 GTP-U Header (数据包的身份证)

本文技术原理深度参考了3GPP TS 29.281 V18.3.0 (2024-12) Release 18规范,将聚焦 Chapter 5 GTP-U header 核心章节。在前两篇文章中,我们建立了GTP-U隧道的宏观概念并探究了其两端协议实体的运作机制。本篇,我们将扮演“微观解剖学家”的角色,把一个GTP-U数据包放到“手术台”上,仔细剖析它的“身份证”——GTP-U头部,揭示每一个字段和标志位背后隐藏的秘密。

在前文的旅程中,我们的主角小明一直在他的5G手机上流畅地观看4K火箭发射直播。我们知道,承载这股视频洪流的是一条建立在UPF和gNB之间的GTP-U隧道。

现在,为了让故事更有趣,我们让小明坐上一辆飞驰的高速列车。当列车穿过城市,小明的手机需要不断地从一个基站(gNB)切换到另一个基站,以保持网络连接。这个过程被称为“切换”或“Handover”。

正是这个看似寻常的切换动作,为我们提供了一个绝佳的契机,去深入理解GTP-U头部的精妙设计。因为在切换过程中,为了保证小明的视频流“无缝衔接”,GTP-U头部中的许多可选字段和扩展头将扮演至关重要的角色。

1. GTP-U头部的标准照:通用格式 (General format)

让我们先从一个静止的、非切换状态下的普通GTP-U数据包开始。这个包就是我们前面比喻的,装载着小明视频数据的“集装箱”。它的头部,就是贴在集装箱上的“运单”,包含了最基础的物流信息。

The GTP-U header is a variable length header whose minimum length is 8 bytes. There are three flags that are used to signal the presence of additional optional fields: the PN flag, the S flag and the E flag.

规范开篇点明,GTP-U头部最少有8个字节(Octets),这是所有GTP-U包都必须具备的强制部分。其中,有三个关键的“开关”型标志位(Flag),它们决定了头部是否会携带额外的可选信息。

现在,我们参考规范中的“Figure 5.1-1: Outline of the GTP-U Header”,将其“翻译”成一张更易于理解的Markdown表格,并逐一解剖这8个字节的每一个比特。

图解:GTP-U强制头部结构 (8字节)

| Octet | Bit 8 | Bit 7 | Bit 6 | Bit 5 | Bit 4 (E) | Bit 3 (S) | Bit 2 (PN) | Bit 1 |

| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |

| 1 | Version (3 bits) | PT (1 bit) | (*) | E | S | PN |

| 2 | \multicolumn{8}{c|}{Message Type (8 bits)} |

| 3-4 | \multicolumn{8}{c|}{Length (16 bits)} |

| 5-8 | \multicolumn{8}{c|}{Tunnel Endpoint Identifier (TEID) (32 bits)} |


当E、S、PN任一标志位置1时,才会出现后续的可选字段(9-12字节)。

| Octet | \multicolumn{8}{c|}{Content} |

|:---:|---|

| 9-10 | \multicolumn{8}{c|}{Sequence Number (16 bits) - (当S=1时存在且有效)} |

| 11 | \multicolumn{8}{c|}{N-PDU Number (8 bits) - (当PN=1时存在且有效)} |

| 12 | \multicolumn{8}{c|}{Next Extension Header Type (8 bits) - (当E=1时存在且有效)} |


下面,我们来详细解读这些“始终存在”(Always present fields)的字段:

1.1 第1字节:版本与核心标志

  • Version (版本号, 3 bits)

    Version field: This field is used to determine the version of the GTP-U protocol. The version number shall be set to ‘1’.

    这个字段定义了GTP协议的版本。对于我们讨论的GTPv1-U,这个值固定为二进制的001,即十进制的1。网络设备收到包后,先检查这3个比特,就能知道该用哪个版本的规范来解析后续的字段。

  • PT (Protocol Type, 协议类型, 1 bit)

    Protocol Type (PT): This bit is used as a protocol discriminator between GTP (when PT is ‘1’) and GTP’ (when PT is ‘0’).

    PT位置1代表是GTP协议(包括GTP-C和GTP-U),为0则代表是GTP’(GTP Prime)协议,后者主要用于计费领域。对于小明的数据包,这里必然是1。

  • (*) (Spare bit, 预留位, 1 bit)

    这个比特位在当前版本中未使用,发送时应设为0,接收方不应解析。

  • E, S, PN (三大标志位)

    这三个1比特的标志位是整个头部的“扩展开关”,我们稍后会详细展开。

    • E (Extension Header flag): 置1表示后面跟着一个或多个“扩展头”。这是GTP-U协议保持灵活和前瞻性的关键。

    • S (Sequence number flag): 置1表示头部包含了16位的“序列号”字段。

    • PN (N-PDU Number flag): 置1表示头部包含了8位的“N-PDU Number”字段,这个字段主要用于2G/3G兼容的一些场景。

对于小明正在观看的4K直播,为了保证画面的流畅,网络很可能为他的业务启用了保序投递功能,因此S标志位会被置为1

1.2 第2-8字节:核心身份与尺寸信息

  • Message Type (消息类型, 8 bits)

    Message Type: This field indicates the type of GTP-U message.

    这个字段标识了这是一个什么类型的GTP-U包。它可以是承载用户数据的G-PDU,也可以是用于路径管理的信令消息(如Echo Request/Response)。对于承载小明视频数据的包,其消息类型值为255 (0xFF),代表这是一个G-PDU。

  • Length (长度, 16 bits)

    Length: This field indicates the length in octets of the payload, i.e. the rest of the packet following the mandatory part of the GTP header (that is the first 8 octets). The Sequence Number, the N-PDU Number or any Extension headers shall be considered to be part of the payload…

    这是一个非常关键的字段。它定义的不是整个GTP-U包的长度,而是从第9个字节开始的载荷部分的总长度。这个“载荷”不仅包括用户的原始T-PDU,还包括了所有由E/S/PN标志位引入的可选字段和扩展头。接收端(gNB)需要靠这个Length字段来准确地找到用户T-PDU的起始位置。

  • TEID (Tunnel Endpoint Identifier, 隧道端点标识符, 32 bits)

    Tunnel Endpoint Identifier (TEID): This field unambiguously identifies a tunnel endpoint in the receiving GTP-U protocol entity… The TEID shall be used by the receiving entity to find the PDP context…

    这是我们反复强调的GTP-U之魂。这个32位的数字唯一地标识了小明的这条下行视频数据流。当gNB收到这个包时,它会查看TEID字段,就像在庞大的邮件系统中查找一个特定的邮箱号,从而立即知道这个数据包属于哪个用户、哪个业务,应该如何处理。

2. GTP-U的“附加页”:扩展头 (GTP-U Extension Header)

现在,我们的主角小明坐着高铁,即将进入下一个基站gNB-B的覆盖范围。网络需要为他执行一次无感的切换。这意味着,UPF需要将数据流从通往gNB-A的旧隧道,平滑地切换到通往gNB-B的新隧道上。

在这个过程中,一些临时的、特殊的信息需要在节点间传递,而这些信息并不适合放在强制的8字节头部里。这正是扩展头大显身手的时刻!此时,GTP-U头部的E标志位会被置为1

2.1 扩展头的通用结构

The format of GTP-U Extension Headers is depicted in figure 5.2.1-1. The Extension Header Length field specifies the length of the particular Extension header in 4 octets units. The Next Extension Header Type field specifies the type of any Extension Header that may follow a particular Extension Header. If no such Header follows, then the value of the Next Extension Header Type shall be 0.

所有扩展头都遵循一个统一的格式,这使得协议解析变得规范和简单。

| 字段 | 长度 | 描述 |

|---|---|---|

| Extension Header Length | 1字节 | 表示该扩展头的总长度,单位是4字节。例如,值为2,表示该扩展头总长为 2 * 4 = 8 字节。 |

| Extension Header Content | 变长 | 扩展头的实际内容,其长度由Extension Header Length决定。 |

| Next Extension Header Type | 1字节 | 指向下一个扩展头的类型。如果这是最后一个扩展头,则该字段值为0。 |

这种“链式”结构非常精妙。接收端解析完一个扩展头后,通过查看Next Extension Header Type字段,就知道后面是否还有、以及是什么类型的扩展头,从而可以像顺着藤蔓摸瓜一样,逐个解析所有扩展头,直到遇到类型值为0的“终结符”。

2.2 切换场景中的关键扩展头类型

现在,让我们跟随小明的切换过程,看看哪些扩展头正在为他的流畅体验保驾护航。规范在 “Figure 5.2.1-3: Definition of Extension Header Type” 中定义了多种扩展头类型,我们挑选几个与切换最相关的进行解读。

类型 0b11000000: PDCP PDU Number

(注:规范中值为-,即TS 36.323和TS 38.323,这里用二进制表示其类型值)

场景: 在切换的瞬间,gNB-A可能已经从UPF收到了一些数据包,但还没来得及通过空口发给小明。为了不让这些数据丢失,gNB-A需要将这些“缓冲”的数据通过一条临时的Xn接口GTP-U隧道,转发给新的gNB-B。

但是,gNB-B如何知道这些转发过来的数据包,哪些是小明手机已经收到的,哪些是需要接着发的呢?这就需要用到PDCP层的序列号。

This extension header is transmitted, for example in UTRAN, at SRNS relocation time, to provide the PDCP sequence number of not yet acknowledged N-PDUs. … When used during a handover procedure between two NG-RANs at the Xn interface (direct DL data forwarding)…

gNB-A在转发这些数据包时,会在GTP-U头部添加这个扩展头,里面携带了该数据包在PDCP层的序列号。gNB-B收到后,就能精确地知道这个包的“身份”,从而实现:

  1. 避免数据重复:如果gNB-B后续又从UPF收到了同样PDCP序列号的包,就可以将其丢弃。

  2. 保证有序发送:gNB-B可以根据PDCP序列号,将转发来的数据和从UPF新收到的数据进行正确排序,再按序发给小明。

这个小小的扩展头,是实现真正“无损切换”(Lossless Handover)的核心技术之一,它直接关系到小明的视频会不会在切换时卡顿一下。

类型 0b10000101: PDU Session Container

场景: 切换流程启动后,UPF需要停止向旧的gNB-A发送数据,并将数据流转向新的gNB-B。为了确保gNB-A知道数据流已经结束,不会再有新的用户数据包过来,UPF会向旧的隧道发送一个特殊的信令包——End Marker(结束标记)

End Marker本身也是一个GTP-U包,但它不带用户数据(T-PDU为空)。在5G网络中,一个用户的PDU会话可能包含多个具有不同QoS要求的业务流(QoS Flow),比如小明可能同时在看4K视频(QoS Flow 1)和后台下载文件(QoS Flow 2)。

in End Marker packets over data forwarding tunnels in 5GS, for data forwarding between 5GS and EPS. The PDU Session Container has a variable length and its content is specified in 3GPP TS 38.415.

当切换只涉及到部分业务流时(例如,只切换视频流),UPF发送的End Marker需要明确指出“是哪个QoS Flow的数据结束了”。这些QoS相关的信息,就装在PDU Session Container这个扩展头里。

gNB-A收到带有此扩展头的End Marker后,就能精确地知道:“好的,TEID为XXXX的隧道中,QFI(QoS Flow Identifier)为1的视频流已经结束了,我可以释放相关资源了。” 这保证了网络资源管理的精细度和准确性。

类型 0b10000100: NR RAN Container

场景: 在gNB-A和gNB-B之间进行切换决策和准备时,它们需要交换一些纯粹与无线接入网(RAN)相关的信息,这些信息对于核心网的UPF来说是“不透明”也无需理解的。

This extension header may be transmitted in a G-PDU over the X2-U, Xn-U and F1-U user plane interfaces, within NG-RAN… The NR RAN Container has a variable length and its content is specified in 3GPP TS 38.425.

例如,gNB-A可能需要告诉gNB-B一些关于小明手机无线能力的上下文信息。这些信息就可以被打包进NR RAN Container扩展头中,通过Xn接口上的GTP-U隧道进行传输。这使得GTP-U不仅能承载用户数据,还能在特定接口上“捎带”一些控制面的上下文信息,提高了切换的效率。

2.3 扩展头的处理逻辑

规范中还定义了扩展头类型的最高两位比特的含义,这决定了接收节点如何处理一个它不认识的扩展头。

Bits 7 and 8 of the Next Extension Header Type define how the recipient shall handle unknown Extension Types…

| Bits 8 7 | 含义 | 处理方式 |

| :---: |---|---|

| 0 0 | 不要求理解,中间节点需转发 | 节点如果不认识,就忽略它,但必须把它连同整个G-PDU转发给下一跳。 |

| 0 1 | 不要求理解,中间节点需丢弃 | 中间节点如果不认识,就丢弃这个扩展头,但继续处理和转发G-PDU的其余部分。 |

| 1 0 | 端点必须理解,中间节点需转发 | 中间节点不需理解,直接转发。但最终的接收端如果还不认识,就必须报错。 |

| 1 1 | 所有接收方(包括中间节点)都必须理解 | 任何一个处理此包的节点,只要不认识这个扩展头,就必须报错。 |

这个精巧的设计,使得协议在未来增加新的扩展头时,可以明确指定其“重要性”等级。一些辅助性的新功能可以使用00类型,保证了对老设备的后向兼容;而一些涉及网络关键行为的颠覆性新功能,则可以使用11类型,确保只有升级过的设备才能处理,避免了因误解而导致的网络故障。

3. FAQ - 常见问题解答

Q1:GTP-U头的强制部分(8字节)和扩展头的主要区别和用途是什么?

A1:强制部分是每个GTP-U包的“基础身份证”,包含了最核心的路由和识别信息,如TEID(去往哪个隧道)、消息类型(是什么包)和长度(包有多大)。无论任何场景,这些信息都是必需的。扩展头则是“附加签证页”,用于处理特定场景下的临时或可选需求。例如,在切换场景中,需要携带PDCP序列号来实现无损转发,这时就会加上PDCP PDU Number扩展头。这种设计使得GTP-U协议既保持了核心的简洁高效,又具备了应对复杂场景的灵活性和可扩展性。

Q2:GTP-U头中的E、S、PN三个标志位,为什么需要一个总开关的作用?

A2:这三个标志位(E: Extension, S: Sequence, PN: N-PDU)控制着其后三个可选字段(Next Extension Header Type, Sequence Number, N-PDU Number)是否存在。规范规定,只要这三个标志位中任何一个被置为1,那么其后的整个4字节可选字段区域(Octets 9-12)就必须存在。接收端首先检查这三个标志位,如果全为0,就直接跳到第9字节开始作为T-PDU来解析;如果其中任何一个为1,它就知道需要先解析这4个字节的可选字段,然后再根据每个标志位的具体值(是否为1)来判断对应的字段是否有效。这种设计简化了解析逻辑,避免了头部长度的频繁变化。

Q3:扩展头的“链式结构”是如何工作的?它有什么好处?

A3:扩展头的链式结构是通过每个扩展头末尾的Next Extension Header Type字段实现的。解析器读完一个扩展头的内容后,会检查这个字段:如果它是一个非零值,就代表后面还跟着另一个扩展头,且这个值就是下一个扩展头的类型,解析器可以继续处理;如果值为零,则表示这是最后一个扩展头,其后就是真正的用户数据(T-PDU)。这种结构的好处是极大的灵活性,允许在一个GTP-U包中任意组合、任意数量的扩展头,而不需要预先固定它们的顺序或数量,使得协议扩展非常容易。

Q4:在小明的高铁切换场景中,PDCP PDU Number扩展头是如何保证他的视频不卡顿的?

A4:在切换时,旧基站(gNB-A)会将已接收但未发送给手机的数据,通过Xn隧道转发给新基站(gNB-B)。这些转发的数据包会带上PDCP PDU Number扩展头。这相当于给每个包都贴上了无线层的“序列号”。新基站gNB-B收到这些包后,就能精确知道它们的顺序。同时,gNB-B也开始直接从UPF接收新的数据。它能够利用这些序列号,将“转发来的旧数据”和“直接来的新数据”完美地整合在一起,按正确的顺序发送给小明的手机,并丢弃任何可能重复的数据。这个过程避免了数据的丢失和乱序,从而防止了视频在切换点的卡顿或花屏。

Q5:什么是“End Marker”(结束标记)?它为什么需要PDU Session Container这个扩展头?

A5:“End Marker”是一个特殊的GTP-U信令包,由UPF在切换时发送给旧的隧道端点(如gNB-A)。它的作用是明确告知旧路径:“该隧道的用户数据流已经结束,后续数据将从新路径走”。在5G中,一个PDU会话(由一个TEID标识的隧道)可能承载多个不同服务质量的QoS Flow(如视频、网页、后台下载)。有时切换只涉及其中一个或几个QoS Flow。因此,End Marker需要一种方式来指明是“哪个QoS Flow结束了”。PDU Session Container扩展头就扮演了这个角色,它内部可以携带QoS Flow Identifier (QFI),从而实现了对业务流级别的精细化信令控制,使得网络资源管理更加高效。