PDCP-NR in a Real 5G Capture

One layer of the 5G NR attach walkthrough, followed on its own: every PDCP PDU on both of the connection's bearers, and the sequence numbers that tie them together.

๐Ÿ’ก Read the walkthrough and the diagram side by side. This page carries two diagrams โ€” one per bearer. The signaling bearer's is linked above and walked in Act One; the data bearer's is linked further down, where Act Two begins. Open whichever act you are reading in a split-screen window so the captions stay in view. On macOS, prefer Chrome or Firefox โ€” Safari has no in-browser split screen.

Where PDCP sits

PDCP appears in both planes of the 5G radio stack, and this page walks one bearer in each โ€” so it gets both pictures. The layer is the same in either; what changes is what sits above it and where the traffic goes once it leaves the gNB.

Control plane โ€” the signaling bearer

Under RRC, carrying the signaling that sets the connection up. This is the stack Act One walks on SRB 1.

sequenceDiagram accTitle: 5G NR control-plane protocol stack, PDCP highlighted accDescr: The control-plane layers, top of stack to bottom. NAS spans the UE and the AMF, passing transparently through the gNB. RRC, PDCP, RLC, MAC and PHY each span the UE and the gNB. PDCP, the subject of this article, is highlighted. participant UE participant gNB participant AMF Note over UE,AMF: NAS Note over UE,gNB: RRC Note over UE,gNB: PDCP Note over UE,gNB: RLC Note over UE,gNB: MAC Note over UE,gNB: PHY
The 5G NR control-plane stack, with PDCP highlighted. PDCP sits between RRC above and RLC below, and talks to its peer PDCP entity in the gNB. NAS passes transparently through the gNB to the AMF.

User plane โ€” the data bearer

Under SDAP, instead of RRC, carrying user traffic that continues past the gNB to the UPF. This is the stack Act Two walks on DRB 1.

sequenceDiagram accTitle: 5G NR user-plane protocol stack, PDCP highlighted accDescr: The user-plane layers, top of stack to bottom. SDAP, PDCP, RLC, MAC and PHY each span the UE and the gNB. Below them, the N3 interface, GTP-U carrying the QoS Flow Identifier, spans the gNB and the UPF. PDCP, the subject of this article, is highlighted. participant UE participant gNB participant UPF Note over UE,gNB: SDAP Note over UE,gNB: PDCP Note over UE,gNB: RLC Note over UE,gNB: MAC Note over UE,gNB: PHY Note over gNB,UPF: N3 ยท GTP-U (QFI)
The 5G NR user-plane stack, with PDCP highlighted. Here PDCP sits under SDAP rather than RRC, still above RLC. Below the radio stack, an N3 box (GTP-U carrying the QFI) spans the gNB and the UPF โ€” where the QoS flow continues into the core.

Same layer, two entities. The difference between those two stacks is exactly the difference the rest of this page is about: a 12-bit sequence number and a mandatory integrity tag on one, an 18-bit sequence number and no integrity tag at all on the other.

What PDCP does

PDCP โ€” Packet Data Convergence Protocol (TS 38.323) is the last layer a packet passes through before it becomes radio traffic, and the first one it passes through coming back. It is where the radio link stops being a transport problem and starts being a security problem.

Everything above PDCP hands down whole messages and assumes they will arrive, once, in order, and unread by anyone else. PDCP is what makes those three assumptions true:

That last point is the reason PDCP sits above RLC rather than beside it. The two differ in scope, not in diligence: RLC makes delivery reliable across one radio link, retransmitting until the far end confirms; PDCP secures the message and puts it back in order above whatever the link below had to do to move it. Their sequence numbers count different things.

Six fields carry the whole walk, and they are worth learning before it starts:

FieldMeaning
SNSequence number. It counts SDUs handed to the layer โ€” not bytes, not transmissions. 12 bits on a signaling bearer; 12 or 18 bits on a data bearer, chosen by configuration.
COUNTThe 32-bit value the cipher actually consumes: an HFN (Hyper Frame Number) concatenated with the SN (TS 38.323). Only the SN travels; the HFN is state each end keeps and increments when the SN wraps.
D/CThe Data/Control bit, one bit. It exists only on the user plane โ€” it distinguishes a PDCP Data PDU from a PDCP Control PDU (a status report or ROHC feedback). Signaling bearers have no such bit, because they never carry a Control PDU.
MAC-IMessage Authentication Code for Integrity: a 32-bit tag in the trailer, after the payload. Always present on a signaling bearer; present on a data bearer only if integrity protection was configured.
BEARER / DIRECTIONTwo more cipher inputs alongside COUNT and the key: which bearer, and which way. Together they guarantee that two PDUs never share a keystream.

Those fields do not share one layout. TS 38.323 ยง6.2 defines a separate PDU format per bearer type and per sequence-number width, and the two this capture uses are the two drawn below.

The signaling bearer's header is the smallest thing PDCP defines โ€” four reserved bits, twelve bits of sequence number, and nothing else (ยง6.2.2.1). There is no D/C bit at all, because an SRB has no Control PDU to tell it apart from a Data PDU.

packet accTitle: PDCP-NR Data PDU header format for a signaling radio bearer accDescr: Sixteen bits, two octets. Four reserved bits, then twelve bits of sequence number. There is no D/C bit in this format. 0-3: "R (4 bits)" 4-15: "SN (12 bits)"
PDCP Data PDU header on SRB 1 โ€” two octets. Four reserved bits, then a 12-bit sequence number. No D/C bit exists in this format. The SDU follows, and the 4-byte MAC-I trailer follows that.

Frame 4 reads exactly that shape: 0000 .... = Reserved: 0, then .... 0000 0000 0000 = Seq Num: 0.

The data bearer runs an 18-bit sequence number, which needs a third octet and spends the very first bit on D/C (ยง6.2.2.3):

packet accTitle: PDCP-NR Data PDU header format for a data radio bearer with an 18-bit sequence number accDescr: Twenty-four bits, three octets. One bit D/C, then five reserved bits, then eighteen bits of sequence number. 0: "D/C" 1-5: "R (5 bits)" 6-23: "SN (18 bits)"
PDCP Data PDU header on DRB 1 โ€” three octets. The D/C bit marks it a Data PDU; five reserved bits follow, then an 18-bit sequence number. Any MAC-I trailer is optional here and absent in this capture.

Frame 41 reads 1... .... = PDU Type: Data PDU and then .000 00.. = Reserved: 0x00 โ€” the D/C bit set to Data, then those five reserved bits. A DRB configured for a 12-bit sequence number instead (ยง6.2.2.2) keeps the D/C bit but drops back to two octets, leaving three reserved bits where the SRB has four; frame 38 selects len18bits on this bearer, so that third format never appears in the trace.

One format remains, and this capture never produces it. A PDCP Control PDU carries no SDU at all โ€” it is PDCP talking to its own peer rather than to the layer above (ยง6.2.3.1). D/C is zero, and a 3-bit PDU type selects between a status report (000) and interspersed ROHC feedback (001). The status report names an FMC (First Missing COUNT) and then a bitmap covering what came after it:

packet accTitle: PDCP-NR Control PDU format for a status report accDescr: One bit D/C set to zero, three bits of PDU type, four reserved bits, then a thirty-two bit first missing COUNT field, then a variable length bitmap. 0: "D/C" 1-3: "PDU Type" 4-7: "R (4 bits)" 8-39: "FMC (32 bits)" 40-47: "Bitmap (variable)"
PDCP Control PDU carrying a status report, the format this capture never produces. D/C is zero, PDU type selects the report, and FMC names the first missing COUNT. The bitmap that follows runs to the end of the PDU, one bit per COUNT above FMC.

That format is why the D/C bit exists, and why only the user plane has one. Act Two comes back to it: frame 38 arms this bearer to send status reports, and not one is ever sent.

One thing to note: the PDCP header is never ciphered. Ciphering starts immediately after it and covers the payload and the MAC-I trailer (TS 38.323 ยง5.8). A gNB has to be able to route, reorder, and de-duplicate PDUs before it decrypts them, so the sequence number stays in the clear on every frame โ€” even the frames in this trace that nobody has the keys for.

This page is about the frame-by-frame mechanics: the number, the COUNT, the tag, and the boundary. The security story โ€” the three encryption levels in this capture, the key hierarchy, and how the trace was opened in the first place โ€” belongs to Decrypting a 5G NR radio capture, and this walk links back to it wherever the two touch.

Two bearers, two PDCP entities

One UE. One radio connection with two completely independent PDCP entities.

The trace carries an SRB (Signaling Radio Bearer) for control messages and a DRB (Data Radio Bearer) for user traffic, and both are numbered 1. They are not two halves of one story. They have different header formats, different keys, and โ€” the point of this page โ€” separate sequence-number and COUNT spaces:

SRB 1DRB 1
Sessionpdcp-bearer/timeout/00005pdcp-bearer/timeout/00012
Plane1 (Signalling)2 (User)
Messages2632
Frames4โ€“14641โ€“114
Sequence-number width12-bit18-bit
D/C bitabsentpresent, always Data PDU
MAC-Ipresent on all 26absent on all 32
Ciphering key95F23667A60D91689B31772783E6FDDD4CB12A7FB40AE866AE59FC9529E0BC5B
DiagramAct One, belowAct Two, below

๐Ÿ’ก Where these diagrams come from. The Session names in that table are how VisualEther โ€” the tool that decoded this capture and generated the diagrams here โ€” labels each per-bearer slice when it splits the trace into sessions.

That is why this page carries two diagrams instead of one timeline. A sequence number means nothing across the boundary, and neither does a COUNT: SRB 1's SN=5 and DRB 1's SN=5 are unrelated packets that were ciphered with different keys.

There is a second, finer split inside each bearer. Each end runs its own PDCP entity and keeps its own TX_NEXT for what it transmits (TS 38.323 ยง7.1), so the uplink SN=0 and the downlink SN=0 on the same bearer are also unrelated โ€” they were minted by different entities. Four independent counters open these two diagrams.

