From 67e9c9c26398f72b1d74c1cbcf7d80136468203d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Jun 2025 08:00:08 +0200 Subject: [PATCH] RRC: auto-generate release request when no AMF Mark non-existing AMF UE NGAP ID through invalid INT64_MAX number (permitted range is up to 2^40-1). Check for this range in the RAN function, as we might otherwise pass the invalid AMF UE NGAP ID to the agent, which would assert with nr-softmodem: /oai-ran/openair2/E2AP/flexric/src/lib/3gpp/enc/enc_gnb.c:83: enc_gNB_UE_asn: Assertion `gnb->amf_ue_ngap_id < 1UL << 40' failed. In other words, don't send KPM messages for a UE which has no valid AMF UE NGAP ID yet (which follows from the fact that the spec requires an AMF UE NGAP ID; the previous behavior of simply sending 0 could be considered a bug, because it's not the UE's true AMF UE NGAP ID). --- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c | 7 ++++++- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 6 ++++++ openair2/RRC/NR/rrc_gNB.c | 10 ++++++---- openair2/RRC/NR/rrc_gNB_UE_context.c | 2 ++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c index c3f6277f6f..a81a01d394 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c @@ -30,7 +30,12 @@ ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, __attr // 6.2.3.16 // Mandatory // AMF UE NGAP ID - ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->amf_ue_ngap_id; + // it seems that certain messages can be triggered before the ue has an AMF + // UE NGAP ID (e.g., RRC setup). In that case, the AMF UE NGAP ID is set to + // an invalid value. Below, check for this, and set 0 in that case (which + // historically used to be in amf_ue_ngap_id). + uint64_t auni = rrc_ue_context->amf_ue_ngap_id; + ue_id.gnb.amf_ue_ngap_id = auni < (1LL << 40) ? auni : 0; // Mandatory //GUAMI 6.2.3.17 diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 4468cdf0b9..fd6578b3b2 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -209,6 +209,9 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info) struct rrc_gNB_ue_context_s* rrc_ue_context = NULL; RB_FOREACH(rrc_ue_context, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { gNB_RRC_UE_t *ue = &rrc_ue_context->ue_context; + /* UE has no AMF UE NGAP ID yet => can't send message */ + if (ue->amf_ue_ngap_id >= (1LL << 40)) + continue; for (int p = 0; p < ue->nb_of_pdusessions; ++p) { pdusession_t *pdu = &ue->pduSession[p].param; if (nssai_matches(pdu->nssai, sst, sd)) { @@ -296,6 +299,9 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_DU](NULL, rrc_ue_id.secondary_ue, 0); } else { rrc_gNB_ue_context_t* rrc_ue_context = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], -1, ue->rnti); + /* UE has no AMF UE NGAP ID yet => can't send message */ + if (rrc_ue_context->ue_context.amf_ue_ngap_id >= (1LL << 40)) + continue; arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB](&rrc_ue_context->ue_context, 0, 0); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ef11ce605..f9952d0dae 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2146,12 +2146,14 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id); - // TODO what happens if no AMF connected? should also handle, set an_release true int srbid = 1; - if (!ue_context_p) { - LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id); + // valid AMF UE NGAP ID range is 0..2^40-1 + if (!ue_context_p || ue_context_p->ue_context.amf_ue_ngap_id >= (1LL << 40)) { + const char *reason = !ue_context_p ? "could not find UE context" : "no AMF"; + LOG_W(RRC, "%s for CU UE ID %u: auto-generate release command\n", reason, req->gNB_CU_ue_id); uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0)); + RETURN_IF_INVALID_ASSOC_ID(assoc_id); f1ap_ue_context_release_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, @@ -2159,7 +2161,7 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release .srb_id = srbid, }; - deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd}; + deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = assoc_id}; nr_pdcp_data_req_srb(req->gNB_CU_ue_id, srbid, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); return; } diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index b39abd9a30..cb3a04fbce 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -200,6 +200,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, gNB_RRC_UE_t *ue = &ue_context_p->ue_context; ue->rnti = rnti; ue->random_ue_identity = ue_identityP; + // signal "no AMF UE NGAP ID" because valid range is 0..2^40-1 + ue->amf_ue_ngap_id = INT64_MAX; f1_ue_data_t ue_data = {.secondary_ue = du_ue_id, .du_assoc_id = assoc_id}; AssertFatal(!cu_exists_f1_ue_data(ue->rrc_ue_id), "UE F1 Context for ID %d already exists, logic bug\n",