PDCP-LTE in a Real VoLTE Capture: Sequence Numbers, COUNT, and the MAC-I

The PDCP layer of the LTE attach and VoLTE walkthrough, followed on its own. One phone, UE 70, holds a PDCP entity for every radio bearer. This page reads two of them: SRB1, which carries RRC signaling and shows where integrity protection starts, and DRB 3, which carries call 1's voice. Two annotated diagrams caption every PDCP PDU of each.

๐Ÿ’ก Read the walkthrough and the diagram side by side: this page has two diagrams, one per bearer. SRB1's is linked above for Act One, the voice bearer's further down for Act Two. Open the one you are reading in a split-screen window, or open it in a new tab.

Where PDCP sits

PDCP (Packet Data Convergence Protocol, TS 36.323) is the top of the LTE radio stack: the last layer a packet passes through before RLC and MAC turn it into radio traffic. It appears in both planes. On a signaling bearer it carries RRC; on a data bearer it carries IP packets.

sequenceDiagram accTitle: LTE control-plane protocol stack, PDCP highlighted accDescr: The control-plane layers, top of stack to bottom. NAS spans the UE and the MME, passing through the eNB. RRC, PDCP, RLC, MAC, and PHY each span the UE and the eNB. PDCP, the subject of this article, is highlighted. participant UE participant eNB participant MME Note over UE,MME: NAS Note over UE,eNB: RRC Note over UE,eNB: PDCP Note over UE,eNB: RLC Note over UE,eNB: MAC Note over UE,eNB: PHY
The LTE control plane, with PDCP highlighted. On SRB1, PDCP carries RRC messages between the UE and the eNB, and NAS rides inside RRC to the MME.
sequenceDiagram accTitle: LTE user-plane protocol stack, PDCP highlighted accDescr: The user-plane layers. An IP packet carrying RTP spans the UE and the gateway. Below it, PDCP, RLC, MAC, and PHY span the UE and the eNB, and GTP-U over S1-U spans the eNB and the gateway. PDCP, the subject of this article, is highlighted. participant UE participant eNB participant GW as S-GW / P-GW Note over UE,GW: IP (RTP over UDP) Note over UE,eNB: PDCP Note over UE,eNB: RLC Note over UE,eNB: MAC Note over UE,eNB: PHY Note over eNB,GW: S1-U ยท GTP-U
The LTE user plane, with PDCP highlighted. On the voice bearer, PDCP carries RTP over UDP and IP between the UE and the eNB; GTP-U takes the packets on over S1-U.

The capture is the same srsRAN eNB log as the main walkthrough, in its re-tagged form. srsRAN marks every frame with UE identity 0, so Wireshark merges both phones' PDCP state; the copy used here sets each frame's identity to its C-RNTI and changes nothing else. Every COUNT on this page depends on that fix. Before the re-tag shows what the original file looks like, and Why the capture was re-tagged on the main page explains the fix.

What PDCP does

Everything above PDCP hands down whole messages and expects them to arrive once, in order, and unread by anyone else. PDCP does four jobs to make that so:

RLC, the layer below, also numbers its PDUs. The two counts are separate: RLC numbers the pieces it sends on the radio; PDCP numbers the packets it was given. The RLC page follows the RLC side of the same two bearers.

SN and COUNT

Five fields carry the walk:

FieldMeaning
SNSequence number, in the header of every PDU. 5 bits on an SRB; 7 or 12 bits on a data bearer, chosen when the bearer is created.
COUNTA 32-bit counter: the HFN (Hyper Frame Number) in the high bits, the SN in the low bits (TS 36.323 ยง6.3.5). Only the SN travels. Each end keeps the HFN and adds 1 to it every time the SN wraps back to 0.
MAC-IMessage Authentication Code for Integrity: a 4-byte tag after the payload. Present on every SRB PDU, absent on data bearers.
D/COne bit on a data bearer that marks a data PDU (1) or a PDCP control PDU (0), such as a status report. SRBs have no such bit.
BEARER, DIRECTIONTwo more inputs to the security algorithms: the radio bearer identity minus 1, and uplink (0) or downlink (1).

Why keep a COUNT at all, when the SN is on the wire? The SN repeats. A 5-bit SN returns to 0 after 32 PDUs, and the security algorithms must never see the same input twice under one key. COUNT doesn't repeat until all 32 bits are used, so it is the number that ciphering and integrity consume. The HFN is the part each end keeps in step without sending it.

Each PDCP entity has its own COUNT per direction, starting at 0 when the bearer is created (TS 36.323 ยง7.1). The SRB header is a single byte:

packet accTitle: PDCP-LTE Data PDU header for a signaling radio bearer accDescr: Eight bits. Three reserved bits, then a five-bit sequence number. 0-2: "R R R" 3-7: "SN (5 bits)"
PDCP Data PDU header on an SRB (TS 36.323 ยง6.2.2). Three reserved bits and a 5-bit SN. The RRC message follows, then the 4-byte MAC-I.
packet accTitle: PDCP-LTE COUNT on a 5-bit sequence-number bearer accDescr: Thirty-two bits. The high twenty-seven bits are the hyper frame number, the low five bits the sequence number. 0-26: "HFN (27 bits)" 27-31: "SN (5 bits)"
COUNT on an SRB: a 27-bit HFN above the 5-bit SN. With the HFN at 0, COUNT equals the SN.

The voice bearer uses the 12-bit format, two bytes:

packet accTitle: PDCP-LTE Data PDU header for a data radio bearer with a 12-bit sequence number accDescr: Sixteen bits. One bit D/C, three reserved bits, then a twelve-bit sequence number. 0: "D/C" 1-3: "R R R" 4-15: "SN (12 bits)"
PDCP Data PDU header on a data bearer with a 12-bit SN (TS 36.323 ยง6.2.3). The D/C bit, three reserved bits, and the SN. The IP packet follows, with no MAC-I.
packet accTitle: PDCP-LTE COUNT on a 12-bit sequence-number bearer accDescr: Thirty-two bits. The high twenty bits are the hyper frame number, the low twelve bits the sequence number. 0-19: "HFN (20 bits)" 20-31: "SN (12 bits)"
COUNT on a 12-bit-SN bearer: a 20-bit HFN above the 12-bit SN.

What is signed and what is ciphered

LTE AS security has two algorithms, chosen by the RRC Security Mode Command. Here both are picked in frame 16: EIA2 for integrity and EEA0 for ciphering.

flowchart LR accTitle: Integrity protection and ciphering of an SRB PDU accDescr: The PDCP header and the RRC message feed 128-EIA2 together with K RRCint, COUNT, BEARER, and DIRECTION. EIA2 outputs the 32-bit MAC-I. The RRC message and the MAC-I are then XORed with the EEA keystream. The PDU on the air is the clear header followed by the ciphered message and ciphered MAC-I. IN["PDCP header<br/>and RRC message"] --> EIA["128-EIA2<br/>K RRCint, COUNT,<br/>BEARER, DIRECTION"] EIA --> MAC["MAC-I<br/>32 bits"] MSG["RRC message"] --> XOR(("XOR with<br/>EEA keystream")) MAC --> XOR XOR --> AIR["On the air:<br/>header in clear,<br/>ciphered message and MAC-I"]
How an SRB1 PDU is built once AS security is on. EIA2 signs the header and the RRC message, the tag is appended, and then the RRC message and the tag are ciphered. EEA0's keystream is all zeros, so in this capture the ciphered bytes equal the plaintext.

EEA0, the null algorithm, produces a keystream of zeros. XOR with zeros changes nothing, so every "ciphered" byte in this capture is the plaintext. That is why Wireshark decodes the RRC on SRB1 and the RTP on the voice bearer with no keys. EIA2 is not null: the tags from frame 16 on are real integrity tags, but nobody can check them without K_RRCint, which the capture doesn't contain.

Two bearers, two PDCP entities

SRB1 and DRB 3 share one phone and one radio link, and nothing else at PDCP:

SRB1DRB 3 (call 1 voice)
Session keypdcp-bearer::70|1|1pdcp-bearer::70|2|3
PlaneSignalingUser
Created byRRC Connection Setup, frame 3RRC Connection Reconfiguration, frame 846
Removedneverframe 1146
PDUs in the diagram39, frames 4โ€“328872, frames 985โ€“1140
SN5-bit; UL 0โ€“19, DL 0โ€“1812-bit; UL 0โ€“34, DL 0โ€“36
Header1 byte2 bytes
MAC-Ion all 39; zero until frame 16none
BEARER input02
CarriesRRC, with NAS inside some messagesIP, UDP, RTP, AMR-WB

๐Ÿ’ก Where these diagrams come from. The session keys in that table are how VisualEther, the tool that decoded this capture and drew the diagrams, labels each PDCP entity: C-RNTI, plane (1 signaling, 2 user), and bearer number.

Within each bearer there are two counters, one per direction: the UE's transmitting entity numbers the uplink; the eNB's numbers the downlink. So these two diagrams hold four independent counts, and an SN means something only on its own bearer and direction.

Act One โ€” SRB1, the signaling bearer

SRB1 carries every RRC message after setup. Its 39 PDUs fall into three groups: the attach (frames 4โ€“14) before any radio security, the Security Mode Command and the capability and bearer setup that follow (frames 16โ€“34), and twelve reconfigurations for six calls (frames 846โ€“3288).

Before security: a zero MAC-I

Frame 4 โ€” the first PDU. Uplink SN=0, carrying RRC Connection Setup Complete with the NAS Attach Request inside. The header byte is 0x00: three reserved bits and SN 0. At the end sits a MAC-I of 0x00000000. AS security doesn't exist yet, but an SRB PDU always has the field, padded with zeros until integrity protection starts (TS 36.323 ยง6.3.4). Wireshark marks it [Matches calculated result]: with no integrity configured, zeros are what it expects.

Frame 6 โ€” the downlink's own SN 0. The eNB's first PDU, 1.9 ms later, carries the NAS Identity Request. It is also SN 0. It isn't a repeat of frame 4; the downlink entity has started its own count.

Frames 13 and 14 โ€” a security procedure that doesn't touch PDCP. These carry the NAS Security Mode Command and Complete. They select EEA0 and EIA2 for NAS, the link between the UE and the MME. The PDCP MAC-I stays zero. NAS and the radio each run their own security, with their own keys and counters; the NAS page follows the NAS side. Seven PDUs, frames 4 to 14, carry a zero tag.

Frame 16 โ€” integrity starts

Frame 16 is the AS Security Mode Command. Downlink SN=3, carrying cipheringAlgorithm: eea0 and integrityProtAlgorithm: eia2. The eNB signs the command itself with the new K_RRCint, so its MAC-I, 0x4efe0942, is the first non-zero tag on SRB1 (TS 36.331 ยง5.3.4.3, TS 33.401 ยง7.2.4.5). The command isn't ciphered: ciphering starts only after it.

Wireshark marks the tag MAC-I Digest wrong - calculated 00000000. That is its own limitation, not an error on the link. It applies the new settings only to PDUs after this one, so it expected zeros, and it couldn't check an EIA2 tag anyway without the key. The RRC page reads the command's contents.

Frame 17 โ€” the first COUNT. Uplink SN=4, the Security Mode Complete, 29 ms later. It is signed (MAC-I 0xc1047431) and, by rule, not ciphered. From this PDU on, Wireshark prints the inputs EIA2 used:

[UE Security (ciphering=EEA0 (NULL), integrity=EIA2 (AES))]
    [Configuration frame: 16]
    [Ciphering Algorithm: EEA0 (NULL) (0)]
    [Integrity Algorithm: EIA2 (AES) (2)]
    [BEARER: 0]
    [DIRECTION: Uplink (0)]
    [COUNT: 4]
000. .... = Reserved: 0
...0 0100 = Seq Num: 4

COUNT: 4 and Seq Num: 4 are the same number because the HFN is 0. BEARER: 0 is SRB1's identity minus 1. "Configuration frame: 16" names the command that set the algorithms; every later SRB1 PDU, and every voice PDU in Act Two, points back to it.

Frame 19 โ€” ciphering starts, and nothing changes. Downlink SN=4, the UE Capability Enquiry, is the first downlink PDU after the command, so it is ciphered, with EEA0. The RRC message and the tag go out exactly as they would unciphered. With EEA1, EEA2, or EEA3, everything after the header byte would be unreadable without K_RRCenc.

Frame 22 โ€” one SN for 2,017 bytes. Uplink SN=5, UE Capability Information, is a 2,017-byte PDCP PDU. RLC carried it in three segments, RLC SN 5 to 7, across frames 20 to 22. PDCP numbers it once. How many pieces RLC needed isn't visible from here.

Same message, different tag

Frame 24 is the first RRC Connection Reconfiguration. It adds SRB2 and DRB 1, each with a PDCP entity and counters of its own, starting at 0. The UE's answer, frame 27, shows the result: the same transport block carries SRB1's uplink SN=6 and SRB2's uplink SN=0: two SNs from two entities, side by side and unrelated.

The Reconfiguration Complete PDUs make the point of MAC-I concrete. Each is 7 bytes:

FrameSNHeaderRRC messageMAC-I
2760610 00dc1bab6b
3470710 00cd1f8525
114890910 0032646424
2928171110 00d740352b

The RRC message is two bytes, 10 00: Reconfiguration Complete with transaction identifier 0, the same every time. UE 70 sends it 14 times on SRB1 and gets 14 different tags, because COUNT is different each time. If an attacker recorded frame 27 and replayed it later, the receiver would check it against a newer COUNT, and the tag would fail. The SN in the header byte is in the low five bits: 0x11 is SN 17.

Six calls, two SNs each

Frames 846 to 3288. After frame 34, SRB1 is silent for 23 seconds while IMS registration runs on DRB 2. The entity keeps its state, and frame 846 continues at downlink SN=7, COUNT 7. That reconfiguration adds DRB 3, the voice bearer of Act Two, and frame 1146 releases it.

From there the pattern repeats: each call adds a voice DRB and later releases it, and each add and each release costs one downlink SN and one uplink SN. Uplink NAS answers go on SRB2, so SRB1's uplink carries only Reconfiguration Completes. The RRC page reads the reconfigurations.

Frame 3288 โ€” the last PDU. Uplink SN=19, 102 s into the capture. The totals are 20 uplink PDUs (SN 0 to 19) and 19 downlink (SN 0 to 18), with no gap and no repeat. A 5-bit SN wraps after 32 PDUs. Neither direction got there, so the HFN stayed 0 and COUNT equals SN on every PDU.

Act Two โ€” DRB 3, the voice bearer

Call 1's voice bearer exists from frame 846 to frame 1146. Its PDCP entity handles 72 PDUs, frames 985 to 1140, and its diagram shows all of them.

Frame 846 configures this entity in three lines of pdcp-Config:

SettingValueEffect
pdcp-SN-Size (under rlc-UM)len12bits2-byte header, SN 0 to 4,095
discardTimerms100the UE drops a packet not sent within 100 ms
headerCompressionnotUsedno ROHC: IP, UDP, and RTP headers travel in full

A UM bearer may use a 7-bit SN and a 1-byte header instead (TS 36.323 ยง6.2.4). This one doesn't.

The first PDUs

Frame 985 โ€” the first voice PDU. Uplink SN=0, COUNT 0. The header reads 1... .... = PDU Type: Data PDU, .000 .... = Reserved, then the 12-bit SN. After it comes a 73-byte IP packet and nothing else: the PDU is 75 bytes. There is no MAC-I, because LTE doesn't integrity-protect user-plane traffic between the UE and the eNB (TS 33.401 ยง5.1.4.1).

Wireshark's UE Security line still says integrity=EIA2, with "Configuration frame: 16". That is the UE's security configuration, shared by all its bearers. On a data bearer only the cipher applies, and EEA0 leaves the packet as it is: RTP sequence 1 from 192.168.101.2 to the media relay at 172.22.0.16, AMR-WB at 12.65 kbit/s. The SIP page explains why the voice goes to a relay and how the codec was chosen. BEARER is 2 here: DRB 3 minus 1.

Frame 994 โ€” what ROHC would remove. Of each 73-byte packet, 40 bytes are IPv4, UDP, and RTP headers; the AMR-WB payload is 33. During silence the packet shrinks to 47 bytes, still with 40 bytes of header. Without header compression, every packet on this bearer carries more bytes of header than of voice.

Frame 1003 โ€” the downlink's own SN 0. The relay's stream from UE 71 starts at downlink SN=0, COUNT 0. UE 71 encodes at 23.85 kbit/s, so its speech PDUs are 103 bytes against UE 70's 75.

PDCP numbers packets, not RTP sequence numbers. Uplink SN 0 carries RTP 1, because UE 70's stream starts at 1; downlink SN 0 carries RTP 0, because UE 71's starts at 0. The offset stays fixed for the call because every RTP packet becomes exactly one PDCP SDU.

Silence, discard, and sharing a transport block

Frame 1004 โ€” silence. Uplink SN=7, RTP 8, is AMR-WB SID_FIRST, the start of silence suppression (TS 26.193). The PDU drops to 49 bytes, and PDCP spends one SN on it like any other packet. From frame 1024 each direction sends one 49-byte SID_UPDATE every 160 ms, and one SN with each. The RLC page times the pattern.

discardTimer โ€” evidence by absence. The UE starts a 100 ms timer for each packet as it enters PDCP, and drops the packet if it hasn't gone out when the timer expires (TS 36.323 ยง5.4). A voice frame that late is useless to the listener. The packet already has its SN, so a discard would leave a gap in the uplink sequence. There is none: SN 0 to 34 all arrive, in order.

