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.
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:
- It numbers. Each SDU (Service Data Unit: one packet handed down by RRC or IP) gets the next sequence number.
- It protects. AS (Access Stratum) security lives here: integrity protection on signaling bearers, ciphering on all bearers. Both use the sequence number.
- It reorders and drops duplicates on the receiving side, using the same number.
- It compresses headers and discards stale packets on data bearers, if configured.
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:
| Field | Meaning |
|---|---|
SN | Sequence 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. |
COUNT | A 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-I | Message Authentication Code for Integrity: a 4-byte tag after the payload. Present on every SRB PDU, absent on data bearers. |
D/C | One 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, DIRECTION | Two 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:
The voice bearer uses the 12-bit format, two bytes:
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.
- Integrity (EIA2), signaling bearers only. 128-EIA2 is AES-CMAC (TS 33.401 Annex B.2). It takes the key
K_RRCint,COUNT,BEARER,DIRECTION, and the message, and returns the 32-bitMAC-I. The message it covers is the PDCP header plus the RRC message (TS 36.323 ยง5.7). Change one bit of either, or replay an old PDU under a newer COUNT, and the tag no longer matches. - Ciphering (EEA0 here), all bearers. The algorithm turns the key, COUNT, BEARER, and DIRECTION into a keystream and XORs it with the data. On an SRB it ciphers the RRC message and the
MAC-I; on a data bearer, the IP packet (TS 36.323 ยง5.6). The header is never ciphered: the receiver needs the SN to rebuild COUNT before it can decipher.
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:
| SRB1 | DRB 3 (call 1 voice) | |
|---|---|---|
| Session key | pdcp-bearer::70|1|1 | pdcp-bearer::70|2|3 |
| Plane | Signaling | User |
| Created by | RRC Connection Setup, frame 3 | RRC Connection Reconfiguration, frame 846 |
| Removed | never | frame 1146 |
| PDUs in the diagram | 39, frames 4โ3288 | 72, frames 985โ1140 |
| SN | 5-bit; UL 0โ19, DL 0โ18 | 12-bit; UL 0โ34, DL 0โ36 |
| Header | 1 byte | 2 bytes |
MAC-I | on all 39; zero until frame 16 | none |
BEARER input | 0 | 2 |
| Carries | RRC, with NAS inside some messages | IP, 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:
| Frame | SN | Header | RRC message | MAC-I |
|---|---|---|---|---|
| 27 | 6 | 06 | 10 00 | dc1bab6b |
| 34 | 7 | 07 | 10 00 | cd1f8525 |
| 1148 | 9 | 09 | 10 00 | 32646424 |
| 2928 | 17 | 11 | 10 00 | d740352b |
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:
| Setting | Value | Effect |
|---|---|---|
pdcp-SN-Size (under rlc-UM) | len12bits | 2-byte header, SN 0 to 4,095 |
discardTimer | ms100 | the UE drops a packet not sent within 100 ms |
headerCompression | notUsed | no 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:
| Frame | PDU | Original file | Re-tagged |
|---|---|---|---|
| 17 | UE 70, SRB1 UL SN=4 | COUNT 4, configuration frame 16 | the same |
| 304 | UE 71, SRB1 UL SN=0 | COUNT 32, configuration frame 16 | no COUNT: UE 71 has no AS security yet |
| 846 | UE 70, SRB1 DL SN=7 | no COUNT, no PDCP sequence analysis; RLC: "AM Frame retransmitted โฆ most likely in response to NACK" | COUNT 7 |
| 1148 | UE 70, SRB1 UL SN=9 | COUNT 41, configuration frame 319, previous frame 514 | COUNT 9, configuration frame 16, previous frame 847 |
| 3288 | UE 70, SRB1 UL SN=19 | COUNT 51 | COUNT 19 |
| 1003 | UE 70, DRB 3 DL SN=0 | no COUNT; RLC: "UM SN (0) repeated for Downlink for UE 0 (DRB-3)" | COUNT 0 |
| 1124 | UE 70, DRB 3 UL SN=30 | no COUNT; RLC flags SN repeated | COUNT 30 |
Three things went wrong.
- A phantom wrap. The merged uplink entity saw UE 70 reach SN 7 (frame 34), then UE 71 start at SN 0 (frame 304). A lower SN after a higher one looks like a wrap, so Wireshark raised the HFN to 1. UE 71's first PDU got COUNT 32, and UE 70's later uplink PDUs got COUNT = SN + 32: 11 of them, frames 1148 to 3288.
- One phone's security applied to the other. Frame 304 is UE 71's Setup Complete, sent before UE 71 had any AS security, yet the original file credits it to UE 70's Security Mode Command in frame 16. After UE 71's own command in frame 319, UE 70's PDUs point to frame 319 instead.
- PDUs written off as repeats. When the RLC layer underneath decides a PDU is a retransmission, Wireshark skips PDCP's sequence analysis and prints no COUNT. Every downlink SRB1 PDU of UE 70 from frame 846 on (12 PDUs) is flagged this way. Uplink frame 847, where RLC reports SN 9 missing instead, gets no COUNT either: 13 of 39 in all. On the voice bearer it is 35 of 72: downlink SN 0 to 29 (frames 1003 to 1119) and uplink SN 30 to 34 (frames 1124 to 1140).
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
- 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.
- 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.
- 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. - A tag changes when COUNT changes. The same two-byte Reconfiguration Complete went out 14 times with 14 different
MAC-Ivalues. That is replay protection. - 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-Iat all. - 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
- An LTE Attach and a VoLTE Call on the Air Interface: the full walkthrough this page is a slice of, with every layer on one timeline.
- RLC-LTE: Acknowledged and Unacknowledged Mode: the layer below, on DRB 2 and this page's voice bearer, including the one real retransmission in the capture.
- LTE-RRC: One Connection, Fourteen Reconfigurations: the messages SRB1 carries, and the
pdcp-Configin each new DRB. - NAS-EPS: Attach, Default Bearers, and Six Voice Bearers: the separate NAS security context, with its own Security Mode procedure and its own counter.
- SIP: IMS Registration and the VoLTE Call: what the RTP on the voice bearer and the ESP on DRB 2 carry.
- PDCP-NR in a Real 5G Capture: the same layer in 5G, with a real NEA2 cipher and 12- and 18-bit sequence numbers.