>
Home5G NRMAC — Medium Access ControlMAC PDU & CEs
🧩 MAC — Medium Access ControlIntermediate

MAC PDU, Subheaders & MAC CEs in 5G NR

How SDUs, MAC Control Elements and padding are packed into a transport block.

📚 3GPP-basedTS 38.321

The physical layer will accept exactly one transport block per HARQ process per transmission occasion, of exactly one size, chosen by the scheduler from a table TS 38.214 cl. 5.1.3.2. MAC's job is to fill that block completely and to make the result parseable by a peer that was told nothing about what is inside it. Those two requirements together produce the whole design: a flat concatenation of self-describing units, plus padding to make the total land on the transport block size with no slack.

Contents
  1. 01What a MAC PDU Is For, and Why Every Byte Has a Subheader
  2. 02The subPDU: the Only Unit MAC Actually Handles
  3. 03The Subheader, All Six Shapes
  4. 04LCID on DL-SCH: the Complete Codepoint Space
  5. 05LCID on UL-SCH: the Complete Codepoint Space
  6. 06eLCID and the Two-Octet Extended Space
  7. 07subPDU Ordering, and Why It Is Asymmetric
  8. 08Padding, and the Single-Byte Case
  9. 09How a Receiver Walks a PDU -- and What Happens When It Cannot
  10. 10The Control Element Catalogue
  11. 11Bit Layouts of the CEs You Will Actually Meet
  12. 12What Each CE Tells You When You See It in a Log
  13. 13What Control Costs: Overhead Arithmetic
  14. 14Failure Modes and What Each One Means
  15. 15Where the Configuration Comes From
  16. 16Illustrative Message Traces
  17. 17Release Deltas: Rel-15 to Rel-18
  18. 18Reading MAC PDUs in Logs: a Checklist
  19. 19Glossary
  20. 20References

1. What a MAC PDU Is For, and Why Every Byte Has a Subheader

The physical layer will accept exactly one transport block per HARQ process per transmission occasion, of exactly one size, chosen by the scheduler from a table TS 38.214 cl. 5.1.3.2. MAC's job is to fill that block completely and to make the result parseable by a peer that was told nothing about what is inside it. Those two requirements together produce the whole design: a flat concatenation of self-describing units, plus padding to make the total land on the transport block size with no slack.

There is no MAC header in the sense that IP or Ethernet has one. There is no PDU-level length, no version, no checksum, no next-header pointer and no field that says how many pieces follow. A receiver starts at offset zero, reads one octet, and works out from that octet alone what to do with the next few. It repeats until it runs out of transport block. Everything good and everything fragile about MAC decoding follows from that.

The pieces MAC concatenates are of two kinds. MAC SDUs come from above: one RLC PDU per logical channel, opaque to MAC. MAC Control Elements are generated by MAC itself and consumed by the peer MAC: no RRC message, no ASN.1, no acknowledgement, no retransmission of their own beyond whatever HARQ gives them. A MAC CE is the cheapest signalling in NR, and that cheapness is why so much of the fast control loop -- timing advance, buffer status, power headroom, carrier activation, beam selection, DRX -- was put here rather than in RRC.

💡
Key Point

The reason to care about the exact packing rules is not academic. A MAC CE that the network sent and the UE did not act on looks identical, in most logs, to a MAC CE the network never sent -- unless you can read the octets. Two thirds of the "UE ignored our command" investigations in practice resolve to an ordering rule, a padding rule, or a codepoint the decoder on one side of the link did not know.

The companion 06 Channel Mapping document introduces the LCID field and the subheader in the context of which channel carries what. This document is the authoritative treatment: every subheader shape including the Rel-16 extensions, both complete codepoint tables, the ordering and padding rules, and each control element with its trigger and layout.

2. The subPDU: the Only Unit MAC Actually Handles

A MAC PDU consists of one or more MAC subPDUs TS 38.321 cl. 6.1.2. A subPDU is a subheader plus at most one of: a MAC SDU, a MAC CE, or padding. That is the entire grammar. There is no nesting, no optional second payload, and no subPDU that carries two things.

MAC PDU structure in both directionsA MAC PDU Is a Sequence of subPDUs -- and the Order Differs by DirectionTS 38.321 cl. 6.1.2 -- control first in the downlink, data first in the uplinkDL-SCH MAC PDU (one transport block)subPDU 1TA Command CEsubPDU 2SCell A/D CEsubPDU 3DCCH SDU (SRB1)subPDU 4DTCH SDU (DRB1)subPDU 5PaddingUL-SCH MAC PDU (one transport block)subPDU 1DCCH SDU (SRB1)subPDU 2DTCH SDU (DRB1)subPDU 3Short BSR CEsubPDU 4Single Entry PHRsubPDU 5PaddingInside one subPDUMAC subheader1, 2 or 3 octets -- LCID and maybe LPayloadMAC CE, MAC SDU, or nothingThe asymmetry is deliberate. A gNB wants its control element acted on before the UE spends time on the data;a UE wants its report to describe the buffer *after* the SDUs in this very PDU have been removed from it.
Figure 1. The same five-piece PDU packed for each direction. The subPDU boundary is the only structure MAC has; everything else is a consequence of the LCID inside each subheader.
subPDU containsSubheader shapeLength known fromExample
A MAC SDUR/F/LCID/L (2 or 3 octets)The L fieldAn RLC PDU on DTCH, LCID 4, L = 132
A variable-size MAC CER/F/LCID/L, or with an eLCID escapeThe L fieldLong BSR (UL LCID 62); TCI States Activation/Deactivation (DL LCID 53)
A fixed-size MAC CER/LCID (1 octet), or with an eLCID escapeThe codepoint itself -- the receiver must already know the CETiming Advance Command (DL LCID 61, 1 octet payload)
A zero-size MAC CER/LCID (1 octet)Nothing follows; the subheader is the whole subPDUDRX Command (DL LCID 60); Configured Grant Confirmation (UL LCID 55)
An UL CCCH SDUR/LCID (1 octet)The codepoint: LCID 52 means 48 bits, LCID 0 means 64 bitsRRCSetupRequest in MSG3
PaddingR/LCID (1 octet), LCID 63Implicit -- everything to the end of the transport blockThe last subPDU of almost every real PDU

Table 1. The six things a subPDU can be. Note the third and fifth rows: two cases where the length is carried by prior knowledge rather than by a field, which is exactly where decoders break.

📘
Spec Detail

A single MAC SDU is never split across two subPDUs, and a subPDU never spans two transport blocks. If an RLC PDU does not fit, RLC segments it and hands MAC a smaller PDU -- MAC does not fragment. This is why the L field is enough: whatever it says is entirely present in this transport block. See the companion 09 LCP document for how the size handed to RLC is decided.

3. The Subheader, All Six Shapes

Every subheader begins with the same two bit positions and a 6-bit LCID. What follows the LCID depends on what the LCID means, which the receiver has to know in advance. Four shapes existed in Rel-15; Rel-16 added two more by turning two LCID values into escapes.

The Four Base MAC Subheader ShapesThe Four Base MAC Subheader ShapesTS 38.321 cl. 6.1.2. Each shape restarts at its own octet 1; rows are numbered continuously herebit76543210Oct 1RF=0LCID = 4 shape A: R/F/LCID/L with 8-bit LOct 2L = 26 octets (SDU or variable CE, 0 .. 255)Oct 3RF=1LCID = 4 shape B: R/F/LCID/L with 16-bit LOct 4L, high octet = 0x04Oct 5L, low octet = 0xB0 -> L = 1200 octetsOct 6RRLCID = 61 shape C: R/LCID, no L field at allOct 7RRLCID = 63 shape D: R/LCID for paddingNothing in the subheader says which shape it is. The receiver decides from the LCID alone: a variable-size codepointmeans an L field follows and the F bit says how wide it is; a fixed-size codepoint means the payload length is alreadyknown; LCID 63 means the rest of the transport block is padding.
Figure 2. The four Rel-15 shapes. The F bit only exists when there is an L field to describe; in shapes C and D that bit position is a second reserved bit.
The Rel-16 Extended-LCID Subheader ShapesThe Rel-16 Extended-LCID Subheader ShapesLCID 33 and 34 are escapes, not control elements -- TS 38.321 cl. 6.1.2 and Tables 6.2.1-1a/-1b/-2a/-2bbit76543210Oct 1RRLCID = 34 one-octet eLCID escape, fixed-size CEOct 2eLCID = 230 -> codepoint 64 + 230 = 294Oct 3RF=0LCID = 34 one-octet eLCID escape, variable-size CEOct 4eLCID = 236 -> codepoint 64 + 236 = 300Oct 5L = 3 octetsOct 6RRLCID = 33 two-octet eLCID escapeOct 7eLCID, high octetOct 8eLCID, low octet -> codepoint 320 + valueThe escape costs one or two extra octets per subPDU, which is why it was spent on rare control elements and never onlogical-channel identities. A pre-Rel-16 decoder prints LCID 33/34 as reserved and then desynchronises for the rest of the PDU.
Figure 3. The Rel-16 escapes. LCID 33 and 34 are not control elements -- they are instructions to read a wider identifier from the following octet or two.
ShapeOctetsBit layoutUsed forHow the receiver knows
A2R(1) F=0(1) LCID(6) | L(8)Any SDU or variable-size CE up to 255 octetsLCID is a variable-size codepoint; F = 0
B3R(1) F=1(1) LCID(6) | L(16)A single SDU longer than 255 octets -- common on high-throughput DRBsLCID is a variable-size codepoint; F = 1
C1R(1) R(1) LCID(6)Fixed-size and zero-size MAC CEs; the UL CCCH SDULCID is a fixed-size codepoint of known length
D1R(1) R(1) LCID = 63Padding, always the last subPDULCID 63 is reserved for exactly this
E (Rel-16)2 or 3R/R/LCID=34 | eLCID(8) | (L)A control element in codepoints 64 .. 319LCID 34 is an escape; the eLCID octet gives the real codepoint
F (Rel-16)3 or 4R/R/LCID=33 | eLCID(16) | (L)A control element in codepoints 320 .. 65 855LCID 33 is an escape; two octets give the real codepoint