Two facts are true of every PDU on both diagrams, and they are worth stating once rather than repeating them on both:

Act One โ€” SRB 1, the signaling bearer

26 messages, frames 4 to 146: 12 uplink PDUs and 14 downlink PDUs, 12-bit sequence numbers, a four-byte MAC-I on every one. This is the diagram linked at the top of the page. It is the bearer that teaches the mechanism, because it is the only one where you can watch the security switch on.

Frame 4 โ€” the whole SRB header format in two bytes. The first PDCP PDU of the capture reads 0000 .... = Reserved: 0 and then .... 0000 0000 0000 = Seq Num: 0. Four reserved bits, twelve bits of sequence number, and that is the entire header. There is no D/C bit here โ€” the signaling PDU format has no way to express a Control PDU (TS 38.323 ยง6.2.2.1).

Behind the SDU sits the four-byte MAC-I trailer, and Wireshark reads it as MAC: 0x00000000 [Matches calculated result]. Access-Stratum security has not been activated yet, and TS 38.323 ยง6.3.4 says the field is still present on an SRB and padded with zeros until it is. Eight PDUs in this session carry a zeroed MAC-I: frames 4, 7, 9, 11, 12, 14, 15, and 133.

Frame 7 โ€” the downlink has its own counter. The gNB's first PDU is also Seq Num: 0. Not a repeat of frame 4; the other direction's entity opening its own count.

Frame 12 โ€” frame carrying the encrypted NAS packet. Uplink SN=2. At the PDCP layer, this PDU is wide open: no ciphering yet, MAC-I all zeros. At the NAS layer, it is completely opaque โ€” security header type Integrity protected and ciphered with new 5GS security context (4), message authentication code 0x97f62856, and then Encrypted data.

An unciphered PDCP PDU whose payload is still unreadable. The NAS layer runs its own security context, negotiated with the core rather than the gNB, and it started well before this one. The decryption companion has the full account of the split; the thing to take from this frame is that the two layers are genuinely independent, and you can see it in a single packet.

Frames 17 to 23 โ€” where security actually starts

Frame 17 is the RRC Security Mode Command. Downlink SN=3, carrying a securityModeCommand that selects cipheringAlgorithm: nea2 (2) and integrityProtAlgorithm: nia2 (2) โ€” AES for both. (The RRC companion reads the message itself; this page is about what PDCP then does with it.) Two things change here, and they change at different moments.

The MAC-I is suddenly real: 0x5cfaa560, not zeros. Integrity protection applies to this very message, with the new key.

But the message is still readable. Ciphering is not applied to it. TS 38.331 ยง5.3.4.3 draws the line exactly there โ€” integrity from this message onward, ciphering only after the procedure completes โ€” and the trace shows it plainly: the RRC decodes in full and Wireshark's Deciphered Data field is absent, because nothing had to be decrypted.

Wireshark does flag MAC-I Digest wrong - calculated 00000000 but found 5cfaa560 here, and that is a tooling artifact rather than a protocol error: the dissector only learns the algorithms from this frame, so it validated the digest before it had them. Every subsequent PDU of this connection โ€” on both bearers, including all 32 on the data bearer that does not exist yet โ€” names this frame as its Configuration frame: 17.

Frame 18 is the Security Mode Complete, and the mirror image. Uplink SN=4, MAC-I 0x944c9d98 โ€” a real digest โ€” and again no Deciphered Data. Integrity yes, ciphering not yet.

It is also the first frame where Wireshark prints the complete set of inputs the cipher will use for the rest of the connection:

๐Ÿ”ผ [00009] Frame 18 UL PDCP SN=4 2024-04-13T03:06:56.334981Z ๐Ÿ“ฑ UE ๐Ÿ“ก gNB
frame : Frame 18: Packet, 691 bytes on wire (5528 bits), 691 bytes captured (5528 bits)
Encapsulation type : Ethernet (1)
Arrival Time : Apr 12, 2024 20:06:56.334981000 Pacific Daylight Time
UTC Arrival Time : Apr 13, 2024 03:06:56.334981000 UTC
Epoch Arrival Time : 1712977616.334981000
Time shift for this packet : 0.000000000 seconds
Time delta from previous captured frame : 10.220000 milliseconds
Time delta from previous displayed frame : 10.220000 milliseconds
Time since reference or first frame : 543.253000 milliseconds
Frame Number : 18
Frame Length : 691 bytes (5528 bits)
Capture Length : 691 bytes (5528 bits)
Frame is marked : False
Frame is ignored : False
Protocols in frame : eth:ethertype:ip:udp:mac-nr:rlc-nr:rlc-nr:pdcp-nr:nr-rrc
Character encoding : ASCII (0)
eth : Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00
Destination : 00:00:00:00:00:00
Destination (resolved) : 00:00:00:00:00:00
Destination OUI : 00:00:00 (Officially Xerox, but 0:0:0:0:0:0 is more common)
Destination OUI (resolved) : Officially Xerox, but 0:0:0:0:0:0 is more common
.... ..0. .... .... .... .... = LG bit : Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit : Individual address (unicast)
Address : 00:00:00:00:00:00
Address (resolved) : 00:00:00:00:00:00
Address OUI : 00:00:00 (Officially Xerox, but 0:0:0:0:0:0 is more common)
Address OUI (resolved) : Officially Xerox, but 0:0:0:0:0:0 is more common
.... ..0. .... .... .... .... = LG bit : Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit : Individual address (unicast)
Source : 00:00:00:00:00:00
Source (resolved) : 00:00:00:00:00:00
Source OUI : 00:00:00 (Officially Xerox, but 0:0:0:0:0:0 is more common)
Source OUI (resolved) : Officially Xerox, but 0:0:0:0:0:0 is more common
.... ..0. .... .... .... .... = LG bit : Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit : Individual address (unicast)
Address : 00:00:00:00:00:00
Address (resolved) : 00:00:00:00:00:00
Address OUI : 00:00:00 (Officially Xerox, but 0:0:0:0:0:0 is more common)
Address OUI (resolved) : Officially Xerox, but 0:0:0:0:0:0 is more common
.... ..0. .... .... .... .... = LG bit : Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit : Individual address (unicast)
Type : IPv4 (0x0800)
Stream index : 0
ip : Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
0100 .... = Version : 4
.... 0101 = Header Length : 20 bytes (5)
Differentiated Services Field : 0x00 (DSCP: CS0, ECN: Not-ECT)
0000 00.. = Differentiated Services Codepoint : Default (0)
.... ..00 = Explicit Congestion Notification : Not ECN-Capable Transport (0)
Total Length : 677
Identification : 0x0011 (17)
010. .... = Flags : 0x2, Don't fragment
0... .... = Reserved bit : Not set
.1.. .... = Don't fragment : Set
..0. .... = More fragments : Not set
...0 0000 0000 0000 = Fragment Offset : 0
Time to Live : 64
Protocol : UDP (17)
Header Checksum : 0xffff [validation disabled]
Header checksum status : Unverified
Source Address : 127.0.0.1
Source or Destination Address : 127.0.0.1
Source Host : 127.0.0.1
Source or Destination Host : 127.0.0.1
Destination Address : 127.0.0.1
Source or Destination Address : 127.0.0.1
Destination Host : 127.0.0.1
Source or Destination Host : 127.0.0.1
Stream index : 0
udp : User Datagram Protocol, Src Port: 13337, Dst Port: 0
Source Port : 13337
Destination Port : 0
Source or Destination Port : 13337
Source or Destination Port : 0
Length : 657
Checksum : 0xffff [unverified]
Checksum Status : Unverified
Stream index : 0
Stream Packet Number : 18
Timestamps
Time since first frame : 543.253000 milliseconds
Time since previous frame : 10.220000 milliseconds
UDP payload (649 bytes)
mac-nr : MAC-NR UL-SCH (LCID:1 3 bytes) || (LCID:1 10 bytes) (Short BSR LCG ID=0 BS=0) (PHR PH=57 PCMAX_f_c=52) (Padding 601 bytes)
Context (RNTI=32768)
Radio Type : FDD (1)
Direction : Uplink (0)
RNTI : 0x8000 (32768)
RNTI Type : C-RNTI (3)
UEId : 1
System Frame Number : 243
Slot : 5
HarqId : 5
PHR Type2 other cell PHR : False
Subheader : (LCID:1 3 bytes)
0... .... = Reserved : 0x00
.0.. .... = Format : 8 bits
..00 0001 = LCID : 1 (1)
..00 0001 = LCID : 0x01
SDU Length : 3
UL-SCH SDU : 000400
RLC-NR UEId=1 [UL] [AM] SRB:1 [CONTROL] ACK_SN=4
Context
Direction : Uplink (0)
RLC Mode : Acknowledged Mode (4)
UEId : 1
Bearer Type : SRB (4)
Bearer Id : 1
PDU Length : 3
Sequence Number length : 12
AM
AM Header ACK_SN=4
0... .... = Data/Control : Control PDU
.000 .... = Control PDU Type : STATUS PDU (0x0)
.... 0000 0000 0100 = ACK Sequence Number : 4
0... .... = Extension bit 1 : A set of NACK_SN, E1, E2 and E3 does not follow
.000 0000 = Reserved : 0x00
Subheader : (LCID:1 10 bytes)
0... .... = Reserved : 0x00
.0.. .... = Format : 8 bits
..00 0001 = LCID : 1 (1)
..00 0001 = LCID : 0x01
SDU Length : 10
UL-SCH SDU : c00400042800944c9d98
RLC-NR UEId=1 [UL] [AM] SRB:1 [DATA] (P) SN=4 [8-bytes]
Context
Direction : Uplink (0)
RLC Mode : Acknowledged Mode (4)
UEId : 1
Bearer Type : SRB (4)
Bearer Id : 1
PDU Length : 10
Sequence Number length : 12
AM
AM Header (P) SN=4
1... .... = Data/Control : Data PDU
.1.. .... = Polling Bit : Status report is requested
..00 .... = Segmentation Info : Data field contains all bytes of an RLC SDU (0x0)
.... 0000 0000 0100 = Sequence Number : 4
AM Data : 00042800944c9d98
PDCP-NR (SN=4 )
Configuration : UEId= 1 SRB-1 (direction=Uplink, plane=Signalling)
Direction : Uplink (0)
Plane : Signalling (1)
UE : 1
Bearer type : DCCH (1)
Bearer Id : 1
Seqnum length : 12
MAC-I Present : True
Ciphering disabled : False
UE Security (ciphering=NEA2 (AES), integrity=NIA2 (AES))
Configuration frame : 17
Ciphering Algorithm : NEA2 (AES) (2)
Integrity Algorithm : NIA2 (AES) (2)
BEARER : 0
DIRECTION : Uplink (0)
COUNT : 4
CIPHER KEY : 95F23667A60D91689B31772783E6FDDD
0000 .... = Reserved : 0
.... 0000 0000 0100 = Seq Num : 4
Sequence Analysis - OK
Previous frame for Bearer : 15
Expected SN : 4
OK : True
NR Radio Resource Control (RRC) protocol
NR Radio Resource Control (RRC) protocol
UL-DCCH-Message
message : c1 (0)
c1 : securityModeComplete (5)
securityModeComplete
rrc-TransactionIdentifier : 0
criticalExtensions : securityModeComplete (0)
securityModeComplete
0... .... Optional Field Bit : False (lateNonCriticalExtension is NOT present)
.0.. .... Optional Field Bit : False (nonCriticalExtension is NOT present)
MAC : 0x944c9d98
Subheader : (Short BSR LCG ID=0 BS=0)
00.. .... = Reserved : 0x00
..11 1101 = LCID : Short BSR (61)
..11 1101 = LCID : 0x3d
000. .... = LCG : 0
...0 0000 = Buffer Size for LCG0 : BS = 0 (0)
Subheader : (PHR PH=57 PCMAX_f_c=52)
00.. .... = Reserved : 0x00
..11 1001 = LCID : Single Entry PHR (57)
..11 1001 = LCID : 0x39
00.. .... = Reserved : 0x0
..11 1001 = Power Headroom : 26 dB <= PH < 28 dB (57)
00.. .... = Reserved : 0x0
..11 0100 = Pcmax,c,f : 22 dBm <= Pcmax,f,c < 23 dBm (52)
Subheader : (Padding 601 bytes)
00.. .... = Reserved : 0x00
..11 1111 = LCID : Padding (63)
..11 1111 = LCID : 0x3f
Rendered from a Wireshark PCAP by VisualEther.

