EN-DC SgNB Addition over X2: The Request and Its Acknowledge

Reading two small X2AP-over-SCTP captures that carry the exchange at the heart of 5G Non-Standalone: the SgNB Addition Request, by which an LTE master eNB asks a secondary 5G gNB to stand up an NR data radio bearer for a UE already anchored on LTE — and the Acknowledge with which the gNB replies. Both were decoded and annotated with VisualEther, which turns a Wireshark PCAP into a sequence diagram.

The Request capture — annotated diagrams (the Acknowledge capture's diagrams appear with Act 2 below):

💡 Read the walkthrough and the diagram side by side. Open the interactive diagram (or PDF) in a split-screen window so the captions stay in view as you read. In Edge, Chrome, or Firefox, right-click the link and pick your browser's split-screen option (Edge labels it "Open link in split screen window"). On macOS, prefer Chrome or Firefox — Safari has no in-browser split screen. Otherwise, open the diagram in a new tab and snap the two windows side by side.

Overview

These are two compact 8-frame captures of the X2 interface — the link between two base stations — carrying the two halves of the one X2AP procedure that makes 5G Non-Standalone work: SgNB Addition. An LTE master eNB (MeNB) that already serves a UE reaches out over X2 to a secondary 5G gNB (SgNB) and asks it to allocate NR radio resources for a new data bearer; the gNB replies with what it can allocate. That is how a 4G operator layers 5G throughput onto an existing LTE anchor without a 5G core.

A caveat up front, because it changes how you read every value in both traces. These are synthetic captures — message-builder / conformance traces (every endpoint sits on 127.0.0.1, distinguished only by SCTP port), not live inter-node dialogs. Many payloads are placeholders typical of such tools: an all-zero SgNB security key, 0.0.0.0 / TEID-0 GTP endpoints, UE security capabilities that advertise no standard algorithms, an rlc-Mode of "Unknown", and an empty CG-Config. Read them as a faithful demonstration of the message structure of EN-DC bearer addition — which IEs travel, and what they mean — not as a set of realistic network values. Where a field is a placeholder, this walkthrough indicates as much.

One more caveat that keeps us honest: the two captures are not the two ends of one wire. They come from the same message-builder family but are independent traces — the UE identifiers and E-RAB IDs do not match across them (the Request uses MeNB-UE-X2AP-ID 1 / E-RAB 11; the Acknowledge uses MeNB-UE-X2AP-ID 85 / SgNB-UE-X2AP-ID 102 / E-RAB 119). So read Act 2 as what a matching-shape Acknowledge carries, not as the literal reply to the Act 1 request. That is exactly why this procedure needs two captures to show in full: neither trace carries both directions.

Every step is visible in the packets. In either capture's interactive viewer or HTML sequence diagram, click any message to open its parameter details and the complete Wireshark field tree for that frame.

A primer on EN-DC and X2AP

EN-DC (E-UTRA–NR Dual Connectivity) is the dual-connectivity mode behind 5G Non-Standalone, Option 3. The UE keeps its control-plane anchor on an LTE MeNB (master eNB) connected to the 4G EPC, and gains a second, high-throughput user-plane leg on a 5G SgNB (secondary gNB). The two base stations coordinate over the X2 interface.

PieceRole in one lineWhat you'll see in the trace
MeNBLTE master — owns the UE and its control planeInitiates the association (SCTP port 41471 in the Request capture, 44762 in the Acknowledge); sends the X2 Setup
SgNB5G secondary — adds NR user-plane capacityResponder on SCTP port 62324; returns the Acknowledge (Act 2)
X2APThe application protocol spoken over X2X2 Setup Request, SgNB Addition Request, SgNB Addition Request Acknowledge
SCTPThe reliable transport X2AP rides onINIT / INIT-ACK / COOKIE-ECHO / COOKIE-ACK, then ABORT
Split bearerOne bearer using both nodes' lower layersen-DC-ResourceConfiguration with MCG + SCG resources

Two ideas do the heavy lifting in both captures:

X2AP rides on SCTP, and SCTP comes up first. Unlike TCP, SCTP opens an association with a four-way handshake and multiplexes independent streams so that non-UE signaling (the X2 Setup) and per-UE signaling (the SgNB Addition) never head-of-line block each other. Nothing at the X2AP layer can happen until that association is established.

The added bearer is a split bearer anchored at the MeNB. The SgNB Addition Request asks the gNB to contribute NR radio resources for a Data Radio Bearer. Still, the request here keeps PDCP at the MeNB (resource-configuration: sgNBPDCPnotpresent) while marking both MCG (LTE) and SCG (NR) lower-layer resources present. That shape — one bearer, PDCP at the master, data split across both nodes' radios — is the classic MCG-anchored split bearer of Option 3. And it carries an explicit DRB-ID, which is what this capture is named for: the MeNB pins the NR bearer's identity rather than leaving the SgNB to choose it.

The flow at a glance

Both captures share the same eight-frame skeleton and differ only in the single X2AP payload at frame 7. Read once, the shape is:

  1. SCTP association setup (frames 1–4) — the four-way INIT / INIT-ACK / COOKIE-ECHO / COOKIE-ACK handshake that opens the transport.
  2. X2 Setup (frame 5) — the MeNB introduces itself and its served cell (non-UE-associated). Identical in both captures.
  3. The X2AP payload (frame 7) — the one frame that differs: the SgNB Addition Request in Act 1, the SgNB Addition Request Acknowledge in Act 2.
  4. SCTP ABORT (frame 8) — the association is torn down before any graceful close. (Frame 6, in each capture, is the SCTP acknowledgment of frame 5, not an X2AP message.)

So the plan below is: walk the shared skeleton — SCTP, then X2 Setup — once; then look at each frame-7 payload in turn, the Request and then the Acknowledge; and close on the teardown they both share.

Read end-to-end, the two captures trace one procedure — but only the X2 slice of it. Here is the full logical flow, including the UE and the over-the-air (Uu) messages the X2 captures never see: the MeNB requests the NR bearer, the SgNB acknowledges, the MeNB hands the UE the NR configuration, and once the UE completes and accesses the NR cell, the EN-DC leg is live. Each synthetic capture holds only a fragment of this — Act 1's the SgNB Addition Request, Act 2's the Acknowledge — and nothing on the Uu interface at all.

sequenceDiagram accTitle: EN-DC SgNB Addition end to end — UE, MeNB and SgNB accDescr: An end-to-end EN-DC SgNB Addition. With the UE already RRC-connected on LTE and the X2 interface up, the MeNB sends an SgNB Addition Request carrying the DRB-ID and an RRC CG-ConfigInfo, the SgNB acknowledges with its SgNB-UE-X2AP-ID, the admitted E-RAB and an RRC CG-Config, the MeNB hands the UE the NR secondary-cell-group configuration in an RRCConnectionReconfiguration, the UE replies with RRCConnectionReconfigurationComplete, the MeNB confirms to the SgNB with SgNB Reconfiguration Complete, and the UE performs random access on the NR cell to activate the secondary leg. participant U as UE participant M as MeNB (LTE anchor) participant S as SgNB (5G, NR leg) Note over U,M: UE already RRC-connected on LTE, data on the MCG bearer Note over M,S: SCTP association + X2 interface up (X2 Setup Request / Response) M->>S: SgNB Addition Request (DRB-ID, CG-ConfigInfo) S->>M: SgNB Addition Request Acknowledge (SgNB-UE-X2AP-ID, admitted E-RAB, CG-Config) M->>U: RRCConnectionReconfiguration (carries the NR SCG config) U->>M: RRCConnectionReconfigurationComplete M->>S: SgNB Reconfiguration Complete U->>S: Random Access on NR (SCG activation) Note over U,S: NR leg active — EN-DC dual connectivity
EN-DC SgNB Addition as one end-to-end logical flow across both interfaces. Over X2, the MeNB requests the NR bearer (sending a CG-ConfigInfo) and the SgNB acknowledges with its SgNB-UE-X2AP-ID, the admitted E-RAB, and an RRC CG-Config. Over the air (Uu), the MeNB then hands the UE the NR SCG config in an RRCConnectionReconfiguration; the UE completes, the MeNB confirms to the SgNB with SgNB Reconfiguration Complete, and the UE accesses the NR cell to bring the leg up. The two captures in this article cover only the X2 SgNB Addition messages, not the Uu exchange.

Want the whole EN-DC procedure, not just this X2 slice? This walkthrough zooms in on the two X2AP messages at the center of SgNB Addition. For the complete Non-Standalone signaling — the UE's registration for dual connectivity, the bearer move onto the gNB, and the EPC's part in it — see the full 5G-NR Non-Standalone access call flows.

This is a picture of the X2 topology the messages act on — a UE anchored at the MeNB, with X2 reaching the SgNB that will add the NR leg:

flowchart LR accTitle: EN-DC Option 3 topology accDescr: The UE connects to the LTE master eNB, which links to the EPC and, over the X2 interface which carries X2AP over SCTP, to the secondary 5G gNB that adds an NR data radio bearer. UE(["UE"]) MeNB["MeNB (LTE anchor)"] SgNB["SgNB (5G, NR leg)"] EPC[("EPC")] UE --- MeNB MeNB --- EPC MeNB -- "X2AP / SCTP<br/>SgNB Addition" --> SgNB
EN-DC topology: the UE is anchored at the LTE MeNB (control plane to the EPC); X2AP over SCTP reaches the 5G SgNB, which this capture asks to add an NR data radio bearer.

Underneath the X2AP messages, the SCTP association runs its own lifecycle — and in both captures it never reaches a graceful close; it is aborted:

stateDiagram-v2 accTitle: SCTP association lifecycle in this capture accDescr: The SCTP association moves from CLOSED through the cookie handshake to ESTABLISHED, carries the X2AP PDUs, then goes to CLOSED on a User-initiated ABORT rather than a graceful shutdown. [*] --> CLOSED CLOSED --> COOKIE_WAIT: INIT COOKIE_WAIT --> COOKIE_ECHOED: INIT-ACK COOKIE_ECHOED --> ESTABLISHED: COOKIE-ACK ESTABLISHED --> CLOSED: User-initiated ABORT CLOSED --> [*] note right of ESTABLISHED: Carries X2 Setup + the X2AP payload
The SCTP association lifecycle in each trace: a four-way handshake opens it (frames 1–4), it carries the X2AP PDUs (frames 5, 7), then a User-initiated ABORT (frame 8) tears it down — no graceful SHUTDOWN.

Now the same story, frame by frame — starting with the skeleton both captures share.

Bringing up the transport — SCTP (frames 1–4)

sequenceDiagram accTitle: SCTP association setup accDescr: The MeNB and SgNB complete SCTP's four-way handshake — INIT, INIT-ACK with a state cookie, COOKIE-ECHO, and COOKIE-ACK — establishing the association that will carry X2AP. participant M as MeNB (:41471) participant S as SgNB (:62324) M->>S: INIT (10 outbound streams offered) S->>M: INIT-ACK (parameters + state cookie) M->>S: COOKIE-ECHO (echoes the cookie) S->>M: COOKIE-ACK (association established) Note over M,S: X2AP can now flow

Frames 1–4 — the SCTP four-way handshake. X2AP is carried over SCTP, not TCP, so before any application messages are exchanged, the two nodes establish an association. The MeNB's INIT (frame 1) offers 10 outbound streams; the SgNB's INIT-ACK (frame 2) returns its own parameters plus a state cookie and commits no state yet — that cookie carries the association state, so the responder holds nothing until the echo returns, a feature of SCTP's built-in anti-DoS design. The MeNB's COOKIE-ECHO (frame 3) proves the round-trip, and the SgNB's COOKIE-ACK (frame 4) opens the association in both directions.

Those multiple streams matter for what follows: X2AP deliberately keeps non-UE-associated signaling (the X2 Setup) on a separate stream from UE-associated procedures (the SgNB Addition). Hence, a stall on one never blocks the other. Throughout this loopback capture, the 41471 ↔ 62324 port pair is the only difference between MeNB and SgNB. (The Acknowledge capture of Act 2 runs the same handshake on 44762 ↔ 62324 — same responder port, different initiator port, one small confirmation that it is a separate trace.)

Bringing up the X2 interface — X2 Setup (frame 5)

sequenceDiagram accTitle: X2 Setup accDescr: The MeNB sends an X2 Setup Request advertising its global eNB ID, and one served E-UTRA cell. In a real dialog, the SgNB would reply with an X2 Setup Response, but none arrives in this capture. participant M as MeNB (:41471) participant S as SgNB (:62324) M->>S: X2 Setup Request (Global eNB-ID, 1 served cell) Note over M,S: X2 Setup Response would normally follow — none arrives here

Frame 5 — X2 Setup Request (non-UE-associated). Before any per-UE work, the MeNB introduces itself so the peer knows who it is and which cells it serves. The decoded contents:

IEValueMeaning
Global eNB-ID1macro eNB-ID (20-bit), decimal 1
Served cells1one E-UTRA cell advertised
PCI6physical cell ID
TAC0tracking area code
Broadcast PLMNs001-01, 001-02, 001-03the three PLMNs the cell broadcasts
UL/DL EARFCN3350carrier frequency (same up and down in the test data)

Both captures advertise the same served-cell configuration — the same builder produced them — so the X2 Setup reads the same whether the following frame-7 payload is the Request or the Acknowledge.

Normally the peer answers with an X2 Setup Response, and only then does UE-associated signaling begin. Here the MeNB does not wait — it fires its frame-7 payload immediately, and no response ever arrives. That "send everything, don't wait" pattern is one more tell that these are message-builder traces rather than a real gNB dialog. (Frame 6, in each capture, is the SCTP acknowledgment of frame 5, not an X2AP message.)

Act 1 — The Request: adding the 5G bearer (frame 7)

sequenceDiagram accTitle: Act 1 — SgNB Addition Request accDescr: The MeNB sends an X2AP SgNB Addition Request identifying the UE by MeNB-UE-X2AP-ID and asking the SgNB to add one E-RAB mapped to DRB-ID 1 as an MCG-anchored split bearer with PDCP kept at the MeNB. participant M as MeNB (:41471) participant S as SgNB (:62324) M->>S: SgNB Addition Request (MeNB-UE-X2AP-ID = 1) Note over M,S: Add E-RAB 11 -> DRB-ID 1, split bearer, PDCP at MeNB Note over M,S: The Acknowledge carrying the SCG config<br/>is Act 2 (a separate capture)

Frame 7 — SgNB Addition Request. This is the message the whole capture exists to show: X2AP procedure id-sgNBAdditionPreparation (27). The MeNB, the LTE anchor that owns the UE, asks the secondary gNB to allocate NR radio resources so the UE can run in dual connectivity. The MeNB owns the UE-association here — the identifier is the MeNB-UE-X2AP-ID = 1; the gNB would mint its own SgNB-UE-X2AP-ID in the Acknowledge that never comes.

The bearer being added, decoded from the E-RABs-ToBeAdded list (exactly one item):

Security-context IEs are present but carry placeholder patterns: the SgNBSecurityKey (S-KgNB) is all zeros (256-bit), and the NR UE security capabilities advertise no standard algorithms (the 128-NEA and 128-NIA bits all decode as Not supported). An opaque MeNBtoSgNBContainer — the RRC CG-ConfigInfo — is included as a short stub. In a live add, the gNB would use S-KgNB and these capabilities to configure NR security and reply with a SgNB Addition Request Acknowledge carrying the SCG RRCReconfiguration. That reply is the whole of Act 2 — and watch the container's direction: here the MeNB sends the MeNB→SgNB container, an RRC CG-ConfigInfo, to the SgNB; in Act 2 the SgNB sends the SgNB→MeNB container back, an RRC CG-Config — same procedure, two different RRC containers, one each way.

Here is that request as its fully decoded packet — click any layer to drill in (x2ap is open to the message; expand E-RABs-ToBeAdded and the security IEs to see the placeholders discussed above):

[00006] Frame 7 SgNBAdditionRequest 2018-06-27T09:23:46.688329Z 📶 MeNB (:41471) 📡 SgNB (:62324)
frame : Frame 7: Packet, 196 bytes on wire (1568 bits), 196 bytes captured (1568 bits) on interface any, id 0
Section number : 1
Interface id : 0 (any)
Interface name : any
Encapsulation type : Linux cooked-mode capture v1 (25)
Arrival Time : Jun 27, 2018 02:23:46.688329000 Pacific Daylight Time
UTC Arrival Time : Jun 27, 2018 09:23:46.688329000 UTC
Epoch Arrival Time : 1530091426.688329000
Time shift for this packet : 0.000000000 seconds
Time delta from previous captured frame : 17.000 microseconds
Time delta from previous displayed frame : 17.000 microseconds
Time since reference or first frame : 149.000 microseconds
Frame Number : 7
Frame Length : 196 bytes (1568 bits)
Capture Length : 196 bytes (1568 bits)
Frame is marked : False
Frame is ignored : False
Protocols in frame : sll:ethertype:ip:sctp:x2ap
Character encoding : ASCII (0)
sll : Linux cooked capture v1
Packet type : Unicast to us (0)
Link-layer address type : Loopback (772)
Link-layer address length : 6
Source : 00:00:00:00:00:00
Unused : 0000
Protocol : IPv4 (0x0800)
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 : 0x02 (DSCP: CS0, ECN: ECT(0))
0000 00.. = Differentiated Services Codepoint : Default (0)
.... ..10 = Explicit Congestion Notification : ECN-Capable Transport codepoint '10' (2)
Total Length : 180
Identification : 0x0002 (2)
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 : SCTP (132)
Header Checksum : 0x3bc0 [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
sctp : Stream Control Transmission Protocol, Src Port: 41471 (41471), Dst Port: 62324 (62324)
Source port : 41471
Destination port : 62324
Verification tag : 0x8095663d
Association index : disabled (enable in preferences)
Port : 41471
Port : 62324
Checksum : 0x00000000 [unverified]
Checksum Status : Unverified
DATA chunk (ordered, complete segment, TSN : 1, SID: 0, SSN: 1, PPID: 0, payload length: 129 bytes)
Chunk type : DATA (0)
0... .... = Bit : Stop processing of the packet
.0.. .... = Bit : Do not report
Chunk flags : 0x03
.... 0... = I-Bit : Possibly delay SACK
.... .0.. = U-Bit : Ordered delivery
.... ..1. = B-Bit : First segment
.... ...1 = E-Bit : Last segment
Chunk length : 145
Transmission sequence number (relative) : 1
Transmission sequence number (absolute) : 1979068346
Stream identifier : 0x0000
Stream sequence number : 1
Payload protocol identifier : not specified (0)
x2ap : EUTRAN X2 Application Protocol (X2AP)
0... .... Extension Bit : False
X2AP-PDU : initiatingMessage (0)
initiatingMessage
procedureCode : id-sgNBAdditionPreparation (27)
criticality : reject (0)
value
SgNBAdditionRequest
0... .... Extension Bit : False
protocolIEs : 6 items
Item 0 : id-MeNB-UE-X2AP-ID
ProtocolIE-Field
id : id-MeNB-UE-X2AP-ID (111)
criticality : reject (0)
value
UE-X2AP-ID : 1
Item 1 : id-NRUESecurityCapabilities
ProtocolIE-Field
id : id-NRUESecurityCapabilities (248)
criticality : reject (0)
value
NRUESecurityCapabilities
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
..0. .... Extension Present Bit : False
nRencryptionAlgorithms : 0001 [bit length 16, 0000 0000 0000 0001 decimal value 1]
0... .... .... .... = 128-NEA1 : Not supported
.0.. .... .... .... = 128-NEA2 : Not supported
..0. .... .... .... = 128-NEA3 : Not supported
...0 0000 0000 0001 = Reserved : 0x0001
...0 .... Extension Present Bit : False
nRintegrityProtectionAlgorithms : 0002 [bit length 16, 0000 0000 0000 0010 decimal value 2]
0... .... .... .... = 128-NIA1 : Not supported
.0.. .... .... .... = 128-NIA2 : Not supported
..0. .... .... .... = 128-NIA3 : Not supported
...0 0000 0000 0010 = Reserved : 0x0002
Item 2 : id-SgNBSecurityKey
ProtocolIE-Field
id : id-SgNBSecurityKey (203)
criticality : reject (0)
value
SgNBSecurityKey : 0000000000000000000000000000000000000000000000000000000000000000 [bit length 256]
Item 3 : id-SgNBUEAggregateMaximumBitRate
ProtocolIE-Field
id : id-SgNBUEAggregateMaximumBitRate (204)
criticality : reject (0)
value
UEAggregateMaximumBitRate
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
uEaggregateMaximumBitRateDownlink : 100bits/s
uEaggregateMaximumBitRateUplink : 50bits/s
Item 4 : id-E-RABs-ToBeAdded-SgNBAddReqList
ProtocolIE-Field
id : id-E-RABs-ToBeAdded-SgNBAddReqList (205)
criticality : reject (0)
value
E-RABs-ToBeAdded-SgNBAddReqList : 1 item
Item 0 : id-E-RABs-ToBeAdded-SgNBAddReq-Item
ProtocolIE-Single-Container
id : id-E-RABs-ToBeAdded-SgNBAddReq-Item (209)
criticality : reject (0)
value
E-RABs-ToBeAdded-SgNBAddReq-Item
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
..0. .... Extension Present Bit : False
e-RAB-ID : 11
drb-ID : 1
en-DC-ResourceConfiguration
.... 0... Extension Bit : False
.... .0.. Optional Field Bit : False (iE-Extensions is NOT present)
.... ..0. Extension Present Bit : False
pDCPatSgNB : present (0)
0... .... Extension Present Bit : False
mCGresources : present (0)
..0. .... Extension Present Bit : False
sCGresources : present (0)
.... 0... Extension Bit : False
resource-configuration : sgNBPDCPnotpresent (1)
sgNBPDCPnotpresent
.... ..0. Extension Bit : False
.... ...0 Optional Field Bit : False (secondary-meNB-UL-GTP-TEIDatPDCP is NOT present)
0... .... Optional Field Bit : False (uL-Configuration is NOT present)
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
requested-SCG-E-RAB-Level-QoS-Parameters
..0. .... Extension Bit : False
...0 .... Optional Field Bit : False (gbrQosInformation is NOT present)
.... 0... Optional Field Bit : False (iE-Extensions is NOT present)
qCI : 16
allocationAndRetentionPriority
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
priorityLevel : highest (1)
pre-emptionCapability : shall-not-trigger-pre-emption (0)
pre-emptionVulnerability : not-pre-emptable (0)
meNB-UL-GTP-TEIDatPDCP
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
..0. .... Extension Present Bit : False
transportLayerAddress : 00000000 [bit length 32, 0000 0000 0000 0000 0000 0000 0000 0000 decimal value 0]
transportLayerAddress(IPv4) : 0.0.0.0
gTP-TEID : 00000000
1... .... Extension Present Bit : True
.0.. .... Small Number Bit : False
Enumerated Extension Index : 0
rlc-Mode : Unknown (4)
Item 5 : id-MeNBtoSgNBContainer
ProtocolIE-Field
id : id-MeNBtoSgNBContainer (206)
criticality : reject (0)
value
MeNBtoSgNBContainer : f0f1f20000000000000000000000000000000000000000000000000000000000
NR Radio Resource Control (RRC) protocol
CG-ConfigInfo
criticalExtensions : criticalExtensionsFuture (1)
criticalExtensionsFuture
Rendered from a Wireshark PCAP by VisualEther.

Act 2 — The Acknowledge: the SgNB's reply, carrying CG-Config (frame 7)

Everything to here — SCTP, X2 Setup, the frame-8 ABORT — was the shared skeleton, read from the Request capture. Act 2 is a second capture (Wireshark issue #14940), built the same way, whose frame 7 carries the message the Request capture never received: the SgNB Addition Request Acknowledge. It has its own annotated diagrams:

sequenceDiagram accTitle: Act 2 — SgNB Addition Request Acknowledge accDescr: The secondary gNB replies to the master eNB with an SgNB Addition Request Acknowledge, minting its own SgNB-UE-X2AP-ID, admitting one E-RAB, and returning the SCG configuration as an RRC CG-Config container. participant M as MeNB participant S as SgNB S->>M: SgNB Addition Request Acknowledge (SgNB-UE-X2AP-ID = 102) Note over M,S: Admit E-RAB 119, split bearer, SCG DL GTP TEID, RRC CG-Config Note over M,S: Loopback builder emits this toward the SgNB — read it as the SgNB's reply
Act 2 — the SgNB Addition Request Acknowledge: the secondary gNB mints its own SgNB-UE-X2AP-ID (102), admits E-RAB 119 as an MCG-anchored split bearer, and returns the SCG configuration as an RRC CG-Config. Drawn in its true semantic direction (SgNB → MeNB); the loopback capture emits it the other way — see the note below.

Frame 7 — SgNB Addition Request Acknowledge. Same X2AP procedure as Act 1 — id-sgNBAdditionPreparation (27) — but now a successfulOutcome. Where the Request carried the MeNB's ask, this carries the SgNB's admit: the SCG resources the gNB allocated, and the RRC container the MeNB will forward to the UE. The decoded contents:

IEValueMeaning
MeNB-UE-X2AP-ID85the MeNB's UE-association ID, echoed back
SgNB-UE-X2AP-ID102the gNB now mints its own UE ID — the half the Request lacked
E-RAB-ID (admitted)11 → 119one E-RAB admitted, in E-RABs-Admitted-ToBeAdded-SgNBAddReqAckList
en-DC-ResourceConfigurationpDCPatSgNB, mCGresources, sCGresources all presentthe split-bearer shape, echoed from the request
resource-configurationsgNBPDCPnotpresentPDCP stays at the MeNB — an MCG-anchored split bearer
sgNB-DL-GTP-TEIDatSCG0.0.0.0 / TEID 0x00000000the SgNB's downlink X2-U endpoint for the SCG leg (placeholder)

Two things make this the more interesting half of the procedure:

The UE-association is now complete. The Request carried only a MeNB-UE-X2AP-ID; the Acknowledge returns that plus the gNB's own SgNB-UE-X2AP-ID = 102. That pair — one ID minted by each node — is the handle both sides use for every later X2AP message about this UE. (As flagged in the Overview, these values — 85 / 102 / 119 — don't match the Request capture's 1 / 11, because the two captures are independent builder traces; read this as the shape of the reply, not the literal answer to Act 1's request.)

The SgNBtoMeNBContainer carries an RRC CG-Config. This is the field the capture is really about. The container (IE id-211) is a short stub that Wireshark dissects as nr-rrc CG-ConfigcriticalExtensions: c1: cg-Config, with every optional bit false — no scg-CellGroupConfig, no scg-RB-Config, no configRestrictModReq. So it is a well-formed but empty CG-Config: the right container, carrying no actual SCG cell-group configuration (a placeholder, as in these traces). In a live add, this is where the SCG RRCReconfiguration would ride back to the MeNB for relay to the UE, thereby standing up the NR leg.

The direction of that container is the crux of Wireshark issue #14940, which this capture comes from: the SgNB→MeNB container must decode as CG-Config (TS 38.331), not the CG-ConfigInfo that travels the other way in Act 1's MeNBtoSgNBContainer: one procedure, two RRC containers — CG-ConfigInfo out, CG-Config back.

One last honest note about the diagram. Read the on-wire direction carefully: this loopback builder emits every application PDU from the initiator socket (44762), so on the wire the Acknowledge travels toward the SgNB — the same direction as the X2 Setup. Semantically it is the SgNB's reply to the MeNB as shown in the inline diagram above. Read the hosted capture diagram for the message's content, not its arrow direction — the same "structure, not values" discipline the rest of this trace demands.

And the Acknowledge as its full decoded packet — expand the x2ap subtree to find the SgNB-UE-X2AP-ID, the admitted E-RAB, and the SgNBtoMeNBContainer carrying the CG-Config:

[00006] Frame 7 SgNBAdditionRequestAcknowledge 2018-07-04T01:53:27.544684Z 📶 MeNB (:44762) 📡 SgNB (:62324)
frame : Frame 7: Packet, 124 bytes on wire (992 bits), 124 bytes captured (992 bits) on interface any, id 0
Section number : 1
Interface id : 0 (any)
Interface name : any
Encapsulation type : Linux cooked-mode capture v1 (25)
Arrival Time : Jul 3, 2018 18:53:27.544684000 Pacific Daylight Time
UTC Arrival Time : Jul 4, 2018 01:53:27.544684000 UTC
Epoch Arrival Time : 1530669207.544684000
Time shift for this packet : 0.000000000 seconds
Time delta from previous captured frame : 17.000 microseconds
Time delta from previous displayed frame : 17.000 microseconds
Time since reference or first frame : 157.000 microseconds
Frame Number : 7
Frame Length : 124 bytes (992 bits)
Capture Length : 124 bytes (992 bits)
Frame is marked : False
Frame is ignored : False
Protocols in frame : sll:ethertype:ip:sctp:x2ap
Character encoding : ASCII (0)
sll : Linux cooked capture v1
Packet type : Unicast to us (0)
Link-layer address type : Loopback (772)
Link-layer address length : 6
Source : 00:00:00:00:00:00
Unused : 0000
Protocol : IPv4 (0x0800)
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 : 0x02 (DSCP: CS0, ECN: ECT(0))
0000 00.. = Differentiated Services Codepoint : Default (0)
.... ..10 = Explicit Congestion Notification : ECN-Capable Transport codepoint '10' (2)
Total Length : 108
Identification : 0x0002 (2)
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 : SCTP (132)
Header Checksum : 0x3c08 [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
sctp : Stream Control Transmission Protocol, Src Port: 44762 (44762), Dst Port: 62324 (62324)
Source port : 44762
Destination port : 62324
Verification tag : 0xcbf1d023
Association index : disabled (enable in preferences)
Port : 44762
Port : 62324
Checksum : 0x00000000 [unverified]
Checksum Status : Unverified
DATA chunk (ordered, complete segment, TSN : 1, SID: 0, SSN: 1, PPID: 0, payload length: 57 bytes)
Chunk type : DATA (0)
0... .... = Bit : Stop processing of the packet
.0.. .... = Bit : Do not report
Chunk flags : 0x03
.... 0... = I-Bit : Possibly delay SACK
.... .0.. = U-Bit : Ordered delivery
.... ..1. = B-Bit : First segment
.... ...1 = E-Bit : Last segment
Chunk length : 73
Transmission sequence number (relative) : 1
Transmission sequence number (absolute) : 3340726994
Stream identifier : 0x0000
Stream sequence number : 1
Payload protocol identifier : not specified (0)
x2ap : EUTRAN X2 Application Protocol (X2AP)
0... .... Extension Bit : False
X2AP-PDU : successfulOutcome (1)
successfulOutcome
procedureCode : id-sgNBAdditionPreparation (27)
criticality : reject (0)
value
SgNBAdditionRequestAcknowledge
0... .... Extension Bit : False
protocolIEs : 4 items
Item 0 : id-MeNB-UE-X2AP-ID
ProtocolIE-Field
id : id-MeNB-UE-X2AP-ID (111)
criticality : reject (0)
value
UE-X2AP-ID : 85
Item 1 : id-SgNB-UE-X2AP-ID
ProtocolIE-Field
id : id-SgNB-UE-X2AP-ID (207)
criticality : reject (0)
value
SgNB-UE-X2AP-ID : 102
Item 2 : id-E-RABs-Admitted-ToBeAdded-SgNBAddReqAckList
ProtocolIE-Field
id : id-E-RABs-Admitted-ToBeAdded-SgNBAddReqAckList (210)
criticality : ignore (1)
value
E-RABs-Admitted-ToBeAdded-SgNBAddReqAckList : 1 item
Item 0 : id-E-RABs-Admitted-ToBeAdded-SgNBAddReqAck-Item
ProtocolIE-Single-Container
id : id-E-RABs-Admitted-ToBeAdded-SgNBAddReqAck-Item (213)
criticality : ignore (1)
value
E-RABs-Admitted-ToBeAdded-SgNBAddReqAck-Item
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
..1. .... Extension Present Bit : True
integer length : 1
e-RAB-ID : 119
en-DC-ResourceConfiguration
0... .... Extension Bit : False
.0.. .... Optional Field Bit : False (iE-Extensions is NOT present)
..0. .... Extension Present Bit : False
pDCPatSgNB : present (0)
.... 0... Extension Present Bit : False
mCGresources : present (0)
.... ..0. Extension Present Bit : False
sCGresources : present (0)
0... .... Extension Bit : False
resource-configuration : sgNBPDCPnotpresent (1)
sgNBPDCPnotpresent
..0. .... Extension Bit : False
...0 .... Optional Field Bit : False (secondary-sgNB-DL-GTP-TEIDatSCG is NOT present)
.... 0... Optional Field Bit : False (iE-Extensions is NOT present)
sgNB-DL-GTP-TEIDatSCG
.... .0.. Extension Bit : False
.... ..0. Optional Field Bit : False (iE-Extensions is NOT present)
.... ...0 Extension Present Bit : False
transportLayerAddress : 00000000 [bit length 32, 0000 0000 0000 0000 0000 0000 0000 0000 decimal value 0]
transportLayerAddress(IPv4) : 0.0.0.0
gTP-TEID : 00000000
Item 3 : id-SgNBtoMeNBContainer
ProtocolIE-Field
id : id-SgNBtoMeNBContainer (211)
criticality : reject (0)
value
SgNBtoMeNBContainer : 00100ea084c400188000
NR Radio Resource Control (RRC) protocol
CG-Config
criticalExtensions : c1 (0)
c1 : cg-Config (0)
cg-Config
...0 .... Optional Field Bit : False (scg-CellGroupConfig is NOT present)
.... 0... Optional Field Bit : False (scg-RB-Config is NOT present)
.... .0.. Optional Field Bit : False (configRestrictModReq is NOT present)
.... ..0. Optional Field Bit : False (drx-InfoSCG is NOT present)
.... ...0 Optional Field Bit : False (candidateCellInfoListSN is NOT present)
0... .... Optional Field Bit : False (measConfigSN is NOT present)
.0.. .... Optional Field Bit : False (selectedBandCombination is NOT present)
..0. .... Optional Field Bit : False (fr-InfoListSCG is NOT present)
...1 .... Optional Field Bit : True (candidateServingFreqListNR is present)
.... 0... Optional Field Bit : False (nonCriticalExtension is NOT present)
candidateServingFreqListNR : 1 item
Item 0
ARFCN-ValueNR : 958596
Rendered from a Wireshark PCAP by VisualEther.

The teardown — an SCTP ABORT, not a verdict (frame 8)

Both captures end the same way — not with an X2AP follow-up or a graceful SCTP SHUTDOWN, but with an ABORT:

sequenceDiagram accTitle: SCTP ABORT accDescr: Instead of a further X2AP message, the SgNB-side endpoint sends an SCTP ABORT with cause User-initiated ABORT. This is a graceful socket teardown that leaves the X2AP procedures without a follow-up on the wire. participant M as MeNB participant S as SgNB S->>M: SCTP ABORT (cause: User-initiated ABORT) Note over M,S: Association closed — no X2AP follow-up,<br/>no graceful SHUTDOWN

Frame 8 — SCTP ABORT. In both captures, the SgNB-side endpoint (port 62324) sends an SCTP ABORT with cause "User initiated ABORT" (0x000c). Read this carefully: it is a graceful, application-driven socket teardownnot an X2AP SgNBAdditionRequestReject, and not a protocol error. The test tool closed the association after emitting its PDUs.

Consequently, each capture is incomplete::no-close at X2AP and failure::aborted at SCTP — even the Act 2 capture, whose frame 7 is itself a successful outcome. It looks like a failure; it is really just the capture ending. And it is one more reason the procedure takes two captures to show in full: neither one carries a graceful, two-directional exchange.

Reading a synthetic capture

The most useful skill these traces teach is not about EN-DC at all — it is how to tell structure from values. A message-builder capture like these is authored to exercise the encoding of a procedure. Every mandatory IE is present and correctly typed, so the message decodes cleanly, and you can study exactly which parameters an SgNB Addition Request and its Acknowledge carry. But the contents are filler — zero keys, 0.0.0.0 endpoints, "Unknown" modes, capability bitmaps with nothing set, an empty CG-Config.

Three habits keep you honest when you meet one on a real analysis:

  1. Distinguish a transport event from an application verdict. The frame-8 ABORT ends the association, but it says nothing about whether the SgNB accepted the bearer. Act 2 makes the point vividly: its frame 7 is a successful Acknowledge, yet the association still aborts a frame later — the SCTP teardown and the X2AP outcome are independent facts at different layers. A real rejection, likewise, would be an X2AP SgNBAdditionRequestReject with a cause, not an ABORT.
  2. Double-check the values against the spec. An all-zero security key, a 0.0.0.0 GTP endpoint, an empty CG-Config, or a QCI that isn't in the standard tables are the fingerprints of test data, not of a network you should be troubleshooting.
  3. Don't over-read on-wire direction in a builder trace. This tool emits every PDU from the initiator socket, so Act 2's Acknowledge travels toward the SgNB even though it is semantically the SgNB's reply. On a synthetic capture, trust the message type and its IEs over the arrow's direction.

📨 Have a complete EN-DC capture? Both traces here are synthetic message-builder samples — a full, real-world Non-Standalone flow (UE registration for dual connectivity, then SgNB Addition and the bearer moving onto the gNB) isn't publicly available anywhere we could find. If you have one you can share, send it to support@eventhelix.com, and we'll turn it into an annotated walkthrough like this one — and credit the source of the flow.

Takeaways

  1. EN-DC grafts 5G onto LTE over X2, in two moves. The UE remains anchored to the LTE MeNB; the MeNB requests an NR leg over X2 (Act 1), and the SgNB acknowledges the admission (Act 2). Those two X2AP messages are the whole of SgNB Addition.
  2. SCTP first, X2AP second. No X2AP message can flow until the four-way SCTP handshake establishes the association, and its multiple streams keep non-UE and per-UE signaling from blocking each other.
  3. The bearer is an MCG-anchored split bearer. PDCP remains at the MeNB (sgNBPDCPnotpresent), while both MCG and SCG resources are marked as present. The Request pins the NR bearer with an explicit DRB-ID; the Acknowledge echoes the same split-bearer shape back.
  4. The Acknowledge completes the UE association and returns the CG-Config. The gNB mints its own SgNB-UE-X2AP-ID to pair with the MeNB's, admits the E-RAB, and returns the SCG configuration as an RRC CG-Config — the reply container, distinct from the CG-ConfigInfo the MeNB sent outbound.
  5. An SCTP ABORT is not an X2AP reject. Both associations are torn down at the transport layer — even the one whose frame 7 was a successful Acknowledge. Read the SCTP outcome and the X2AP outcome as independent facts.
  6. Know structure from values — and it takes two captures to see both directions. These are message-builder traces: trust them for which IEs an SgNB Addition Request and its Acknowledge carry, not for the placeholder contents inside them, and remember the two are independent traces, not two ends of one wire.

Try it on your own capture

Every arrow in this walkthrough was decoded and captioned by VisualEther from a raw Wireshark PCAP — no manual diagramming. Point it at your own 5G, LTE, or IMS trace and read it the same way.