Commit f5c90ead authored by Robert Schmidt's avatar Robert Schmidt

Free DU at CU on lost connection, store assoc ID

- store the assoc ID of a UE at the RRC
- if F1 receives an SCTP shutdown, it removes the endpoint
- F1 will also send an "F1 Lost Connection" message to the RRC
- it is not yet possible to reconnect a DU after it had already been
  connected at the CU, since the CU F1AP task will try to rebind GTP,
  which fails
parent 62fd56f9
......@@ -32,6 +32,9 @@ MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t
MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure)
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update)
/* F1AP -> RRC to inform about lost connection */
MESSAGE_DEF(F1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, f1ap_lost_connection_t, f1ap_lost_connection)
/* MAC -> F1AP messages */
MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_initial_ul_rrc_message_t , f1ap_initial_ul_rrc_message)
MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_rrc_message_t , f1ap_ul_rrc_message)
......
......@@ -39,6 +39,8 @@
#define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure
#define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure
#define F1AP_LOST_CONNECTION(mSGpTR) (mSGpTR)->ittiMsg.f1ap_lost_connection
#define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message
#define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message
#define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req
......@@ -405,4 +407,8 @@ typedef struct f1ap_paging_ind_s {
uint8_t paging_drx;
} f1ap_paging_ind_t;
typedef struct f1ap_lost_connection_t {
int dummy;
} f1ap_lost_connection_t;
#endif /* F1AP_MESSAGES_TYPES_H_ */
......@@ -63,3 +63,13 @@ void createF1inst(instance_t instanceP, f1ap_setup_req_t *req, f1ap_net_config_t
f1_inst[0]->net_config = *nc;
pthread_mutex_unlock(&f1_inst_mtx);
}
void destroyF1inst(instance_t instance)
{
DevAssert(instance == 0);
pthread_mutex_lock(&f1_inst_mtx);
AssertFatal(f1_inst[0] != NULL, "Attempted to free uninitialized F1 instances\n");
free(f1_inst[instance]);
f1_inst[instance] = NULL;
pthread_mutex_unlock(&f1_inst_mtx);
}
......@@ -418,6 +418,7 @@ uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_m
f1ap_cudu_inst_t *getCxt(instance_t instanceP);
void createF1inst(instance_t instanceP, f1ap_setup_req_t *req, f1ap_net_config_t *nc);
void destroyF1inst(instance_t instance);
//lts: C struct type is not homogeneous, so we need macros instead of functions
#define addnRCGI(nRCGi, servedCelL) \
......
......@@ -94,6 +94,7 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance,
}
MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_SETUP_REQ);
message_p->ittiMsgHeader.originInstance = assoc_id;
f1ap_setup_req_t *req = &F1AP_SETUP_REQ(message_p);
/* gNB_DU_id */
// this function exits if the ie is mandatory
......
......@@ -71,6 +71,18 @@ static void cu_task_handle_sctp_association_ind(instance_t instance,
static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
DevAssert(sctp_new_association_resp != NULL);
if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) {
f1ap_cudu_inst_t *f1ap_cu_data = getCxt(instance);
AssertFatal(f1ap_cu_data != NULL, "illegal state: SCTP shutdown for non-existing F1AP endpoint\n");
LOG_I(F1AP, "Received SCTP shutdown for assoc_id %d, removing endpoint\n", sctp_new_association_resp->assoc_id);
destroyF1inst(instance);
/* inform RRC that the DU is gone */
MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_LOST_CONNECTION);
message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id;
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
return;
}
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
sctp_new_association_resp->sctp_state,
......
......@@ -369,6 +369,7 @@ typedef struct cucp_cuup_if_s {
} cucp_cuup_if_t;
typedef struct nr_rrc_du_container_t {
int assoc_id;
f1ap_setup_req_t *setup_req;
NR_MIB_t *mib;
NR_SIB1_t *sib1;
......
......@@ -1801,12 +1801,12 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell
&& rrc->nr_cellid == info->nr_cellid;
}
static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req)
static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, int assoc_id)
{
gNB_RRC_INST *rrc = RC.nrrrc[0];
DevAssert(rrc);
LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s)\n", req->gNB_DU_id, req->gNB_DU_name);
LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id);
// check:
// - it is the first DU
......@@ -1876,6 +1876,7 @@ static void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req)
// we accept the DU
rrc->du = calloc(1, sizeof(*rrc->du));
AssertFatal(rrc->du != NULL, "out of memory\n");
rrc->du->assoc_id = assoc_id;
/* ITTI will free the setup request message via free(). So the memory
* "inside" of the message will remain, but the "outside" container no, so
......@@ -2423,6 +2424,21 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
prepare_and_send_ue_context_modification_f1(ue_context_p, resp);
}
static void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, int assoc_id)
{
AssertFatal(rrc->du != NULL, "no DU connected, cannot received F1 lost connection\n");
AssertFatal(rrc->du->assoc_id == assoc_id,
"previously connected DU (%d) does not match DU for which connection has been lost (%d)\n",
rrc->du->assoc_id,
assoc_id);
(void) lc; // unused for the moment
ASN_STRUCT_FREE(asn_DEF_NR_MIB, rrc->du->mib);
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, rrc->du->sib1);
free(rrc->du);
rrc->du = NULL;
LOG_I(RRC, "dropping DU with assoc_id %d (UE connections remain, if any)\n", assoc_id);
}
static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults)
{
DevAssert(measresults->measResultServingMOList.list.count >= 1);
......@@ -2621,7 +2637,7 @@ void *rrc_gnb_task(void *args_p) {
/* Messages from F1AP task */
case F1AP_SETUP_REQ:
AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n");
rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p));
rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p), msg_p->ittiMsgHeader.originInstance);
break;
case F1AP_UE_CONTEXT_SETUP_RESP:
......@@ -2644,6 +2660,10 @@ void *rrc_gnb_task(void *args_p) {
rrc_CU_process_ue_context_release_complete(msg_p);
break;
case F1AP_LOST_CONNECTION:
rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance);
break;
/* Messages from X2AP */
case X2AP_ENDC_SGNB_ADDITION_REQ:
LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n");
......
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