Previously, TAU procedure validated EPS Bearer Context Status (BCS)
only when active_flag == 0. When active_flag == 1, the MME skipped BCS
validation and sent TAU ACCEPT directly via InitialContextSetup.
This patch unifies BCS validation so both active_flag paths handle
bearer mismatches consistently. It also selects the correct S1AP
procedure (InitialContextSetup or DownlinkNASTransport) depending on
the UE active state.
Changes:
- emm-sm.c / sgsap-handler.c:
* Always check EPS_BEARER_CONTEXT_STATUS_TYPE presence.
* Invoke mme_send_delete_session_or_tau_accept() for both
active_flag=0 and 1.
* Send TAU ACCEPT directly only when BCS is not present.
- mme-path.c:
* Select S1AP procedure in TAU ACCEPT based on active_flag.
- mme-s11-handler.c:
* After Delete Session Response (OGS_GTP_DELETE_SEND_TAU_ACCEPT),
send TAU ACCEPT using proper S1AP procedure by active_flag.
This aligns MME TAU behavior with 3GPP TS 24.301 section 5.3.3.0a,
ensuring consistent BCS synchronization regardless of UE activity.
Instead of predetermined endpoints in the metrics library, each NF can
now set it's own endpoints on which it listens for requests to dump info
(UE/PDU/gNB/eNB).
Remove function pointers to set page/page sizes per info type
(UE/PDU/gNB/eNB info). Instead, call dumpers functions with this
information as function arguments.
When the UE sends a Tracking Area Update (TAU) Request with active_flag=0,
the MME previously sent TAU Accept without verifying the EPS Bearer Context
Status (EBCS). This caused stale bearer sessions to remain in the MME even
if the UE had already released them.
According to 3GPP TS 24.301 §5.5.3.2, the MME should release any bearer
not reported in the UE’s EBCS when active_flag=0. This patch introduces
mme_send_delete_session_or_tau_accept(), which compares the UE’s EBCS bitmask
with the MME session list and deletes any missing default bearer session
before sending TAU Accept.
If no mismatch is found, TAU Accept is sent immediately. The Delete Session
response triggers TAU Accept when deletions are required. This ensures that
the TAU Accept message reflects the UE’s current bearer context accurately.
Also includes:
- Added OGS_GTP_DELETE_SEND_TAU_ACCEPT handling in mme-s11-handler.c
- Simplified EBCS structure (uint16_t value) for bitmask comparison
- Updated TAU-related tests with realistic EBI bitmasks (0x20, 0x60)
This change aligns TAU handling with 3GPP 24.301 and prevents bearer
mismatch issues between UE and EPC during TAU.
Open5GS has a lightweight HTTP server (already used for `/metrics`) embedded in each NF.
New optional JSON endpoints were added:
| NF | Endpoint | Content |
| --- | --- | --- |
| **SMF** | `/pdu-info` | All currently connected UEs + their PDU sessions (IMSI/SUPI, DNN, IPs, S-NSSAI, QoS, state, etc.) |
| **AMF** | `/gnb-info` | All currently connected gNBs and their supported TAs, PLMNs, SCTP info, number of UEs |
| **AMF** | `/ue-info` | All currently connected NR UEs and their info, active gNB, tai, security, slices, am_policy |
| **MME** | `/enb-info` | All currently connected eNBs and their supported TAs, PLMNs, SCTP info, number of UEs |
| **MME** | `/ue-info` | All currently connected LTE UEs and their info, active eNB, tai, pdn info |
They are exposed on the same HTTP port used by Prometheus metrics (default `:9090`).
To reduce processor load when there are a large number of devices, the API includes a pager that limits output.
`/ue-info?page=0&page_size=100`
page in the range 0-n (0 is default),
`page=-1` to avoid paging
`page_size=100` (default and MAX)
Problem
-------
AMF was crashing several times per day when multiple UEs were connecting,
sending data, and disconnecting. The crash occurred in
gmm_state_de_registered() with the following log:
FATAL: Invalid state [2]
FATAL: gmm_state_de_registered: should not be reached.
This was triggered by network-initiated deregistration scenarios that were
not explicitly handled in the FSM, causing the AMF to enter an unexpected
state and abort.
- Added explicit size checks for critical IE fields (PLMNIdentity, TAC,
GTP-TEID, Cell-ID, UE security capability algorithms, etc.) before
memcpy() operations.
- When size mismatch is detected, log an error and return an Error
Indication (or Setup Failure) with appropriate protocol cause
(semantic_error or message_not_compatible_with_receiver_state).
- Introduced s1ap_send_error_indication1(enb_ue_t *enb_ue, ...)
as a helper for cases where ENB UE context is available directly.
s1ap_send_error_indication2(mme_ue_t *mme_ue, ...) now delegates
to the new function, reducing code duplication.
- Replaced ogs_assert() checks with graceful error handling paths
to avoid abnormal process termination.
This improves robustness against malformed or non-compliant NGAP/S1AP
messages and prevents potential AMF/MME crashes.
When the NGSetupRequest contains an invalid GlobalRANNodeID or
BroadcastPLMNItem with a malformed PLMNIdentity, the AMF previously
performed memcpy() without checking the buffer size. This could lead
to invalid memory access and crash.
Fix by validating PLMNIdentity size against sizeof(ogs_plmn_id_t) and
sending NGSetupFailure with CauseProtocol_semantic_error if invalid.
Also add regression tests:
- Build malformed NGSetupRequest with incorrect PLMNIdentity size
- Verify AMF does not crash and returns NGSetupFailure
This resolves the crash reported in issue #4087.
In some handover scenarios, `sgwc_sxa_build_bearer_to_modify_list()` could
be invoked when there were no bearers to modify. This led to an assertion
failure:
Assertion `num_of_remove_pdr + num_of_remove_far + ...` failed
This patch adds explicit checks on `sess->bearer_list` before building or
sending PFCP Session Modification Requests. If no bearers are present, the
request is skipped and an error is logged with IMSI/APN/TEID context
instead of aborting the process.
Changes include:
- Added `ogs_list_count(&sess->bearer_list)` checks in
`pfcp-path.c`, `s11-handler.c`, `s5c-handler.c`, and `sxa-handler.c`.
- Gracefully skip SMR when bearer list is empty in
Delete Indirect Data Forwarding Tunnel Request handling.
- Log diagnostic information (IMSI, APN, TEIDs) when no bearer is found.
This prevents SGWC from crashing under DEBUG logging and concurrent HO
scenarios, and allows multiple handover sessions to proceed more stably.
When the UE context was removed (e.g. after implicit detach or Delete
Session response), ongoing paging procedures were not finalized. This
caused the MME to skip sending the appropriate paging outcome (e.g.
Downlink Data Notification ACK, Create Bearer Response, Update Bearer
Response, Delete Bearer Response, SGSAP Paging Reject, etc.) depending
on the paging type.
As a result, the SGW or MSC/VLR could continue retransmitting, and the
MME produced spurious "Unknown timer[T3413]" errors.
This patch introduces `MME_UE_REMOVE_WITH_PAGING_FAIL`, which:
- Checks if paging is ongoing before removing the UE context
- Calls `mme_send_after_paging()` to send the correct outcome message
(Unable to page UE or equivalent cause) according to paging type
- Removes the UE context afterwards
This change ensures that all paging procedures are completed with a
proper response as required by 3GPP specifications, improving network
interoperability and eliminating misleading timer errors.
When the AMF receives a DELETE request for the registration API while in
the gmm_state_authentication state, it currently crashes because the
HTTP method is not handled. This appears to be a race condition.
To fix this, explicitly handle OGS_SBI_HTTP_METHOD_DELETE by ignoring the
message and logging an error, similar to the handling of other
unexpected SBI messages.
When the AMF receives a PATCH request for the registration API while in
the gmm_state_authentication state, it currently crashes because the
HTTP method is not handled. This appears to be a race condition.
To fix this, explicitly handle OGS_SBI_HTTP_METHOD_PATCH by ignoring the
message and logging an error, similar to the handling of other
unexpected SBI messages.
- Use ogs_pool_id_calloc() / ogs_pool_id_free() instead of ogs_pool_alloc() / ogs_pool_free()
to assign stable pool IDs to connection_t and ogs_sbi_session_t.
- Pass pool ID to ogs_timer_add() instead of raw pointer.
- In connection_timer_expired() and session_timer_expired(), resolve object via
ogs_pool_find_by_id() and safely return if the object has already been freed.
- Add safety checks and error logs for invalid IDs and missing objects.
This prevents use-after-free or double-free crashes when timer callbacks
are triggered after the object has been freed under heavy load.
Previously, the code asserted the existence of a bearer when handling
Create Indirect Data Forwarding Tunnel Request. If the bearer was not
found, this caused a crash.
This patch adds a null check for the bearer. If no bearer is found,
it now logs an error and sends a GTP error response with
CAUSE_CONTEXT_NOT_FOUND, then returns gracefully.
Previously, sgwc_bearer_add() and sgwc_tunnel_add() relied on ogs_assert()
for allocation failures (bearer, tunnel, PDR, FAR). Under heavy handover
(ViLTE ping-pong HO) conditions, pool exhaustion could trigger assertions
and crash the SGW-C.
This patch:
- Adds NULL checks for ogs_pool_id_calloc() in bearer/tunnel creation
- Adds NULL checks for ogs_pfcp_pdr_add() and ogs_pfcp_far_add()
- Cleans up partially created objects on failure
- Returns System Failure for S11 CIDFT requests if tunnel creation fails
- Adds NULL checks before removing PDR/FAR in sgwc_tunnel_remove()
- Fixes log message for PDR allocation failure
These changes improve stability during repeated HO scenarios by preventing
assertion crashes when resource pools are exhausted.
During integration tests with a third-party SCP, SMF crashed after
processing the UDM response to a PUT request during UE attachment.
This issue was traced to a missing NULL-check on the `stream` pointer
inside smf_state_operational().
Previously, the code asserted `stream` unconditionally when sending
the HTTP response or PDU session created data. If the SBI stream had
already been removed, the assertion failed, causing SMF to abort.
This patch adds a NULL-check for `stream`. When `stream` is NULL,
an error log is printed instead of asserting. This prevents SMF from
crashing and allows it to continue processing.
Tested with:
- Open5GS v2.7.6-21-g0516e01
- SCP from another vendor (crash reproduced and fixed)
- Open5GS SCP (no crash observed)
Fixes: smf_state_operational() assertion failure at smf-sm.c:1075
Answer ALERT-REQUEST with either ALERT-ACK or ALERT-REJECT.
This commit leaves unimplemented (to be implemented in the future)
the part regarding setting of internal NEAF flag for UE inside MME
and then triggering SGsAP-UE-ACTIVITY-INDICATION towards VLR.
See 3GPP TS 23.272 and 3GPP TS 29.118 (grep for "Alert" and "Activity")
for further information.
PFCP PDR precedence is a uint32_t. In Open5GS the default
OGS_PFCP_DEFAULT_PDR_PRECEDENCE is 65535. The previous assert enforced
(0,255), which is incorrect and causes valid configurations to abort.
Remove the assert and pass the precedence through as-is.
Fixes assertion failures seen in TC_pdu_sess_modification in
osmo-ttcn3-hacks.
The older version of the code was wrong (or at least not exactly
correct) in many (corner) cases.
* Split the parsing of Packet Filter List into its own helper function
to simplify the code
* Improve error logging to provide more info on which QoS rule failed.
* Add some extra logic checking match between 'Length of QoS rule' and
existance of m+1 and m+2 bytes.
* Correct logic checking expected/unexpected presence of m+1 and m+2
octets based on Rule Operation Code according to specs.
Home-Routed roaming: during Xn/N2 handover the source gNB may forward
remaining DL data to the core using UL PDU Session Information (PSC).
On the V-UPF the PSC was lost on the indirect path because OHR+OHC
removed the incoming GTP-U header (and its extensions) and we did not
recreate PSC when no QER/QFI was provisioned by the V-SMF.
This change makes the V-UPF rebuild a DL PSC for the target gNB even
when QER is absent, limited to the Access->Access indirect path
(source gNB -> V-UPF -> target gNB).
Why this is needed in HR:
- In HR deployments the V-SMF typically does not provision QER/QFI for
the temporary indirect path. Without recreating PSC from recvhdr, the
extension header disappears after OHR+OHC and the target gNB cannot
see the QFI during handover buffering/forwarding.
Previously, Outer Header Removal was set according to PDU session type.
However, outer header IP version is independent of inner packet IP version or
PDU session type. It typically depends on UPF and gNB configuration. Set it to
GTP-U/UDP/IP to handle both IPv4 and IPv6 cases, according to TS 29.244, Table
8.2.64-1, Note 4: "The CP function shall use this value to instruct UP function
to remove the GTP-U/UDP/IP header regardless it is IPv4 or IPv6."
No changes at UPF are necessary because it already ignores Outer Header Removal
Description type and Kernel correctly decapsulates the outer IP header at
socket level.
This change moves the call to fd_msg_new_answer_from_req so that the answer
header is created immediately after the incoming request is received,
ensuring that the ans pointer is initialized before any message‐specific
allocations or parsing take place.
This refactoring guarantees that the answer message is set up once and early,
which improves readability and ensures that proper cleanup can occur
without repeated steps.
Refer to:
- Issues #4012
- Pull Request #4034
- Commit f23d7a5
Add robust error checks and logging to MME, SMF, PCRF, and HSS
Diameter callback functions. Prevent assertion failures by
handling unexpected or late messages gracefully.
Instead of aborting the AMF when an SM context release is requested during the
security-mode state, log an error and allow the system to continue operating.
This avoids a fatal assertion failure and improves overall availability. The
error message "Invalid state transition: cannot release SM Context during
security-mode state" provides a clear debug trace for issue #4012.