Commit bd6ce9ba authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/fix-bug-release-no-amf' into integration_2026_w03 (!3857)

Fix bug "no AMF for UE"

It might happen that the RRC does not know the AMF UE NGAP ID, yet. Even
in that case, we should forward the release request to the NGAP module,
which can either forward a message to the AMF, or reply back to release
the UE. This avoids an error where the CU claims there was no AMF, when
there actually is.

One possible problematic behavior is if a UE disconnects before the gNB
receives an NGAP Initial Context Setup. In this case, the AMF UE NGAP ID
was not forwarded to the RRC (although it was known at NGAP), thus
blocking the release of the UE.

This is the main fix, the rest are minor fixes:

- store AMF UE NGAP ID as early as possible
- warn in MAC if UE unknown for UE context release command
- show TEIDs with correct endianness in GTP
- avoid NG Setup Failure+Setup log.
parents 93b3a5ae 5fa624b2
......@@ -737,6 +737,8 @@ typedef struct ngap_ue_ctxt_modification_resp_s {
typedef struct ngap_downlink_nas_s {
/* UE id for initial connection to NGAP */
uint32_t gNB_ue_ngap_id;
/* UE id at AMF */
uint64_t amf_ue_ngap_id;
/* NAS pdu */
byte_array_t nas_pdu;
} ngap_downlink_nas_t;
......
......@@ -888,6 +888,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd)
UE = UE ? UE : find_ra_UE(&mac->UE_info, cmd->gNB_DU_ue_id);
if (UE == NULL) {
NR_SCHED_UNLOCK(&mac->sched_lock);
LOG_W(NR_MAC, "UE Context Release Command for unknown RNTI %04x/CU UE ID %d\n", cmd->gNB_DU_ue_id, cmd->gNB_CU_ue_id);
f1ap_ue_context_rel_cplt_t complete = {
.gNB_CU_ue_id = cmd->gNB_CU_ue_id,
.gNB_DU_ue_id = cmd->gNB_DU_ue_id,
......
......@@ -2440,10 +2440,8 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as
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);
int srbid = 1;
// 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);
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);
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);
......
......@@ -717,6 +717,7 @@ int rrc_gNB_process_NGAP_DOWNLINK_NAS(MessageDef *msg_p, instance_t instance, mu
}
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
UE->amf_ue_ngap_id = req->amf_ue_ngap_id;
UE->nas_pdu = req->nas_pdu;
rrc_forward_ue_nas_message(rrc, UE);
return 0;
......
......@@ -84,7 +84,6 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut
}
}
} else {
LOG_A(NGAP, "Received NGSetupResponse from AMF\n");
/* Check that at least one setup message is pending */
DevCheck(amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0, amf_desc_p->ngap_gNB_instance->instance,
amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb, 0);
......@@ -314,6 +313,7 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb ++;
ngap_handle_ng_setup_message(amf_desc_p, 0);
LOG_A(NGAP, "Received NGSetupResponse from AMF\n");
return 0;
}
......@@ -849,6 +849,11 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
NGAP_INFO("Initial Context Setup UE RAN ID %d UE AMF ID %ld: %d PDU session(s)\n",
msg->gNB_ue_ngap_id,
msg->amf_ue_ngap_id,
msg->nb_of_pdusessions);
return 0;
}
......
......@@ -54,7 +54,7 @@ void ngap_gNB_itti_send_sctp_data_req(instance_t instance,
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ngap_id, uint8_t *nas_pdu, uint32_t nas_pdu_length)
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ngap_id, uint64_t amf_ue_ngap_id, uint8_t *nas_pdu, uint32_t nas_pdu_length)
{
MessageDef *message_p;
ngap_downlink_nas_t *ngap_downlink_nas;
......@@ -64,6 +64,7 @@ void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ng
ngap_downlink_nas = &message_p->ittiMsg.ngap_downlink_nas;
ngap_downlink_nas->gNB_ue_ngap_id = gNB_ue_ngap_id;
ngap_downlink_nas->amf_ue_ngap_id = amf_ue_ngap_id;
ngap_downlink_nas->nas_pdu = create_byte_array(nas_pdu_length, nas_pdu);
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
......
......@@ -40,7 +40,11 @@ void ngap_gNB_itti_send_sctp_data_req(instance_t instance,
uint32_t buffer_length,
uint16_t stream);
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ngap_id, uint8_t *nas_pdu, uint32_t nas_pdu_length);
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance,
uint32_t gNB_ue_ngap_id,
uint64_t amf_ue_ngap_id,
uint8_t *nas_pdu,
uint32_t nas_pdu_length);
void ngap_gNB_itti_send_sctp_close_association(instance_t instance, sctp_assoc_t assoc_id);
......
......@@ -361,7 +361,11 @@ int ngap_gNB_handle_nas_downlink(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NG
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNASTransport_IEs_t, ie, container,
NGAP_ProtocolIE_ID_id_NAS_PDU, true);
/* Forward the NAS PDU to NR-RRC */
ngap_gNB_itti_send_nas_downlink_ind(ngap_gNB_instance->instance, ue_desc_p->gNB_ue_ngap_id, ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size);
ngap_gNB_itti_send_nas_downlink_ind(ngap_gNB_instance->instance,
ue_desc_p->gNB_ue_ngap_id,
ue_desc_p->amf_ue_ngap_id,
ie->value.choice.NAS_PDU.buf,
ie->value.choice.NAS_PDU.size);
return 0;
}
......
......@@ -1036,9 +1036,9 @@ static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, const s
" TV id for GTP addr %u (should be 133)\n"
" len for addr of UPF %u (should be IPv4 or IPv6 len)"
" (TS 29.281 Sec 7.3.1 Error Handling not implemented)\n",
msg->h.teid,
ntohl(msg->h.teid),
msg->teid_data_i,
msg->teid,
ntohl(msg->teid),
msg->addr_data_i,
msg->addr_len);
int rc = GTPNOK;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment