Commit ef14a2b9 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/issue-911-fix' into integration_2026_w10 (!3697)

fix: issue 911 - OAI gNB hangs when AMF connection goes down

Once the AMF is down, based on the AMF UE NGAP ID and RAN UE NGAP ID,
the UE associated with the AMF is found

All the contexts related to the UE are released and the timer is started
in the NGAP to look up for the SCTP association. The AMF-gNB reconnection
is made if an SCTP connection is found, also the registration of multiple
UE is triggered

These actions are based on the reference from 4.2.6 AN release Specs
TS 123 502 V16.7.0 (2021-01)

When the NG-AP signalling connection is lost due to (R)AN or AMF failure,
the AN release is performed locally by the AMF or the (R)AN as described
in the procedure flow below without using or relying on any of the signalling
shown between (R)AN and AMF. The AN release causes all UP connections of the UE
to be deactivated.

closes #911
parents 5b66b537 c90d7f7f
......@@ -73,6 +73,7 @@ MESSAGE_DEF(NGAP_HANDOVER_NOTIFY, MESSAGE_PRIORITY_MED, ngap_handover_notify_t,
MESSAGE_DEF(NGAP_HANDOVER_CANCEL, MESSAGE_PRIORITY_MED, ngap_handover_cancel_t, ngap_handover_cancel)
MESSAGE_DEF(NGAP_UL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_ul_ran_status_transfer)
MESSAGE_DEF(NGAP_DL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_dl_ran_status_transfer)
MESSAGE_DEF(NGAP_RECONNECT_TIMER, MESSAGE_PRIORITY_MED, IttiMsgText, ngap_gNB_amf_data)
/* NGAP -> RRC messages */
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
......
......@@ -94,6 +94,38 @@ uint32_t ngap_generate_gNB_id(void)
return gNB_id;
}
static void ngap_gNB_redial_amf(ngap_gNB_amf_data_t *amf_desc_p)
{
NGAP_INFO("AMF cnx_id = %u\n", amf_desc_p->cnx_id);
NGAP_INFO("AMF state = %d\n", amf_desc_p->state);
/*reconnect with the amf */
MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req_t *req = &message_p->ittiMsg.sctp_new_association_req;
/*amf descriptor */
req->port = NGAP_PORT_NUMBER;
req->ppid = NGAP_SCTP_PPID;
req->in_streams = amf_desc_p->in_streams;
req->out_streams = amf_desc_p->out_streams;
req->ulp_cnx_id = amf_desc_p->cnx_id;
ngap_gNB_instance_t *inst = amf_desc_p->ngap_gNB_instance;
memcpy(&req->remote_address, &amf_desc_p->amf_s1_ip, sizeof(req->remote_address));
memcpy(&req->local_address, &inst->gNB_ng_ip, sizeof(req->local_address));
NGAP_INFO("[gNB %ld] Re-dial AMF cnx_id=%u (streams in=%u out=%u)\n",
inst->instance,
amf_desc_p->cnx_id,
req->in_streams,
req->out_streams);
inst->ngap_amf_nb++;
inst->ngap_amf_pending_nb++;
itti_send_msg_to_task(TASK_SCTP, inst->instance, message_p);
}
static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p,
net_ip_address_t *amf_ip_address,
net_ip_address_t *local_ip_addr,
......@@ -551,6 +583,15 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
ngap_gNB_handle_sctp_association_resp(instance, &received_msg->ittiMsg.sctp_new_association_resp);
break;
case TIMER_HAS_EXPIRED: {
timer_has_expired_t *th = &received_msg->ittiMsg.timer_has_expired;
ngap_gNB_amf_data_t *amf_desc_p = (ngap_gNB_amf_data_t *)th->arg;
if (amf_desc_p) {
ngap_gNB_redial_amf(amf_desc_p);
}
break;
}
case SCTP_DATA_IND:
ngap_gNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind);
break;
......
......@@ -161,6 +161,8 @@ struct ngap_gNB_instance_s;
/* This structure describes association of a gNB to a AMF */
typedef struct ngap_gNB_amf_data_s {
long t_reconnect; // ITTI timer id (or equivalent)
/* AMF descriptors tree, ordered by sctp assoc id */
RB_ENTRY(ngap_gNB_amf_data_s) entry;
......
......@@ -78,6 +78,8 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut
/* Decrease associated AMF number */
amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb --;
}
/* Release UE context and start reconnection process*/
ngap_release_ues_for_amf(amf_desc_p);
/* If there are no more associated AMF, inform gNB app */
if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb == 0) {
......
......@@ -59,7 +59,7 @@
#include "s1ap_messages_types.h"
#include "xer_encoder.h"
#include "ds/byte_array.h"
#include "intertask_interface.h"
/** @brief Selects the AMF instance for a given UE based on identity information.
* It attempts to select an AMF using the following prioritized criteria:
* 1. GUAMI, if provided and valid (via Region ID, Set ID, Pointer).
......
......@@ -34,6 +34,8 @@
#include "common/utils/T/T.h"
#include "ngap_common.h"
#include "tree.h"
#include "intertask_interface.h"
#define SCTP_LOOKUP_TIMER_TIMEOUT_SEC 30
/* Tree of UE ordered by gNB_ue_ngap_id's
* NO INSTANCE, the 32 bits id is large enough to handle all UEs, regardless the cell, gNB, ...
......@@ -92,3 +94,31 @@ struct ngap_gNB_ue_context_s *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id)
RB_REMOVE(ngap_ue_map, &ngap_ue_head, tmp);
return tmp;
}
void ngap_release_ues_for_amf(ngap_gNB_amf_data_t *amf_desc_p)
{
/* Release all UE contexts for this AMF */
ngap_gNB_ue_context_t *ue = NULL;
ngap_gNB_ue_context_t *next = NULL;
RB_FOREACH_SAFE(ue, ngap_ue_map, &ngap_ue_head, next) {
if (ue->amf_ref == amf_desc_p) {
LOG_I(NGAP, "Releasing UE context: gNB UE NGAP ID: %u | AMF UE NGAP ID: %lu\n", ue->gNB_ue_ngap_id, ue->amf_ue_ngap_id);
MessageDef *msg_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_UE_CONTEXT_RELEASE_COMMAND);
NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id = ue->gNB_ue_ngap_id;
itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, msg_p);
}
}
/* Reset AMF connection and set reconnect timer */
/* SCTP lookup timer */
long tid;
int rc = timer_setup(SCTP_LOOKUP_TIMER_TIMEOUT_SEC,
0,
TASK_NGAP,
amf_desc_p->ngap_gNB_instance->instance,
TIMER_ONE_SHOT,
amf_desc_p,
&tid);
if (rc == 0) {
amf_desc_p->t_reconnect = tid;
}
}
......@@ -74,6 +74,7 @@ typedef struct ngap_gNB_ue_context_s {
} ngap_gNB_ue_context_t;
void ngap_store_ue_context(const ngap_gNB_ue_context_t *ue_desc_p);
void ngap_release_ues_for_amf(ngap_gNB_amf_data_t *amf_desc_p);
ngap_gNB_ue_context_t *ngap_get_ue_context(uint32_t gNB_ue_ngap_id);
ngap_gNB_ue_context_t *ngap_get_ue_context_from_amf_ue_ngap_id(uint32_t amf_ue_ngap_id);
......
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