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
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user