Table 2. Subheader shapes, TS 38.321 cl. 6.1.2. Nothing in the octets distinguishes A/B from C/D except the LCID value, which is why the codepoint tables in the next two sections are the real parsing specification.

⚠️
Common Pitfall

The F bit is not a general format flag. It exists only in shapes A, B and the variable-size eLCID shapes, and it says one thing: whether L is 8 or 16 bits wide. In shapes C and D the same bit position is a reserved bit that must be zero. A log that prints "F = 1" for a Timing Advance Command subheader is either showing you a corrupt octet or printing a field that does not exist at that position.

4. LCID on DL-SCH: the Complete Codepoint Space

Six bits, 64 codepoints, and Rel-15 spent all but twelve of them. The structure is worth noticing: SDU identities occupy the bottom, control elements the top, and the escapes sit at 33 and 34, immediately above the logical channel range so that no future logical channel can ever be added without a version break.

LCIDMeaningSize on the wireFixed / variable
0CCCHSubheader with L; the SDU is RRCSetup or RRCRejectVariable
1 – 32Identity of a logical channel (DCCH or DTCH)Subheader with L, then the RLC PDUVariable
33Extended LCID field, two octets (Rel-16)Escape; codepoint = 320 + value--
34Extended LCID field, one octet (Rel-16)Escape; codepoint = 64 + value--
35 – 46ReservedLargely still reserved through Rel-18; new downlink CEs went into the extended space instead--
47Recommended bit rate2 octetsFixed
48SP ZP CSI-RS Resource Set Activation/Deactivation2 octetsFixed
49PUCCH spatial relation Activation/Deactivation3 octetsFixed
50SP SRS Activation/DeactivationVariable -- depends on the number of resources in the setVariable
51SP CSI reporting on PUCCH Activation/Deactivation2 octetsFixed
52TCI State Indication for UE-specific PDCCH2 octetsFixed
53TCI States Activation/Deactivation for UE-specific PDSCHVariable -- one bit per candidate TCI stateVariable
54Aperiodic CSI Trigger State SubselectionVariable -- one bit per trigger stateVariable
55SP CSI-RS / CSI-IM Resource Set Activation/DeactivationVariableVariable
56Duplication Activation/Deactivation1 octetFixed
57SCell Activation/Deactivation (four octets)4 octetsFixed
58SCell Activation/Deactivation (one octet)1 octetFixed
59Long DRX Command0 octets -- subheader onlyFixed
60DRX Command0 octets -- subheader onlyFixed
61Timing Advance Command1 octetFixed
62UE Contention Resolution Identity6 octets (48 bits)Fixed
63Padding0 octets of subheader payload; fills the rest of the TB--

Table 3. DL-SCH LCID codepoints, TS 38.321 Table 6.2.1-1, with the size class that decides which subheader shape carries them. The companion 06 Channel Mapping document gives the same table from the channel-mapping angle.

⚠️
Common Pitfall

Codepoint 63 is padding in both directions, and codepoints 59-62 in the downlink collide numerically with 59-62 in the uplink (truncated and full BSRs). LCID is only meaningful together with the direction. A decoder configured for the wrong direction will happily turn a Short BSR into a Long DRX Command with no complaint at all -- both are valid fixed-size codepoints and both parse cleanly.

5. LCID on UL-SCH: the Complete Codepoint Space

The uplink table has the same shape and one structural oddity: CCCH appears twice, at 0 and 52, for the two possible sizes. That exists purely so a CCCH SDU can use a 1-octet subheader with no length field -- in MSG3 and MSGA, where every bit is expensive, the codepoint carries the length.

LCIDMeaningSize on the wireRelease
0CCCH of size 64 bits (the CCCH1 channel)8 octets, no L field. Carries RRCResumeRequest1Rel-15
1 – 32Identity of a logical channel (DCCH or DTCH)Subheader with L, then the RLC PDURel-15
33Extended LCID field, two octetsEscape; codepoint = 320 + valueRel-16
34Extended LCID field, one octetEscape; codepoint = 64 + valueRel-16
35 – 44Reserved----
45Truncated Sidelink BSRVariableRel-16
46Sidelink BSRVariableRel-16
47Pre-emptive BSRVariable -- Long-BSR-shapedRel-16 (IAB)
48LBT failure (four octets)4 octetsRel-16 (NR-U)
49LBT failure (one octet)1 octetRel-16 (NR-U)
50BFR (Beam Failure Recovery)Variable -- bitmap plus one octet per failed cellRel-16
51Truncated BFRVariableRel-16
52CCCH of size 48 bits6 octets, no L field. RRCSetupRequest, RRCResumeRequest, RRCReestablishmentRequest, RRCSystemInfoRequestRel-15
53Recommended bit rate query2 octetsRel-15
54Multiple Entry PHR (four octets)Variable -- 4-octet bitmap then 1-2 octets per reported cellRel-15
55Configured Grant Confirmation0 octets -- subheader onlyRel-15
56Multiple Entry PHR (one octet)Variable -- 1-octet bitmap then 1-2 octets per reported cellRel-15
57Single Entry PHR2 octetsRel-15
58C-RNTI2 octetsRel-15
59Short Truncated BSR1 octetRel-15
60Long Truncated BSRVariableRel-15
61Short BSR1 octetRel-15
62Long BSRVariable -- bitmap then one octet per reported LCGRel-15
63PaddingFills the rest of the TBRel-15

Table 4. UL-SCH LCID codepoints. The Rel-16 assignments in 45-51 are the ones most likely to differ between the spec version you are reading and the decoder you are using -- confirm them against TS 38.321 Table 6.2.1-2 of the release in question.

🔍
What You See In Logs

Two uplink codepoints have no payload at all and are therefore invisible in any log that prints only "bytes of MAC CE": Configured Grant Confirmation (55) and, in the downlink, DRX Command (60) and Long DRX Command (59). If you are chasing a configured grant that the network believes is not active, or a UE that will not wake up, look for a single octet -- 0x37, 0x3C, 0x3B respectively -- and nothing after it.

6. eLCID and the Two-Octet Extended Space

By the end of Rel-15 the downlink table had twelve free codepoints and the uplink had seventeen, against a Rel-16 work programme that added beam-failure reporting, LBT failure reporting, IAB power and guard-symbol signalling, positioning, multi-TRP beam management and unified TCI. Reusing reserved values was not an option, because a receiver that meets an unrecognised fixed-size codepoint cannot find the next subheader -- there is no length to skip. So Rel-16 spent two of the remaining codepoints on escapes.

🧮
Worked Calculation

What the escape bought, exactly.

Native 6-bit LCID: 64 codepoints, 0 .. 63

One-octet eLCID via LCID 34: 256 values -> codepoints 64 .. 319

Two-octet eLCID via LCID 33: 65 536 values -> codepoints 320 .. 65 855

Total addressable: 64 + 256 + 65 536 = 65 856

Cost per use: one extra octet for the one-octet form, two for the two-octet form. Against a 2-octet CE that is a 50% or 100% overhead on the control element -- which is why the escape is spent on rare, infrequent CEs and never on a logical channel identity. Logical channels remain capped at 32 per direction per MAC entity.

As of Rel-18 the two-octet space is entirely reserved: nothing has been assigned there yet. Every real extended control element lives in the one-octet space reached through LCID 34. The two-octet escape exists so that the next twenty years of MAC CEs do not require another format change.

Extended-space CEDirReleaseSizeWhat it is for
Enhanced SCell Activation/Deactivation (1-octet and 4-octet Ci forms)DLRel-17VariableActivates an SCell and names the TCI state to use on it, so the UE does not have to run a fresh beam search after activation
Unified TCI States Activation/DeactivationDLRel-17VariableRel-17 unified TCI: one indication drives both DL and UL beams
Enhanced TCI States Activation/Deactivation for UE-specific PDSCHDLRel-17VariableMulti-TRP: two TCI states per codepoint
Duplication RLC Activation/DeactivationDLRel-16VariablePer-RLC-leg duplication control, rather than the whole-DRB switch of LCID 56
Positioning Measurement Gap Activation/Deactivation CommandDLRel-17FixedOpens a gap for PRS measurement without an RRC reconfiguration
Provided Guard Symbols / Desired Guard SymbolsDL / ULRel-16VariableIAB: the DU tells the MT how many symbols it needs to switch between parent and child links, and the MT asks for more
Timing Case Indication / Case-6 Timing RequestDL / ULRel-17FixedIAB timing mode selection
Desired IAB-DU TX Power AdjustmentULRel-17VariableIAB-MT asks its parent to change the collocated DU's transmit power
Enhanced BFR / Enhanced Truncated BFRULRel-17VariablePer-TRP beam failure reporting, for multi-TRP PDCCH
Multiple Entry Configured Grant ConfirmationULRel-16VariableConfirms several configured grants at once (Rel-16 allows up to 12 per BWP)
SP Positioning SRS Activation/DeactivationDLRel-17VariableTurns semi-persistent positioning SRS on and off
Sidelink Configured Grant ConfirmationULRel-16FixedNR sidelink equivalent of LCID 55

Table 5. Representative contents of the one-octet extended space. Codepoints are deliberately not listed: assignments are added from the top of the range downward as features land, and differ between releases. Read them from Table 6.2.1-1b (DL) or 6.2.1-2b (UL) of the exact TS 38.321 version you are decoding against.

⚠️
Common Pitfall

The signature of a decoder that predates the extended space is very specific: one plausible subPDU, then garbage. The decoder prints LCID 33 or 34 as reserved, guesses a length, lands mid-payload, and then reports a run of impossible subheaders -- LCIDs in the reserved range, absurd L values, a padding subheader in the middle of the PDU. That pattern is a decoder version problem, not a radio problem, and no amount of retuning will change it.

7. subPDU Ordering, and Why It Is Asymmetric

The order of subPDUs inside a MAC PDU is fixed by the spec, and it is different in the two directions TS 38.321 cl. 6.1.2.

DirectionRequired orderWhy
DL-SCHMAC CEs first, then MAC SDUs, then paddingThe UE can act on the control element -- change beam, activate an SCell, adjust timing, go to sleep -- while it is still working through the data in the same PDU. Putting the CE last would mean waiting for a full transport block of RLC processing before a 1-octet command takes effect.
UL-SCHMAC SDUs first, then MAC CEs, then padding -- except that a Pre-emptive BSR is placed before all MAC SDUsA buffer status report must describe the buffer as it will be after this PDU leaves, so the SDUs have to be selected first. Building the SDUs first and the report second is the natural implementation order, and the wire order follows it. The Pre-emptive BSR is the exception because it reports data that has not arrived yet, so it does not depend on what was packed.

Table 6. Ordering rules. The uplink exception for Pre-emptive BSR came in with Rel-16 IAB; verify it against the release you are decoding.

Within each of those groups the order is not arbitrary either, but it is decided by a different rule: the relative priority of control elements and logical channel data, defined for the uplink in TS 38.321 cl. 5.4.3.1.3 and covered in the companion 09 LCP document. The short version is that a C-RNTI MAC CE and UL-CCCH data sit above everything, a BSR included as padding sits below everything, and the rest fall between.

💡
Key Point

The ordering rule is a transmitter obligation, not a receiver requirement. A conformant receiver parses subPDUs in whatever order they arrive; it does not reject a PDU whose CEs are in the wrong place. So a vendor bug that emits an uplink CE before the SDUs will not produce an error anywhere -- it will produce a BSR that describes a buffer including data the gNB is about to receive, and therefore a persistent, small over-estimate of the UE's queue. That shows up as chronically slightly over-sized grants, never as a failure.

8. Padding, and the Single-Byte Case

A transport block size comes from a table; the sum of the subPDUs MAC wants to send almost never equals one of those sizes. The difference is padding, and it goes at the end. NR has no equivalent of LTE's front-placed one- and two-byte padding: the padding subPDU is last, always.

  • Zero padding. The subPDUs fill the block exactly. There is no padding subheader at all -- not a padding subheader with L = 0, nothing. This is the normal case for a large data-only PDU where RLC was asked for exactly the right segment size.
  • One octet of padding. The padding subPDU is a single R/LCID subheader with LCID 63 and no payload. One octet in, one octet of transport block consumed, nothing wasted on a length field. This is the single-byte case, and it is why the padding subheader has no L field: with one, one byte of slack would be unrepresentable.
  • Two or more octets. One padding subheader, then padding octets to the end of the block. The receiver does not need to be told how many: LCID 63 means everything from here on.
💡
Key Point

Padding is not free space -- it is the trigger for a whole class of opportunistic reporting. If the padding remaining after a MAC PDU is built is at least the size of a Short BSR plus its subheader (2 octets), MAC replaces padding with a Padding BSR TS 38.321 cl. 5.4.5. The same logic drives the truncated BSR and truncated BFR formats. So the presence of a 1-octet padding subPDU and the presence of a padding BSR are mutually exclusive by construction, and seeing 6 octets of padding with a BSR pending is a genuine anomaly worth chasing.

One more rule that catches people: MAC does not transmit a PDU consisting only of a padding BSR and padding. If there is nothing else to send, the grant goes unused rather than being spent on a report the network can get another way.

9. How a Receiver Walks a PDU -- and What Happens When It Cannot

MAC PDU parse loopHow a Receiving MAC Entity Walks a MAC PDUTS 38.321 cl. 6.1.2 -- there is no PDU-level length field, no checksum and no way to resynchroniseRead the next subheader octetLCID = 33or 34?yesRead 1 or 2 eLCID octets:codepoint = 64+v or 320+vnoLCID = 63?yesRest of the TB is padding. Stop.noLength knownfrom the codepoint?unknownLCIDDiscard the restof the TBno -- variable sizeRead L: 1 octet if F=0,2 octets if F=1yes -- fixed sizeDeliver payload -- CE to its MAC procedure, SDU to the RLCentity for that LCID -- advance the offset, repeatEvery step depends on the previous one having been parsed correctly. That is why an unrecognised fixed-size codepoint isfatal to the rest of the transport block rather than merely to one subPDU.
Figure 4. The receive-side parse. The single most important property of this loop is that it has no error recovery: there is no resynchronisation point anywhere in a MAC PDU.

Three of the branches above are worth dwelling on, because each corresponds to a distinct log signature.

9.1 Unknown variable-size codepoint

The receiver does not recognise the LCID but the codepoint is in a range it knows to be variable-size, so it reads L and skips L octets. It has lost one subPDU and can continue. In a log this appears as a single "unknown LCID" line followed by correctly decoded subPDUs. Annoying, recoverable, usually a bearer that RRC configured on one side only.

9.2 Unknown fixed-size codepoint

The receiver does not recognise the LCID and there is no length field. It cannot skip, cannot resynchronise, and must discard the remainder of the transport block. Everything after that point is lost -- including, commonly, the data SDUs, since in the downlink CEs come first. One unknown control element costs the whole PDU.

9.3 Length field longer than the remaining transport block

An L value that runs past the end of the block means the parse has already gone wrong upstream -- a mis-parsed subheader, a wrong-direction codepoint table, or a corrupt octet that HARQ CRC should have caught but did not because the corruption is in the decoder's own byte accounting rather than on the air. The PDU is discarded.

📘
Spec Detail

Because there is no MAC-level integrity check, a MAC PDU that passes the transport-block CRC is assumed to be correctly formed. That assumption is what makes the parse cheap enough to run at 4 GHz of throughput, and it is why every failure in this section is silent at the physical layer. Correlate with HARQ statistics from the companion 05 HARQ document: if CRC pass rates are healthy and MAC decode is failing, the problem is in the codepoint tables, not on the radio.

10. The Control Element Catalogue

Every MAC CE in NR is listed below by function, with the LCID, the direction, whether the size is fixed, and -- the part that is hardest to find in the spec -- what actually causes one to be emitted. The clause numbers in the last column point at the procedure that triggers the CE, not at its format.

10.1 Identity, contention resolution and grant confirmation

MAC CELCIDDirSizeWhat triggers it
UE Contention Resolution IdentityDL 62DL6 octets, fixedMSG4 in contention-based Random Access. Echoes the first 48 bits of the UE's MSG3 CCCH SDU so the winner can recognise itself TS 38.321 cl. 5.1.5
C-RNTIUL 58UL2 octets, fixedA UE that already has a C-RNTI performs Random Access (handover, TA recovery, beam failure). Sending the C-RNTI in MSG3 is the contention resolution -- the gNB answers on the C-RNTI itself TS 38.321 cl. 5.1.4
Configured Grant ConfirmationUL 55UL0 octetsThe UE has activated or released a Type 2 configured grant via PDCCH and must confirm it TS 38.321 cl. 5.8.2
Multiple Entry Configured Grant ConfirmationeLCIDULVariableRel-16: same, when several configured grants changed state together

Table 7. Identity CEs. The C-RNTI CE is the one people forget exists: its presence in a MSG3 tells you immediately that this was not an initial access.

10.2 Uplink reporting: buffer, power, rate

MAC CELCIDDirSizeWhat triggers it
Short BSRUL 61UL1 octet, fixedRegular, Periodic or Padding BSR when exactly one LCG has data TS 38.321 cl. 5.4.5
Long BSRUL 62ULVariableRegular or Periodic BSR when more than one LCG has data
Short Truncated BSRUL 59UL1 octet, fixedPadding BSR where only one octet fits but more than one LCG has data
Long Truncated BSRUL 60ULVariableA Long BSR is called for but the space cannot hold every buffer size field
Pre-emptive BSRUL 47ULVariableRel-16 IAB: an IAB-MT reports data it expects to receive from a child node, so the parent can grant ahead of arrival
Single Entry PHRUL 57UL2 octets, fixedPHR triggered while only one serving cell has uplink configured TS 38.321 cl. 5.4.6
Multiple Entry PHR (1-octet Ci)UL 56ULVariablePHR with multiplePHR = true and no serving cell index above 7
Multiple Entry PHR (4-octet Ci)UL 54ULVariablePHR with a serving cell index above 7 to report
Recommended bit rate queryUL 53UL2 octets, fixedThe UE asks the network for a bit rate on one logical channel, gated by bitRateQueryProhibitTimer

Table 8. Reporting CEs. All of these are covered in depth in the companion 10 BSR, PHR, SR document, including the buffer size and power headroom quantisation tables.

10.3 Timing, sleep and carrier control

MAC CELCIDDirSizeWhat triggers it
Timing Advance CommandDL 61DL1 octet, fixedThe gNB has measured a timing error on a Timing Advance Group and issues a relative correction. Restarts timeAlignmentTimer TS 38.321 cl. 5.2
DRX CommandDL 60DL0 octetsThe gNB has nothing more for this UE in this on-duration and sends it to short DRX (or long, if short is not configured) TS 38.321 cl. 5.7
Long DRX CommandDL 59DL0 octetsAs above but forces the long cycle directly, skipping short DRX
SCell Activation/Deactivation (1 octet)DL 58DL1 octet, fixedCarrier aggregation state change for serving cell indices 1-7 TS 38.321 cl. 5.9
SCell Activation/Deactivation (4 octets)DL 57DL4 octets, fixedAs above, reaching indices 1-31
Enhanced SCell Activation/DeactivationeLCIDDLVariableRel-17: activation that also carries the TCI state to use, cutting activation delay
Duplication Activation/DeactivationDL 56DL1 octet, fixedTurns PDCP duplication on or off per DRB without an RRC reconfiguration
Duplication RLC Activation/DeactivationeLCIDDLVariableRel-16: same at the granularity of an individual RLC leg
Recommended bit rateDL 47DL2 octets, fixedThe network suggests a bit rate for one logical channel -- typically an answer to a query, used for rate-adaptive voice and video codecs

Table 9. Timing, DRX and carrier CEs. See the companion 04 Timing Advance and 11 DRX documents for the procedures these drive.

10.4 Beam, CSI and SRS control

MAC CELCIDDirSizeWhat it does
TCI States Activation/Deactivation for UE-specific PDSCHDL 53DLVariableSelects which of up to 128 configured TCI states are active -- DCI then picks one of up to 8 active states with 3 bits
TCI State Indication for UE-specific PDCCHDL 52DL2 octets, fixedNames the single TCI state for one CORESET. There is no DCI-level choice for control, so this CE is the beam decision
Aperiodic CSI Trigger State SubselectionDL 54DLVariableNarrows the aperiodic CSI trigger state list so the DCI CSI request field can address it
SP CSI reporting on PUCCH Activation/DeactivationDL 51DL2 octets, fixedStarts or stops a semi-persistent CSI report on PUCCH
SP CSI-RS / CSI-IM Resource Set Activation/DeactivationDL 55DLVariableStarts or stops the reference signals a SP CSI report measures on
SP ZP CSI-RS Resource Set Activation/DeactivationDL 48DL2 octets, fixedActivates zero-power CSI-RS -- REs the UE must treat as muted, used to protect another cell's CSI-RS
SP SRS Activation/DeactivationDL 50DLVariableStarts or stops semi-persistent SRS, and carries the spatial relation for each resource in the set
PUCCH spatial relation Activation/DeactivationDL 49DL3 octets, fixedSelects the beam for one PUCCH resource
Unified TCI States Activation/DeactivationeLCIDDLVariableRel-17: one joint or separate DL/UL TCI indication for the whole cell

Table 10. Beam and CSI CEs. Note the split of labour: for data, the CE activates a candidate set and DCI chooses; for control, the CE chooses outright. That is why a PDCCH beam change is a MAC round trip and a PDSCH beam change is not.

10.5 Failure recovery and channel access

MAC CELCIDDirSizeWhat triggers it
BFRUL 50ULVariableRel-16: beam failure detected on one or more SCells. Reports which cells failed and, per cell, a candidate beam if one was found above rsrp-ThresholdBFR TS 38.321 cl. 5.17
Truncated BFRUL 51ULVariableSame event, but the grant or padding cannot hold every candidate octet
Enhanced BFR / Enhanced Truncated BFReLCIDULVariableRel-17: per-TRP reporting, for a UE with two CORESET pools
LBT failure (1 octet / 4 octets)UL 49 / 48ULFixedRel-16 NR-U: consistent listen-before-talk failure on one or more cells. A channel-access failure, not a radio failure
Desired Guard SymbolseLCIDULVariableRel-16 IAB: the MT asks the parent for more switching time
Provided Guard SymbolseLCIDDLVariableRel-16 IAB: the parent tells the MT what it will actually get

Table 11. Recovery CEs, all post-Rel-15. Beam failure on the SpCell is not reported this way -- it uses Random Access. See the companion 12 Beam Failure Recovery document.

💡
Key Point

Beam failure recovery is split across two mechanisms and the split is a frequent source of confusion. SpCell beam failure triggers a contention-free Random Access on the candidate beam -- there is no CE, because the UE has no working control channel to send one on. SCell beam failure sends a BFR MAC CE on the SpCell, because the SpCell is still up. If you see BFR MAC CEs, the UE's primary link is healthy.

11. Bit Layouts of the CEs You Will Actually Meet

Five figures, covering the control elements that appear in ordinary traffic. The rest follow the same conventions: reserved bits are zero, multi-bit fields are big-endian within and across octets, and bitmaps index from bit 0 upward.

11.1 The small fixed-size CEs

The Small Fixed-Size Control Elements, Bit by BitThe Small Fixed-Size Control Elements, Bit by BitTS 38.321 cl. 6.1.3.4, 6.1.3.3, 6.1.3.2, 6.1.3.5/6/7. Rows are numbered continuously; each CE restarts at its own octet 1bit76543210Oct 1TAG ID = 0Timing Advance Command = 35 (DL LCID 61, 1 octet)Oct 2UE Contention Resolution Identity, octet 1 of 6Oct 3... 48 bits echoing the MSG3 CCCH SDU ... (DL LCID 62)Oct 4C-RNTI, most significant octet = 0x4COct 5C-RNTI, least significant octet = 0x0D (UL LCID 58, 2 octets)Oct 6DRX (59/60), CG Confirmation (UL 55): zero-length CE, no octet at allThree of the most consequential control elements in NR carry no bits at all: DRX Command, Long DRX Command andConfigured Grant Confirmation are pure codepoints. Their subheader is the entire message, one octet on the wire.
Figure 5. Timing Advance Command, UE Contention Resolution Identity, C-RNTI, and the zero-length CEs. The TA Command CE has no reserved bits at all -- both spare bit positions went to the TAG identity.
FieldCEBitsRangeMeaning
TAG IDTiming Advance Command20 – 3Which Timing Advance Group this correction applies to. 0 is the primary TAG
Timing Advance CommandTiming Advance Command60 – 63Relative adjustment, not absolute: 31 means no change, and N_TA,new = N_TA,old + (value − 31) × 16 × 64 / 2^mu in T_c units TS 38.213 cl. 4.2
UE Contention Resolution Identity--48anyThe first 48 bits of the CCCH SDU the UE sent in MSG3, echoed verbatim
C-RNTIC-RNTI CE160x0001 – 0xFFEFThe UE's existing C-RNTI, sent in MSG3 to identify itself without contention resolution

Table 12. Fields of the small fixed-size CEs. The 31-is-zero encoding of the TA command is the most commonly mis-read field in MAC: a logged value of 31 is not a missing command.

🧮
Worked Calculation

Reading a relative TA command. A Timing Advance Command MAC CE with value 35, at 30 kHz SCS (mu = 1):

delta = (35 − 31) = +4 steps

step = 16 × 64 / 2^1 = 512 T_c, and T_c = 1/(480000 × 4096) s ≈ 0.509 ns

shift = 4 × 512 × 0.509 ns ≈ 1.04 us of additional advance

In distance that is about 156 m of extra one-way path -- the UE moved away, or the propagation path changed. Compare with the absolute 12-bit command in the RAR, which is a completely different encoding: see the companion 04 Timing Advance document.

11.2 SCell Activation/Deactivation

SCell Activation/Deactivation: One Octet and Four OctetsSCell Activation/Deactivation: One Octet and Four OctetsTS 38.321 cl. 6.1.3.10. Oct 1 is the whole one-octet form (LCID 58); Oct 2-5 are the four-octet form (LCID 57). Ci = 1 activate, Ci = 0 deactivatebit76543210Oct 1C7=0C6=0C5=0C4=0C3=0C2=1C1=1ROct 2one-octet form: C1 .. C7 reach ServCellIndex 1..7 onlyOct 3C7C6C5C4C3C2C1ROct 4C15 C14 C13 C12 C11 C10 C9 C8Oct 5C23 C22 C21 C20 C19 C18 C17 C16Oct 6C31 C30 C29 C28 C27 C26 C25 C24 -- four-octet form ends hereThe bitmap is absolute, not incremental: every activated SCell must have its bit set in every CE, so a CE that omits abit deactivates that cell. Which form the gNB uses is a choice about the highest ServCellIndex to be addressed, notabout how many SCells are changing -- one SCell at index 12 forces the four-octet form. There is no C0: the SpCell is always active.
Figure 6. Both forms. The bitmap is absolute, not incremental: every activated SCell must have its bit set in every CE, or it is being deactivated.
⚠️
Common Pitfall