Frame 18's field tree, opened at MAC-NR. Expand along the path to reach the cipher's input set โ€” mac-nr โ†’ RLC-NR โ†’ PDCP-NR โ†’ UE Security โ€” where the algorithms, BEARER, DIRECTION, COUNT, and the key sit. Or expand the RRC node under PDCP-NR to see the SecurityModeComplete it is protecting.

COUNT: 4 is the number to look at. COUNT is 32 bits โ€” an HFN concatenated with the sequence number โ€” and only the sequence number travels on the wire. Here the SN has not wrapped, so COUNT and SN read the same, and they do so on every PDU in both sessions.

The split depends on the sequence-number width, because the two always total 32 bits. A 12-bit bearer spends 20 of them on the HFN:

packet accTitle: PDCP-NR COUNT composition on a 12-bit sequence-number bearer accDescr: Thirty-two bits. The high twenty bits are the hyper frame number; the low twelve bits are the sequence number. 0-19: "HFN (20 bits)" 20-31: "SN (12 bits)"
COUNT on SRB 1 โ€” 32 bits, of which the low 12 are the sequence number that travels and the high 20 are the HFN that does not. With the HFN at zero, COUNT reads the same as the SN, which is why every COUNT in this capture matches its header.

An 18-bit bearer takes six of those bits back, leaving a 14-bit HFN:

packet accTitle: PDCP-NR COUNT composition on an 18-bit sequence-number bearer accDescr: Thirty-two bits. The high fourteen bits are the hyper frame number, the low eighteen bits are the sequence number. 0-13: "HFN (14 bits)" 14-31: "SN (18 bits)"
COUNT on DRB 1 โ€” the same 32 bits, split 14 and 18. The wider sequence number buys a longer run before the HFN has to increment, which is why a high-throughput bearer is configured this way.

BEARER: 0 and DIRECTION: Uplink (0) are the other two inputs, and they are what make the numbering safe. Uplink SN=4 and downlink SN=4 on this bearer produce different keystreams because DIRECTION differs; SRB 1's SN=4 and DRB 1's SN=4 produce different keystreams because the keys differ. Change any one input and the output changes completely. The decryption companion has the key hierarchy those two keys descend from.

