diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 09e893f874..36528357f1 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -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 ) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 257ca25f1a..e8fee7f34a 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -93,6 +93,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, @@ -550,6 +582,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; diff --git a/openair3/NGAP/ngap_gNB_defs.h b/openair3/NGAP/ngap_gNB_defs.h index 1a1e5768ff..b7c5dc3f64 100644 --- a/openair3/NGAP/ngap_gNB_defs.h +++ b/openair3/NGAP/ngap_gNB_defs.h @@ -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; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 9113f850ca..be0361afbd 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -77,6 +77,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) { diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 2d4bd3eefa..9e341494c6 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -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). diff --git a/openair3/NGAP/ngap_gNB_ue_context.c b/openair3/NGAP/ngap_gNB_ue_context.c index 994271d822..e50726380f 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.c +++ b/openair3/NGAP/ngap_gNB_ue_context.c @@ -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; + } +} diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h index 8053e8f8c6..1ca458968f 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.h +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -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);