The SCell Activation/Deactivation CE is a complete state statement, not a delta. A gNB that wants to add SCell 3 to a UE already running SCells 1 and 2 must send a CE with C1 = C2 = C3 = 1. Sending C3 = 1 alone deactivates 1 and 2. In logs this appears as SCells mysteriously dropping when another is added, and the throughput signature -- a step down at the moment a carrier was supposedly added -- is unmistakable once you know to look for it.

11.3 The two TCI control elements

The Two TCI Control Elements: Beam for Data, Beam for ControlThe Two TCI Control Elements: Beam for Data, Beam for ControlTS 38.321 cl. 6.1.3.14 and 6.1.3.15Oct 1-3: TCI States Activation/Deactivation for UE-specific PDSCH, DL LCID 53, variable size. Oct 4-5: TCI State Indication for PDCCH, DL LCID 52, 2 octetsbit76543210Oct 1RServing Cell ID = 0BWP ID = 1Oct 2T7T6T5T4T3=1T2T1=1T0Oct 3T15 .. T8 -- up to 16 such octets, one bit per TCI state 0..127Oct 4Serving Cell ID = 0CORESET ID (3 MSB)Oct 5CORESETID LSBTCI State ID = 9 (0 .. 127)The PDSCH CE activates a *candidate set* that DCI then selects from; the PDCCH CE names *the* beam for one CORESEToutright. Note the 4-bit CORESET ID straddling the octet boundary -- a classic hand-decoding error.
Figure 7. Beam control for data and for control. The 4-bit CORESET ID straddles the octet boundary of the PDCCH CE; hand-decoding it as two separate nibbles is a standard mistake.

11.4 BFR and Truncated BFR

BFR and Truncated BFR: Reporting Beam Failure per Serving CellBFR and Truncated BFR: Reporting Beam Failure per Serving CellTS 38.321 cl. 6.1.3.22 / 6.1.3.23 (Rel-16). Oct 1-3 are one BFR MAC CE, UL LCID 50: a bitmap then one octet per cell with Ci = 1, in ascending ServCellIndex orderbit76543210Oct 1SP=0C7=0C6=0C5=0C4=1C3=0C2=1C1=0Oct 2AC=1Candidate RS Index = 12 (for SCell 2)ROct 3AC=0no candidate found -- field ignored (for SCell 4)ROct 4Truncated BFR (UL LCID 51): same bitmap, only as many candidate octets as fitSP is the SpCell bit. AC = 0 means the UE detected failure but found no candidate above the threshold -- which is amaterially different report from AC = 1 and should never be read as the same event.
Figure 8. SCell beam failure reporting. The AC bit distinguishes "failed, here is where to go" from "failed, and I have nowhere to go" -- operationally two very different reports.

11.5 Multiple Entry PHR

The Multiple Entry PHR is the most structurally complicated CE in NR: a bitmap of one or four octets, then one or two octets per reported entry depending on a bit inside the entry itself. Its layout, the PH and P_CMAX,f,c encodings and the virtual-versus-real distinction are covered in full in the companion 10 BSR, PHR, SR document, which also gives the Single Entry PHR layout.

12. What Each CE Tells You When You See It in a Log

A control element in a trace is evidence about state you cannot see directly. This table is the inference, not the definition.

When you see this CEIt tells youAnd the next thing to check
UE Contention Resolution Identity (DL 62)A contention-based RACH reached MSG4. The UE had no C-RNTI, so this was initial access, re-establishment or resumeWhether the echoed 48 bits match the UE's own MSG3. A mismatch is a lost contention, not a failure
C-RNTI CE (UL 58)A RACH from a UE that already had a context -- handover, timing recovery after timeAlignmentTimer expiry, or an SR that ran out of attemptsWhat was running just before: T304 means handover, no timer means TA recovery or SR fallback
Timing Advance Command (DL 61)The gNB measured an uplink timing error worth correcting on that TAGThe magnitude of (value − 31). A steady drip of ±1 is a healthy control loop; a sudden ±20 means the path changed
Short BSR with buffer size 0The UE has just emptied that LCG. This is the end-of-burst markerThat the network stops granting shortly after. Continued grants mean the BSR was not processed
Long BSR appearing where Short BSRs were normalA second LCG became active -- a new bearer started carrying dataWhich LCG appeared, and whether its logicalChannelGroup assignment matches the intent
Short/Long Truncated BSRThe UE wanted to report more than the available space allowed. Not an error -- but the report is incompleteWhether truncation is chronic. Persistent truncation means grants are consistently too tight for the number of active LCGs
Single Entry PHR with a low headroom valueThe UE is near its power ceiling on that carrierWhether the scheduler reduced MCS or PRB count in response. If not, expect uplink HARQ failures
Multiple Entry PHR where Single Entry was normalmultiplePHR was configured, or a second uplink carrier was activatedThe V bits: a virtual entry means the UE was not actually transmitting on that carrier and the number is a calculation, not a measurement
DRX Command (DL 60) / Long DRX Command (DL 59)The scheduler explicitly released the UE early rather than letting drx-InactivityTimer run outHow much of the inactivity timer was left. Frequent early release is a sign the timer is configured too long for the traffic
SCell Activation/Deactivation (DL 57/58)A carrier aggregation state change. Read the whole bitmap, not just the changed bitThe activation delay that follows -- the SCell is not usable immediately TS 38.133 cl. 8.3
Duplication Activation/Deactivation (DL 56)PDCP duplication was switched for at least one DRB, usually in response to a measurement or a reliability targetWhether both legs actually carry traffic afterwards. Duplication activated on a leg with no grant is invisible reliability
BFR / Truncated BFR (UL 50/51)One or more SCells lost their beam, and the SpCell is still healthyThe AC bit. AC = 0 on every entry means the UE has no candidate at all, which usually precedes SCell release
LBT failure CE (UL 48/49)NR-U only: the UE could not get channel access, repeatedly. Nothing is wrong with the radio linkThe unlicensed channel occupancy, not the UE. This is an interference or coexistence question
Configured Grant Confirmation (UL 55)The UE accepted a Type 2 configured grant activation or releaseThat the confirmation arrived at all. A missing one means the network and UE disagree about whether the grant is live
Recommended bit rate query (UL 53) / Recommended bit rate (DL 47)An adaptive codec is negotiating rate with the network at MAC speed instead of via the applicationWhether the queries are being answered. Unanswered queries usually mean the feature is unsupported at the gNB

Table 13. Inference table. Every row here is something you can conclude from the presence of a control element without any other information in the log.

13. What Control Costs: Overhead Arithmetic

What a Control Element Costs on the WireWhat a Control Element Costs on the WireFixed-size CEs use a 1-octet subheader; variable-size CEs pay an extra octet for L012345678DRX Command1Short BSR2TA Command2C-RNTI3SCell A/D (1 oct)2Single Entry PHR3SCell A/D (4 oct)5Long BSR, 4 LCGs7UE Cont. Res. Identity7ME PHR, 4 cells8Octets on the wireThe absolute numbers are small; what matters is the ratio. On a 40-octet transport block a Long BSR plus an ME PHRis 15 octets of overhead -- more than a third of the grant spent on reports rather than data.
Figure 9. Octets consumed by each common control element, subheader included. The absolute numbers are small; what matters is the ratio to the grant they land in.
🧮
Worked Calculation

A small uplink grant, fully accounted. The UE sent a Scheduling Request; the gNB replies with a conservative grant. Transport block = 56 octets TS 38.214 Table 5.1.3.2-1.

Pending: a Regular BSR (3 LCGs with data) and a PHR (2 activated carriers), plus 200 octets of DTCH data.

Long BSR ....... subheader 2 + bitmap 1 + 3 buffer sizes = 6 octets

ME PHR ......... subheader 2 + bitmap 1 + 2 entries x 2 = 7 octets

-------------------------------------------------

Control total ................................. 13 octets (23%)

Left for the DTCH subPDU ...................... 43 octets

minus its own 2-octet subheader ............. 41 octets of data

So 20% of the UE's 200-octet burst goes out in a grant that spent a quarter of itself on reports. Repeat that at a 56-octet grant size and the burst takes five round trips instead of two. This is the whole argument for granting generously once after an SR rather than conservatively several times -- see the companion 08 Scheduling document.

Transport blockControl carriedControl octetsFractionPractical consequence
24 octetsShort BSR only28%Fine. The typical padding-BSR case
56 octetsLong BSR + ME PHR1323%Bad. Grant is too small for a UE that has just asked for capacity
309 octetsLong BSR + ME PHR134%Negligible. This is where reports should live
1544 octetsLong BSR + ME PHR + 2 SDUs171%Invisible
56 octetsTA Command + DRX Command (DL)35%Fine, but note both are 1-octet-payload CEs and still cost a subheader each

Table 14. Control overhead against transport block size. Transport block sizes are illustrative values from the TBS table for common PRB/MCS combinations.

The design consequence runs the other way too. Because a fixed-size CE costs exactly one subheader octet and no length field, the marginal cost of adding MAC signalling to NR was almost zero, and that is why so many features that could have been RRC procedures were built as control elements instead. A beam switch that would take an RRCReconfiguration round trip -- tens of milliseconds, an ASN.1 encode and decode, and an acknowledgement -- takes 2 octets and one slot as a MAC CE.

14. Failure Modes and What Each One Means

FailureDetected byWhat happensDiagnostic pointer
Unknown fixed-size LCIDReceiving MAC, at parse timeThe rest of the transport block is discarded. In the downlink that usually means the SDUs too, since CEs come firstA release or vendor mismatch. Check the UE capability exchange against the CEs the gNB is emitting; check whether the decoder knows the Rel-16 escapes (§6)
Unknown variable-size LCIDReceiving MACThat one subPDU is discarded; L lets the parse continueUsually a logical channel configured on one side only. Compare the LCIDs in PDUs against RLC-BearerConfig
LCID decoded with the wrong direction tableNobody -- it parses cleanlyA Short BSR becomes a Long DRX Command, or a Long BSR becomes a UE Contention Resolution IdentityImpossible-looking CEs in the wrong direction. If a UE 'sent' a DRX Command, this is what happened
L field runs past the end of the transport blockReceiving MACPDU discardedThe parse went wrong earlier. Look at the previous subPDU, not this one
Padding subheader not lastNobody -- everything after it is unreachable by definitionThe subPDUs after the padding subheader are silently lostA transmitter bug. The symptom is data or CEs that the sender logs and the receiver never sees, with no error on either side
MAC CE emitted before SDUs in the uplinkNobody -- it is a transmitter obligation onlyThe BSR describes a buffer that still includes the data in this very PDUChronically over-sized grants and a buffer report that never quite reaches zero
Fixed-size CE truncated by the transport blockReceiving MAC, or nobodyShould not happen -- the transmitter must not start a CE it cannot finish. If it does, the receiver reads past the endA TBS accounting bug in the transmitter. Correlate the sum of subPDU sizes against the TBS the DCI granted
SCell Activation CE read as a delta rather than a stateNobody at MAC level; the throughput drop is the only symptomPreviously active SCells deactivateA carrier count that falls when a carrier is added (§11.2)
Zero-length CE dropped by a log filterNobodyThe CE was sent and acted on, but does not appear in any byte-count view of the traceDRX Command, Long DRX Command, Configured Grant Confirmation. Search for the subheader octet, not for a CE payload
Transport block CRC passes but MAC decode failsReceiving MACPDU discarded, no HARQ retransmission is requested -- HARQ already succeededThe most diagnostic combination in this document: healthy HARQ plus failing MAC decode means a codepoint or format problem, never a radio problem

Table 15. MAC PDU failure modes. Note how many are detected by nobody: MAC has no error reporting toward its peer, so a malformed PDU produces missing behaviour rather than an error message.

💡
Key Point

The single most useful diagnostic in this whole document: compare the sum of the subPDU sizes against the transport block size from the DCI. If they do not agree, the decode is wrong -- and whichever subPDU the shortfall begins at is where it went wrong. This one check separates "my decoder is confused" from "the network really did that", and it takes ten seconds.

15. Where the Configuration Comes From

MAC PDU format is not configurable -- it is fixed by the spec. What is configurable is which control elements are enabled, which logical channel identities exist, and the timers that make CEs fire. Those live in MAC-CellGroupConfig and RLC-BearerConfig inside the cell group configuration TS 38.331.

MAC-CellGroupConfig ::= SEQUENCE {
    drx-Config                 SetupRelease { DRX-Config }      OPTIONAL,
    schedulingRequestConfig    SchedulingRequestConfig          OPTIONAL,
    bsr-Config                 BSR-Config                       OPTIONAL,
    tag-Config                 TAG-Config                       OPTIONAL,
    phr-Config                 SetupRelease { PHR-Config }      OPTIONAL,
    skipUplinkTxDynamic        BOOLEAN,
    ...,
    [[ csi-Mask                BOOLEAN                          OPTIONAL,
       dataInactivityTimer     SetupRelease { DataInactivityTimer } OPTIONAL ]],
    [[ usePreBSR-r16           ENUMERATED {true}                OPTIONAL,
       schedulingRequestID-LBT-SCell-r16 SchedulingRequestId     OPTIONAL,
       lch-BasedPrioritization-r16       ENUMERATED {enabled}    OPTIONAL,
       schedulingRequestID-BFR-SCell-r16 SchedulingRequestId     OPTIONAL ]],
    ...
}

RLC-BearerConfig ::= SEQUENCE {
    logicalChannelIdentity           LogicalChannelIdentity,  -- INTEGER (1..32)
    servedRadioBearer                CHOICE {
        srb-Identity                     SRB-Identity,
        drb-Identity                     DRB-Identity
    }                                                          OPTIONAL,
    reestablishRLC                   ENUMERATED {true}         OPTIONAL,
    rlc-Config                       SetupRelease { RLC-Config } OPTIONAL,
    mac-LogicalChannelConfig         SetupRelease { LogicalChannelConfig } OPTIONAL,
    ...
}

TAG-Config ::= SEQUENCE {
    tag-ToReleaseList  SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG-Id  OPTIONAL,
    tag-ToAddModList   SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG     OPTIONAL
}

TAG ::= SEQUENCE {
    tag-Id                 TAG-Id,        -- INTEGER (0..3), the TAG ID field
    timeAlignmentTimer     TimeAlignmentTimer,
    ...
}

Listing 1. Abridged from TS 38.331. ... marks omitted fields and extension markers. maxNrofTAGs is 4, which is why the TAG ID field in the Timing Advance Command CE is exactly 2 bits.

ParameterWhereRangeTypicalEffect on the PDU
logicalChannelIdentity
RLC-BearerConfig
1 – 321-3 for SRBs, 4+ for DRBsBecomes the LCID in every subheader for that bearer
logicalChannelGroup
LogicalChannelConfig
0 – 70-3Decides which LCG a channel's data is reported under in a BSR, and hence whether a Short or Long BSR is used
multiplePHR
PHR-Config
true / falsetrue with CAChooses between LCID 57 and LCID 54/56 for power headroom
tag-Id
TAG-Config
0 – 30 only, unless CA with mixed geographyThe TAG ID field of the Timing Advance Command CE
drx-Config
MAC-CellGroupConfig
SetupReleaseconfiguredWithout it, a DRX Command CE is meaningless and the UE will ignore it
usePreBSR
MAC-CellGroupConfig
true / absentabsentRel-16. Enables the Pre-emptive BSR CE, and with it the uplink ordering exception in §7
lch-BasedPrioritization
MAC-CellGroupConfig
enabled / absentabsent unless URLLCRel-16 intra-UE prioritisation; changes which subPDUs get built at all. See the companion 09 LCP document
skipUplinkTxDynamic
MAC-CellGroupConfig
true / falsetrueLets the UE drop a grant it would otherwise fill entirely with padding -- directly reduces the number of padding-only PDUs you will see

Table 16. Configuration that changes what a MAC PDU looks like on the wire.

16. Illustrative Message Traces

🔍
About These Traces

Illustrative trace. Field names and encodings follow 3GPP; the values are constructed for this document and are not a capture from any deployed or lab network.

16.1 A five-subPDU downlink MAC PDU, octet by octet

One 64-Octet DL MAC PDU, Byte by ByteOne 64-Octet DL MAC PDU, Byte by ByteFive subPDUs: two fixed-size CEs, one 2-octet beam CE, two SDUs, then padding. C-RNTI 0x4C0D throughout this document3D233A06340089011602221C40038F21005AC418000E60B20744912A00D36C041A800C450000349A11400040061B2EC0A80A050D501F9000502C8E3F0000000008162432404856+0+1+2+3+4+5+6+7Octet offset within the rowTransport block offsetTA Command CESCell A/D CETCI-PDCCH CEDCCH subPDUDTCH subPDUPaddingReading the byte map and the companion listing together is the fastest way to learn the parse: every subPDUboundary above is a place where the previous L field, or the absence of one, told the receiver where to stop.
Figure 10. The transport block the next listing decodes. Reading the byte map and the listing together is the fastest way to internalise the subPDU boundaries.
[MAC-DL] a complete downlink MAC PDU
09:41:18.204  [MAC-DL] PDSCH, C-RNTI 0x4C0D, TBS 64 octets, HARQ pid 3, NDI 1

  off  hex   binary      decode
  ---  ---   --------    --------------------------------------------------
  0    3D    0011 1101   R=0 R=0 LCID=61   -> Timing Advance Command, fixed 1 oct
  1    23    0010 0011   TAG ID=0  TA Command=35   -> +4 steps, ~1.04 us at 30 kHz
  2    3A    0011 1010   R=0 R=0 LCID=58   -> SCell Activation/Deactivation, 1 oct
  3    06    0000 0110   C7..C1 = 0000011, R=0   -> SCell 1 and SCell 2 ACTIVE,
                                                    SCells 3..7 DEACTIVE
  4    34    0011 0100   R=0 R=0 LCID=52   -> TCI State Indication for UE-specific
                                               PDCCH, fixed 2 oct
  5    00    0000 0000   ServingCellId=0  CORESET ID bits 3..1 = 000
  6    89    1000 1001   CORESET ID bit 0 = 1 -> CORESET 1;  TCI State ID = 9
  7    01    0000 0001   R=0 F=0 LCID=1    -> DCCH (SRB1), 8-bit length follows
  8    16    0001 0110   L = 22 octets
  9-30 ..    (22 octets) RLC AM PDU -> PDCP -> RRCReconfiguration segment
  31   04    0000 0100   R=0 F=0 LCID=4    -> DTCH (DRB1), 8-bit length follows
  32   1A    0001 1010   L = 26 octets
  33-58 ..   (26 octets) RLC AM PDU -> PDCP -> SDAP -> IP
  59   3F    0011 1111   R=0 R=0 LCID=63   -> Padding, to end of transport block
  60-63 00   (4 octets)  padding

  accounting: 2 + 2 + 3 + 24 + 28 + 5 = 64 octets = TBS         [consistent]

09:41:18.204  [MAC] applied TA +4 on TAG 0, restarted timeAlignmentTimer
09:41:18.204  [MAC] SCell 1, SCell 2 -> activated; activation delay pending
09:41:18.204  [MAC] CORESET 1 TCI state -> 9
09:41:18.205  [RLC] DCCH SDU (22) and DTCH SDU (26) delivered upward

Listing 2. Three control elements and two SDUs in one 64-octet block. Note the accounting line: 64 octets of subPDU against a 64-octet TBS is the check described in §14.

🔍
What You See In Logs

Three separate state changes -- uplink timing, carrier aggregation and the PDCCH beam -- travelled in seven octets, ahead of the data, in a transport block whose main purpose was to carry an RRCReconfiguration fragment. Reconstructing this sequence from RRC messages alone would show none of it. This is why MAC-level tracing matters even when the question looks like an RRC question.

16.2 An uplink MAC PDU: data, a BSR, and padding

[MAC-UL] SDU + BSR + padding
09:41:22.617  [MAC-UL] grant from DCI 0_1: TBS 68 octets, C-RNTI 0x4C0D,
                       HARQ pid 5, k2 = 4, PUSCH slot 1082.7
09:41:22.617  [MAC]    LCP: Regular BSR pending (triggered 09:41:22.611)
                       DTCH LCID 4: 812 octets available
                       DCCH LCID 1: 0 octets

  off  hex   binary      decode
  ---  ---   --------    --------------------------------------------------
  0    04    0000 0100   R=0 F=0 LCID=4    -> DTCH (DRB1), 8-bit length
  1    3E    0011 1110   L = 62 octets
  2-63 ..    (62 octets) RLC AM PDU, SO=0, 62-octet segment of a 812-octet SDU
  64   3D    0011 1101   R=0 R=0 LCID=61   -> Short BSR, fixed 1 oct
  65   4F    0100 1111   LCG ID=2  Buffer Size index=15  -> > 745 and <= 1038 oct
  66   3F    0011 1111   R=0 R=0 LCID=63   -> Padding
  67   00    0000 0000   1 padding octet

  accounting: 64 + 2 + 2 = 68 octets = TBS                      [consistent]

09:41:22.617  [MAC]    BSR sent -> cancel triggered BSR, restart periodicBSR-Timer
                       (812 - 62 = 750 octets still queued on LCG 2)
                       -- 750 falls in 5-bit level 15, whose range is 746 .. 1038.
                       -- Level 14 (536 .. 745) would UNDER-state it by 5 octets, so
                       -- the UE reports 15 and the gNB learns only 746 <= BS <= 1038.
09:41:22.617  [MAC]    retxBSR-Timer restarted on grant reception

Listing 3. One SDU, one Regular BSR, one octet of padding, exactly filling a 68-octet grant. The uplink order -- SDU first, CE second -- is what makes the reported buffer size describe the queue after this PDU.

⚠️
Common Pitfall

Look at the buffer size reasoning in that trace. The UE has 750 octets queued and reports 5-bit level 15, whose range is 746 .. 1038 octets. The gNB now knows the queue to within 293 octets -- a 39% uncertainty. At level 25 the bucket is over 8 kB wide. A BSR is a bucket, never a byte count, and a scheduler that grants exactly the reported level will over-grant most of the time by construction. The full quantisation table and the 8-bit alternative are in the companion 10 BSR, PHR, SR document.

16.3 An extended-LCID control element

[MAC-DL] eLCID escape, and what happens without it
09:44:03.881  [MAC-DL] PDSCH, C-RNTI 0x4C0D, TBS 16 octets, HARQ pid 1

  off  hex   binary      decode
  ---  ---   --------    --------------------------------------------------
  0    22    0010 0010   R=0 R=0 LCID=34   -> one-octet eLCID escape
  1    E6    1110 0110   eLCID = 230  ->  codepoint 64 + 230 = 294
                         -- this decoder's Rel-17 table resolves 294 to
                         -- Enhanced SCell Activation/Deactivation, 1-octet Ci
  2    06    0000 0110   C7..C1 = 0000011, R=0   -> activate SCell 1, SCell 2
  3    80    1000 0000   entry for SCell 1: TCI state field present, id = 0
  4    82    1000 0010   entry for SCell 2: TCI state field present, id = 2
  5    3F    0011 1111   R=0 R=0 LCID=63   -> Padding
  6-15 00    (10 octets) padding

  accounting: 5 + 11 = 16 octets = TBS                          [consistent]

-- The same event through a decoder that predates the escape:

  0    22    0010 0010   R=0 F=0 LCID=34   *** RESERVED ***
                         decoder assumes shape A and reads the next octet as L
  1    E6                L = 230 octets  -- but only 14 octets remain in the TB
  --   ---   PDU DISCARDED: length exceeds transport block
  -- The SCells are never activated. Nothing is logged as an error on either
  -- side. The gNB's scheduler proceeds as if two carriers are live.

Listing 4. An extended-LCID CE decoded correctly, then the same octets through a decoder that does not know LCID 34. The failure is total and silent.

16.4 A failure: unknown fixed-size codepoint mid-PDU

[MAC-DL] unknown fixed-size LCID
09:52:47.115  [MAC-DL] PDSCH, C-RNTI 0x4C0D, TBS 96 octets, HARQ pid 7
              CRC ....................... PASS      -- HARQ succeeded

  off  hex   binary      decode
  ---  ---   --------    --------------------------------------------------
  0    3D    0011 1101   R=0 R=0 LCID=61   -> Timing Advance Command
  1    21    0010 0001   TAG ID=0  TA Command=33   -> +2 steps        [applied]
  2    31    0011 0001   R=0 R=0 LCID=49   -> PUCCH spatial relation
                                               Activation/Deactivation
                         *** codepoint not supported by this UE release ***
                         *** fixed-size CE: length is not on the wire   ***
  --   ---   MAC: cannot determine subPDU length -> discard remainder of TB
  --   ---   octets 3..95 (93 octets) LOST, including:
  --   ---     one DCCH subPDU  (RRCReconfiguration, 40 octets)
  --   ---     one DTCH subPDU  (48 octets)

09:52:47.115  [MAC]    no HARQ retransmission requested -- CRC passed
09:52:47.115  [RLC-DL] no SDU delivered
09:52:52.115  [RLC-DL] t-Reassembly expired, gap at SN 1204 -> STATUS PDU (NACK)
09:52:52.117  [RRC]    T310 not started; RRCReconfiguration never arrived
09:53:07.118  [RRC]    RRCReconfiguration not completed -> reconfiguration failure

Listing 5. One unsupported control element costs 93 octets, an RRCReconfiguration and, five seconds later, an RLC status report that looks like a radio problem. The CRC passed.

🔍
What You See In Logs

The give-away in that trace is the combination of CRC PASS with a missing SDU and no HARQ retransmission. If HARQ had failed, the block would have been retransmitted and the RRC message would have arrived late rather than never. A CRC pass followed by silence upward is a MAC parse failure, and the octet where it happened is in the log. Nothing about the radio needs investigating.

17. Release Deltas: Rel-15 to Rel-18