Put the five together and the whole of ciphering is one block. TS 33.501 ยงD.2 feeds 128-NEA2 a 128-bit KEY, the 32-bit COUNT, a 5-bit BEARER, a 1-bit DIRECTION, and the length of keystream wanted; out comes a keystream block that is XORed with the plaintext:

flowchart LR accTitle: The NEA2 ciphering block and its five inputs accDescr: A 128-bit key, a 32-bit COUNT, a 5-bit BEARER, a 1-bit DIRECTION, and a LENGTH feed the 128-NEA2 algorithm, which produces a keystream block. The keystream is combined by exclusive-or with the plaintext, which is the SDU plus the MAC-I trailer, producing the ciphered part of the PDU. KEY["KEY, 128 bits<br/>K_RRCenc or K_UPenc"] --> NEA CNT["COUNT, 32 bits<br/>HFN and SN"] --> NEA BRR["BEARER, 5 bits"] --> NEA DIR["DIRECTION, 1 bit"] --> NEA LEN["LENGTH"] --> NEA NEA["128-NEA2<br/>AES counter mode"] --> KS["KEYSTREAM BLOCK"] KS --> XOR(("XOR")) PT["Plaintext<br/>SDU and MAC-I"] --> XOR XOR --> CT["Ciphered part of the PDU"]
The NEA2 ciphering block (TS 33.501 ยงD.2). Five inputs produce a keystream, and the keystream is XORed with the plaintext โ€” so the same five inputs always reproduce the same ciphertext. Frame 18's UE Security node above shows four of them read straight off the wire. Decryption is the identical block: XOR the same keystream back.

Two things follow from that picture, and both show up in this capture. Only the plaintext side is secret, so the header outside the block stays readable to anyone. And because the block is deterministic, frames 128 and 129 โ€” same key, same COUNT, same bearer, same direction โ€” could not have produced anything but byte-identical ciphertext.

Integrity is the same shape with a different output (ยงD.3): 128-NIA2 takes the key, COUNT, BEARER, DIRECTION, and the message, and returns the 32-bit MAC-I rather than a keystream. That is why the tag changes when any one of them changes, and why a replayed message cannot borrow another frame's digest.

Frame 20 is the first ciphertext on the bearer. Downlink SN=4, and a Deciphered Data field appears for the first time in the capture, holding 300201200100100038426d05. Click the frame 20 message in the interactive viewer at the top of this page to open its field tree: MAC-NR -> RLC-NR -> PDCP-NR -> Deciphered Data. The frame 18 tree above has no such node โ€” nothing needs decrypting yet. Look at how it ends โ€” 38426d05 โ€” and compare it with the frame's MAC: 0x38426d05.

The MAC-I is inside the ciphered region. TS 38.323 ยง5.8 puts both the data part and the MAC-I under the cipher, so an observer without keys cannot see the integrity tag either. Only the header stays in the clear.

Frame 23 โ€” one sequence number, 1667 bytes, three RLC transmissions. Uplink SN=5 carries the UECapabilityInformation, and Wireshark reassembles it to 1667 bytes. It occupies exactly one PDCP sequence number. PDCP numbers the SDU it was handed; how many pieces the scheduler forced RLC to cut it into is invisible from up here. The RLC companion walks the same event from below, as a three-segment run across frames 21 to 23.

Frame 38 โ€” the hinge

Downlink SN=6 is an RRC Reconfiguration, and its drb-ToAddModList adds DRB 1 with a pdcp-Config that decides everything the second diagram shows:

SettingValue
pdcp-SN-SizeUL / pdcp-SN-SizeDLlen18bits (1)
discardTimerinfinity (15)
integrityProtectionnot present
headerCompressionnotUsed (0)
statusReportRequiredtrue (0)
t-Reorderingnot present

integrityProtection is NOT present is the one to remember. It is why every PDU on the data bearer arrives with MAC-I Present: False.

The same message carries an sdap-Config โ€” sdap-HeaderUL: present (0), sdap-HeaderDL: absent (1), one mapped QoS flow with QFI: 2 โ€” and adds SRB 2 with pdcp-Config is NOT present. No frame in this capture ever carries a pdcp-Config for any SRB. SRB 1 runs the format the spec fixes for signaling bearers, and nothing in the trace configures it.

Frames 39 to 128 โ€” a 10340.792 ms silence. Uplink SN=8 returns the RRCReconfigurationComplete; its deciphered payload is 0800b04f2105 โ€” two bytes of RRC, then b04f2105, which is exactly what the MAC field displays. Then the signaling bearer goes quiet for more than ten seconds while the entity frame 38 just created does the actual work. That silence is Act Two.

Frames 128 and 129 โ€” a retransmission that reuses a COUNT, legitimately

Frame 128 is downlink SN=7, continuing directly from the SN=6 of frame 38 ten seconds earlier. The entity kept its full state through the silence. It deciphers to 1000a48652fc: an RRC Release and the MAC-I 0xa48652fc.