Frame 1024 โ€” two entities in one transport block. The same MAC PDU carries voice SN=9, COUNT 9, and DRB 1's uplink SN 150 and 151, COUNT 150 and 151. The phone and the direction are the same, but the counts differ widely, because DRB 1, the internet bearer, has been counting since frame 86.

Frame 1121 โ€” two PDCP PDUs in one RLC PDU. Downlink SN=30 (speech) and SN=31 (SID_FIRST) travel in a single RLC UM PDU. PDCP gives each packet its own SN and COUNT however RLC carries them. From here the downlink RLC SN runs one behind the PDCP SN.

Frame 1140 โ€” the end. Uplink SN=34. In 4.4 s the entity sent 35 uplink PDUs (SN 0 to 34) and received 37 downlink (SN 0 to 36), with no gap and no repeat. A 12-bit SN wraps after 4,096 PDUs, about 82 s of nonstop speech at one packet per 20 ms, so the HFN stayed 0. Frame 1146 releases DRB 3, and the entity's COUNTs go with it. Call 2's bearer, DRB 4, starts again from SN 0 in frame 1311.

The highest COUNT anywhere in the re-tagged capture is 334, on UE 70's DRB 1 downlink. No counter comes near a wrap, so in this capture COUNT always equals SN. That makes it a clean test case: any other COUNT means the tool is tracking the wrong entity.

Before the re-tag

srsRAN writes UE identity 0 on every frame. Wireshark keeps one set of PDCP state per UE identity and bearer, so the original file gives it one "UE 0" with one SRB1 shared by both phones, and one DRB 3 shared by both phones' call-1 voice bearers. Read with the same decode recipe, the original file shows what that does to the two entities on this page:

FramePDUOriginal fileRe-tagged
17UE 70, SRB1 UL SN=4COUNT 4, configuration frame 16the same
304UE 71, SRB1 UL SN=0COUNT 32, configuration frame 16no COUNT: UE 71 has no AS security yet
846UE 70, SRB1 DL SN=7no COUNT, no PDCP sequence analysis; RLC: "AM Frame retransmitted โ€ฆ most likely in response to NACK"COUNT 7
1148UE 70, SRB1 UL SN=9COUNT 41, configuration frame 319, previous frame 514COUNT 9, configuration frame 16, previous frame 847
3288UE 70, SRB1 UL SN=19COUNT 51COUNT 19
1003UE 70, DRB 3 DL SN=0no COUNT; RLC: "UM SN (0) repeated for Downlink for UE 0 (DRB-3)"COUNT 0
1124UE 70, DRB 3 UL SN=30no COUNT; RLC flags SN repeatedCOUNT 30

Three things went wrong.

The PDCP-level "SN repeated" warning, the one the main page cites at frame 854, never appears on these two bearers. In the original file it fires on 21 PDUs in 17 frames, 802 to 1499, all on UE 70's DRB 2 downlink. Here the merge is quieter: wrong COUNTs and missing ones, with no PDCP warning to point at them.

With EEA0 the wrong COUNTs do no visible harm: a zero keystream is zero for every COUNT, so the payloads still decode. With a real cipher, Wireshark would derive the keystream from the wrong COUNT and decipher garbage. The re-tagged file has no PDCP sequence warning on either bearer.

Takeaways

  1. The SN travels; COUNT is what the algorithms use. COUNT is the HFN above the SN, and the HFN is state each end keeps. Here no counter wrapped, so every COUNT equals its SN.
  2. Every entity counts on its own. SRB1, SRB2, DRB 1, and each voice DRB have separate counters, one per direction, all starting at 0. Frames 27 and 1024 show two entities' numbers side by side in one transport block.
  3. Integrity starts with the Security Mode Command itself. Frames 4 to 14 carry a zero MAC-I; frame 16, the command, carries the first real one. Ciphering starts after it.
  4. A tag changes when COUNT changes. The same two-byte Reconfiguration Complete went out 14 times with 14 different MAC-I values. That is replay protection.
  5. Ciphered with EEA0 means readable. The null cipher's keystream is zeros, so the RRC and RTP decode without keys. Data bearers carry no MAC-I at all.
  6. Check whose state the tool is tracking. One constant UE identity gave UE 70 COUNTs 32 too high and wrote a third of its PDUs off as repeats.

Where this sits in the stack