ReleaseChangeWhy it matters when reading MAC PDUs
Rel-15The subPDU model, four subheader shapes, both 64-codepoint LCID tables, and 24 control elementsEverything in §2-§5 and most of §10. If a decoder handles Rel-15 correctly it will parse the great majority of real traffic
Rel-16eLCID escapes at LCID 33 and 34, opening codepoints 64 .. 65 855The single most consequential format change since Rel-15. A decoder without it desynchronises on the first extended CE (§6, §16.3)
Rel-16SCell beam failure recovery: BFR and Truncated BFR CEs at UL LCID 50/51Beam failure becomes visible as a control element rather than only as a Random Access
Rel-16NR-U: LBT failure CEs at UL LCID 48/49A new class of uplink failure that is not a radio problem at all
Rel-16NR sidelink: Sidelink BSR and Truncated Sidelink BSR at UL LCID 45/46Uplink codepoints 45-51 stop being reserved. A Rel-15 decoder will call them reserved and desynchronise on the fixed-size ones
Rel-16IAB: Pre-emptive BSR (UL 47), Desired and Provided Guard Symbols, and the uplink ordering exception for Pre-emptive BSRThe first and only exception to "uplink CEs come after SDUs" (§7)
Rel-16Duplication RLC Activation/Deactivation, and Multiple Entry Configured Grant Confirmation, both in the extended spaceDuplication control moves from per-DRB to per-leg; configured grants become plural
Rel-16Type 3 power headroom (SRS-based) in the PHR CEsA PHR entry can now describe an SRS-only carrier. Check the entry type before reading the number
Rel-17Unified TCI and enhanced TCI CEs; Enhanced SCell Activation/Deactivation carrying a TCI stateActivation and beam selection merge into one CE, shortening SCell activation delay measurably
Rel-17Enhanced BFR and Enhanced Truncated BFR for per-TRP reportingWith two CORESET pools, "beam failure" is no longer one event per cell
Rel-17Positioning: SP Positioning SRS Activation/Deactivation and Positioning Measurement Gap Activation/DeactivationMeasurement gaps can now open and close without an RRC round trip
Rel-17IAB timing case CEs and Desired IAB-DU TX Power AdjustmentIAB nodes negotiate timing and power at MAC speed
Rel-18Further extended-space additions for network-controlled repeaters, multi-carrier and energy-saving features; no change to the subPDU or subheader modelThe format has been stable since Rel-16. New CEs appear only as new codepoints in the extended space -- which is exactly what the escape was built for

Table 17. MAC PDU and CE changes by release. Feature presence should always be confirmed against the UE capability exchange -- see the companion 26 UE Capability document.

🔄
Release Delta

There have been exactly two wire-format changes to the MAC PDU since Rel-15, and both are in Rel-16: the eLCID escapes, and the Pre-emptive BSR ordering exception. Everything else is new codepoints. That stability is the whole point of a self-describing subPDU: adding a control element does not touch the parser.

18. Reading MAC PDUs in Logs: a Checklist

1. Check the accounting first. Sum every subPDU -- subheaders, payloads, padding -- and compare against the transport block size from the DCI. If they disagree the decode is wrong, and the first subPDU where the running total goes bad is where it broke (§14).

2. Confirm the direction of the codepoint table. LCID 59-62 mean completely different things in each direction and both parse cleanly. If the decode looks impossible -- a UE that sent a DRX Command, a gNB that sent a BSR -- this is why.

3. Read the whole subheader, not just the LCID. The F bit only exists in shapes A and B. If your tool prints an F bit for a fixed-size CE, it is printing a reserved bit and you should not trust the rest of that line.

4. Look for LCID 33 and 34 before believing anything downstream. One unrecognised escape produces one plausible subPDU followed by nonsense. Check the decoder's spec version against the gNB's release (§6).

5. Verify the ordering. Downlink: CEs, then SDUs, then padding. Uplink: SDUs, then CEs, then padding, with Pre-emptive BSR the one exception. A violation is a transmitter bug that produces no error anywhere (§7).

6. Treat a CRC pass with nothing delivered upward as a MAC problem. No HARQ retransmission plus no SDU means the block decoded and the parse failed. Do not go looking at the radio (§16.4).

7. Read SCell Activation bitmaps in full. They are absolute state, not deltas. Compare against the set of SCells you believe were active before (§11.2).

8. Distinguish 1-octet padding from a padding BSR. If two or more octets of padding remain and no BSR was inserted, either no BSR was pending or the padding-BSR logic is not running -- the second is a real finding (§8).

9. Search for zero-length CEs by their subheader octet. DRX Command (0x3C), Long DRX Command (0x3B) and Configured Grant Confirmation (0x37) have no payload and are invisible to any payload-oriented filter.

10. Correlate every CE you see against the configuration that should have enabled it. A DRX Command to a UE with no drx-Config, a Multiple Entry PHR with multiplePHR absent, or a BFR CE with no schedulingRequestID-BFR-SCell are all configuration mismatches, and all of them look like UE misbehaviour until you check.

19. Glossary

TermExpansionMeaning in this document
MAC PDUProtocol Data UnitThe contents of exactly one transport block on DL-SCH or UL-SCH; a flat sequence of subPDUs with no PDU-level header
subPDU--One subheader plus at most one payload. The only structural unit MAC has
MAC SDUService Data UnitOne RLC PDU handed down for one logical channel. Opaque to MAC
MAC CEControl ElementMAC-generated signalling consumed by the peer MAC entity. No ASN.1, no acknowledgement of its own
LCIDLogical Channel IDThe 6-bit field that identifies what a subPDU contains. Meaningful only together with the direction
eLCIDExtended LCIDThe Rel-16 one- or two-octet field reached through LCID 34 or 33, giving codepoints 64 .. 65 855
L fieldLength8 or 16 bits, present only for variable-size payloads; the F bit says which width
F bitFormatSays whether L is 8 or 16 bits. Does not exist in the 1-octet subheader shapes
R bitReservedSet to zero. Two of them in a 1-octet subheader, one in a 2- or 3-octet subheader
Padding--LCID 63. Means "everything from here to the end of the transport block", so it carries no length and must be last
TAGTiming Advance GroupA set of serving cells sharing one uplink timing correction; the 2-bit TAG ID field addresses up to four
LCGLogical Channel GroupUp to eight groups over which BSR reports buffer occupancy. Set by logicalChannelGroup
TBSTransport Block SizeThe size MAC must fill exactly. Chosen by the scheduler from a table, not by MAC
TCI stateTransmission Configuration Indication stateA beam, expressed as a quasi-colocation relationship to a reference signal. Activated by CE, selected by DCI
BFRBeam Failure RecoveryHere specifically the SCell reporting CE; SpCell recovery uses Random Access instead

20. References

  • 3GPP TS 38.321 -- NR MAC protocol specification. Clause 6.1.2 (MAC PDU for DL-SCH and UL-SCH, subPDU and subheader formats, ordering and padding), 6.1.3 (all MAC CE formats -- 6.1.3.1 BSR, 6.1.3.2 C-RNTI, 6.1.3.3 UE Contention Resolution Identity, 6.1.3.4 Timing Advance Command, 6.1.3.5/6 DRX Commands, 6.1.3.7 Configured Grant Confirmation, 6.1.3.8 Single Entry PHR, 6.1.3.9 Multiple Entry PHR, 6.1.3.10 SCell Activation/Deactivation, 6.1.3.11 Duplication Activation/Deactivation, 6.1.3.14/6.1.3.15 TCI CEs, 6.1.3.20 Recommended bit rate, 6.1.3.22/23 BFR), 6.2.1 (subheader formats), Tables 6.2.1-1 and 6.2.1-2 (LCID values), Tables 6.2.1-1a/-1b and -2a/-2b (eLCID values).
  • 3GPP TS 38.321 -- the procedures that emit the CEs: clause 5.1.4/5.1.5 (Random Access, C-RNTI and Contention Resolution CEs), 5.2 (timing advance), 5.4.3.1 (logical channel prioritisation and CE priority order), 5.4.5 (BSR), 5.4.6 (PHR), 5.7 (DRX), 5.8.2 (configured grant confirmation), 5.9 (SCell activation), 5.17 (SCell beam failure recovery).
  • 3GPP TS 38.331 -- RRC protocol specification. MAC-CellGroupConfig, RLC-BearerConfig, LogicalChannelConfig, TAG-Config, PHR-Config, BSR-Config, DRX-Config.
  • 3GPP TS 38.213 -- Physical layer procedures for control. Clause 4.2 (timing advance application), clause 7.7 (power headroom definitions for Types 1, 2 and 3).
  • 3GPP TS 38.214 -- Physical layer procedures for data. Clause 5.1.3.2 (transport block size determination -- the sizes MAC must fill exactly).
  • 3GPP TS 38.133 -- Requirements for support of radio resource management. Clause 8.3 (SCell activation delay), and the power headroom and P_CMAX reporting ranges.
  • 3GPP TS 38.300 -- NR overall description. Clause 6.2 and 6.4 for where MAC sits and what it is responsible for.

Companion documents in this set

  • 03 Random Access -- the RAR MAC PDU, which uses a different subheader format entirely, and the UE Contention Resolution Identity and C-RNTI CEs in context.
  • 04 Timing Advance -- what the 1-octet relative Timing Advance Command CE does to N_TA, and how it differs from the RAR's absolute command.
  • 05 HARQ -- the transport block and CRC layer beneath everything here; essential for separating radio failures from parse failures.
  • 06 Channel Mapping -- the LCID tables from the channel-mapping angle, and where logical channel identities come from.
  • 08 Scheduling -- who chooses the transport block size MAC has to fill.
  • 09 LCP -- how MAC decides which SDUs and which CEs go into a given grant, and the fixed CE priority order.
  • 10 BSR, PHR, SR -- the BSR and PHR control elements in full, including the buffer size and power headroom quantisation tables.
  • 11 DRX -- what the DRX Command and Long DRX Command CEs actually do.
  • 12 Beam Failure Recovery -- the procedure behind the BFR CE, and the SpCell case that uses RACH instead.
  • 26 UE Capability -- how to establish which control elements a particular UE will accept.