Frame 129 is the same PDU again, 44.894 ms later, byte for byte. Wireshark heads the block Sequence Analysis- SN 7 Repeated and raises PDCP SN (7) repeated for Downlink for UE 1 (DCCH-1), with Expected SN: 8 and OK: False. The deciphered data is 1000a48652fc, and the MAC-I is 0xa48652fc โ€” identical to frame 128 in both cases.

That identity is the lesson. PDCP has no retransmission machinery at all. What happened is that RLC's poll went unanswered, its poll-retransmit timer expired, and RLC put the same stored PDU back on the wire โ€” the RLC companion measures that timer off exactly this pair of frames. Because PDCP had already assigned COUNT 7 and ciphered under it, the ciphertext could not change.

TS 33.501 forbids reusing a COUNT with the same key, bearer, and direction for different plaintext, because that reuses keystream. Re-sending an identical PDU reuses nothing new. Which gives the practical rule: a repeated PDCP SN with identical ciphertext is a lower-layer retransmission; a repeated PDCP SN with different ciphertext would be a genuine security incident.

Act Two โ€” DRB 1, the data bearer

Now rewind. While the signaling bearer sat silent, the entity frame 38 created was carrying the traffic: 32 messages, frames 41 to 114 โ€” 18 uplink PDUs numbered 0 to 17, and 14 downlink PDUs numbered 0 to 13. Its own diagram, its own counters, its own key.

Frame 41 โ€” a different header shape entirely. Seq Num: 0, and everything around it has changed:

And one subtle field: SDAP header: Present, QFI: 2. TS 38.323 ยง5.8 excludes the SDAP header from ciphering even though it rides inside the PDCP SDU, and the trace bears it out โ€” Wireshark's Deciphered Data for this frame begins 6000..., the IPv6 version nibble, with the SDAP byte outside it. The QoS Flow Identifier has to stay readable so the receiver can classify a packet it has not yet decrypted.

Frame 43 โ€” the same bearer, a different PDU layout. Downlink SN=0 reports SDAP header: Not Present. Not an inconsistency: frame 38 said sdap-HeaderUL: present (0) and sdap-HeaderDL: absent (1), so the two directions genuinely carry different layouts. The ignorance runs one way. The gNB already knows which flow it is sending on, because the QFI arrived with the packet from the UPF, so repeating it to the UE would say nothing new. Going up, it is the gNB that has to be told โ€” it must name the flow again before handing the packet to N3, and the header is the only thing that can name it. The SDAP companion has the full argument. Across the session, QFI: 2 appears on all 18 uplink PDUs and on none of the 14 downlink ones.

Frames 50 to 53 โ€” the counter versus the transmissions. Frame 50 is three RLC PDUs on the wire but only one complete PDCP PDU, SN=2. Frame 52 completes SN=3, reassembled to 1264 bytes from three RLC segments. Frame 53 completes SN=4, reassembled to 514 bytes. SN 3 and SN 4 were in flight simultaneously โ€” frame 52 carried the tail of one and the head of the other. That interleaving is exactly why PDCP numbers SDUs before handing them down.

Frames 72 onward โ€” a third layer of encryption, inside the plaintext. Uplink SN=8 deciphers not to TCP but to IPv6 next header 50: ESP, IPsec's Encapsulating Security Payload, with SPI 0x00000100. We decrypted PDCP successfully and found more ciphertext underneath, protected by keys that were never on this radio link. It is frame 12's lesson again in a different place โ€” PDCP protects one hop, and it is not the only thing protecting this traffic. The decryption companion follows that payload the rest of the way and explains why the trail ends there.

Frames 90 and 110 โ€” segmentation is invisible from up here. Downlink SN=8 is a 1223-byte PDCP PDU carried whole. Downlink SN=11 is a 1499-byte PDU that RLC had to cut in two. Same bearer, same direction, same layer โ€” the only difference is how much room the scheduler happened to offer. PDCP's numbering is unaffected either way, which is the whole point of the boundary.

Frames 97 and 111 โ€” two PDCP PDUs in one frame. Frame 97 completes uplink SN=14 and carries the whole of SN=15; frame 111 does the same for downlink SN=12 and SN=13. Two sequence numbers, two COUNT values, two separate keystreams, one radio transmission. The diagram splits each pair into two arrows because they are two independent PDUs.

Frame 114 โ€” the bearer's last PDU. Uplink SN=17, reassembled to 984 bytes. Eighteen uplink PDUs numbered 0 through 17 with no gap and no repeat; Sequence Analysis - OK on every one of the session's 32 PDUs, and not a single retransmission.

The contrast with Act One is instructive, and it is not about PDCP. PDCP has no retransmission logic on either bearer. The difference is that every RLC poll on this bearer was answered, so nothing was ever re-sent, so no COUNT was ever used twice.

One more thing frame 38 predicted, and the trace confirms: statusReportRequired: true (0) arms this bearer to send a PDCP status report โ€” and none is ever sent, in either direction, in the whole capture. A PDCP status report is a re-establishment artifact, and frame 38 also says reestablishPDCP is NOT present and recoverPDCP is NOT present. Nothing ever asked for one.

The later connections

The signaling bearer's diagram does not stop at frame 129. Frames 133 to 146 are a second RRC connection, 3225.427 ms later, and Wireshark's configuration line switches from UEId= 1 to UEId= 2.

Everything resets. Uplink Seq Num: 0 on SRB 1 again, MAC: 0x00000000 [Matches calculated result] again, and no Previous frame for Bearer link back to frame 129. A PDCP entity lives and dies with its bearer, so TX_NEXT, the COUNT state, and the security context all start from nothing. From there, the second connection repeats the first in miniature โ€” three uplink PDUs numbered 0 to 2, five downlink PDUs numbered 0 to 3 with the last one repeated.

That repeat is frames 145 and 146, 44.915 ms apart, and it is frame 129 all over again: PDCP SN (3) repeated for Downlink for UE 2 (DCCH-1), OK: False, and the same two bytes on the wire both times. This SRB session ends there, mid-retransmission โ€” not the capture.

A third connection begins at frame 150, outside this session โ€” the gap before it is past the timeout that closes the session, so it appears on neither diagram.

Where ciphering starts, measured twice โ€” once with keys and once without

Frames 17 and 18 showed the boundary that TS 38.331 ยง5.3.4.3 defines: integrity protection from the Security Mode Command onward, ciphering only after the procedure completes. On the first connection, you can watch it happen because the capture ships with that UE's Access-Stratum keys.

The second connection is the control experiment, and it is better evidence. There are no keys for UEId 2 anywhere in this trace. Nothing on that connection can be decrypted. And yet:

FrameMessageWhat Wireshark shows
133RRCSetupCompleteDecodes fully. MAC: 0x00000000
136RRC securityModeCommandDecodes fully. Real MAC-I 0xcc0cdfbc, and the same MAC-I Digest wrong artifact as frame 17
137RRC securityModeCompleteDecodes fully. Real MAC-I 0x78b22a09
139first message after the procedureSignalling Data: 38a4bc1a51d9573b91b80215131c5150... โ€” opaque
140, 142, 145, 146everything afteropaque

Read those five rows together. On a connection nobody holds a key for, the last two messages that stay readable are the two that bracket security activation โ€” and the very next PDU goes dark. Wireshark's pdcp-nr.signalling-data field, the one it falls back to when it cannot decrypt, appears on frames 139, 140, 142, 145 and 146 and on no others.

Now put that beside the first connection. There, Deciphered Data โ€” the field that appears only when Wireshark actually ran AES โ€” is absent on frames 4 through 18 and first appears on frame 20 in the downlink and frame 23 in the uplink, immediately after the Security Mode exchange. The boundary sits in precisely the same place on both connections.

That is the same spec rule visible from two directions. With keys, you see the first frame that needed decrypting. Without keys, you see the first frame that could not be read โ€” and it is the same frame in the procedure. The rule is not an artifact of holding the keys; the keys change which side of it you can see.

Two things this is not, both worth stating because they are the usual misreadings:

If you take one diagnostic habit from this page, take this one. When an SRB stops decoding partway through a trace, do not assume corruption or a dissector bug โ€” look for the Security Mode Command a frame or two earlier. Everything before it is readable by design, and everything after it needs a key.

Takeaways

  1. The sequence number counts messages, not transmissions. One PDCP SN=5 covered a 1667-byte capability report that RLC split three ways. Across the whole capture, 59 PDCP PDUs on 57 frames, the PDCP sequence number matched the RLC sequence number of the PDU carrying it every single time โ€” two counters that happen to run in lockstep because nothing here ever disturbed either one.
  2. COUNT is what the cipher consumes, and SN is only its lower half. Wireshark prints it on 16 of the signaling bearer's 26 PDUs and on all 32 of the data bearer's, and it is never different from the sequence number, because no counter here wrapped. On a longer trace, the HFN is exactly what you would be hunting when the two diverge.
  3. The header is in the clear; the payload and the MAC-I are not. Frame 20's deciphered bytes end in the same value the MAC field displays โ€” the integrity tag lives inside the ciphered region. Everything a receiver needs before decryption โ€” sequence number, D/C bit, SDAP header โ€” is deliberately outside it.
  4. A repeated PDCP SN is usually a lower-layer retransmission. Frames 128/129 and 145/146 re-sent byte-identical PDUs under an unchanged COUNT, 44.894 ms and 44.915 ms apart. Check whether the ciphertext changed: identical means RLC re-sent; different would mean keystream reuse.
  5. The two bearers share a radio link and almost nothing else. Different sequence-number widths, different header layouts, different keys, and one of them has no integrity tag at all โ€” all of it decided by a single pdcp-Config in frame 38.

Where this sits in the stack

This page follows one layer of a much larger trace. The layers around it tell different parts of the same story:

Try it on your own capture

Every arrow in both diagrams was decoded and captioned by VisualEther from a raw Wireshark PCAP โ€” including the session split that separated the two PDCP entities onto their own timelines. Point it at your own 5G, LTE, or IMS trace and read it the same way.