Implement basic F1 release procedure using F1 internally
This commit is contained in:
@@ -39,6 +39,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r
|
||||
//MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete)
|
||||
|
||||
/* RRC -> F1AP messages */
|
||||
MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message )
|
||||
|
||||
@@ -41,14 +41,14 @@
|
||||
#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
|
||||
#define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp
|
||||
#define F1AP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_resp
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
|
||||
|
||||
#define F1AP_DL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_dl_rrc_message
|
||||
#define F1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req
|
||||
#define F1AP_UE_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req
|
||||
#define F1AP_UE_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_cmd
|
||||
#define F1AP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_complete
|
||||
|
||||
#define F1AP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.f1ap_paging_ind
|
||||
|
||||
|
||||
@@ -165,6 +165,10 @@ void *F1AP_DU_task(void *arg) {
|
||||
&F1AP_UE_CONTEXT_RELEASE_REQ(msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_RELEASE_COMPLETE:
|
||||
DU_send_UE_CONTEXT_RELEASE_COMPLETE(myInstance, &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg));
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(F1AP, " *** Exiting F1AP thread\n");
|
||||
itti_exit_task();
|
||||
|
||||
@@ -2785,6 +2785,16 @@ void nr_mac_update_timers(module_id_t module_id,
|
||||
NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
|
||||
if (nr_mac_check_release(sched_ctrl, UE->rnti)) {
|
||||
nr_rlc_remove_ue(UE->rnti);
|
||||
mac_remove_nr_ue(RC.nrmac[module_id], UE->rnti);
|
||||
// go back to examine the next UE, which is at the position the
|
||||
// current UE was
|
||||
UE--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sched_ctrl->rrc_processing_timer > 0) {
|
||||
sched_ctrl->rrc_processing_timer--;
|
||||
if (sched_ctrl->rrc_processing_timer == 0) {
|
||||
@@ -2946,3 +2956,17 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
DevAssert(bearer->servedRadioBearer->choice.srb_Identity == 1);
|
||||
nr_rlc_add_srb(UE->rnti, DCCH, bearer);
|
||||
}
|
||||
|
||||
void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
|
||||
{
|
||||
// trigger 60ms
|
||||
sched_ctrl->release_timer = 60 << subcarrier_spacing;
|
||||
}
|
||||
|
||||
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti)
|
||||
{
|
||||
if (sched_ctrl->release_timer == 0)
|
||||
return false;
|
||||
sched_ctrl->release_timer--;
|
||||
return sched_ctrl->release_timer == 0;
|
||||
}
|
||||
|
||||
@@ -671,8 +671,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) {
|
||||
LOG_W(NR_MAC,"Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
|
||||
UE->UE_sched_ctrl.ul_failure = 1;
|
||||
|
||||
nr_mac_gNB_rrc_ul_failure(gnb_mod_idP,CC_idP,frameP,slotP,rntiP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,4 +440,7 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu
|
||||
|
||||
void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid);
|
||||
|
||||
void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
|
||||
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti);
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -149,7 +149,29 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
|
||||
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
{
|
||||
AssertFatal(false, "not implemented\n");
|
||||
/* mark UE as to be deleted after PUSCH failure */
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
pthread_mutex_lock(&mac->sched_lock);
|
||||
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->rnti);
|
||||
if (UE->UE_sched_ctrl.ul_failure > 0 || cmd->rrc_container_length == 0) {
|
||||
/* The UE is already not connected anymore or we have nothing to forward*/
|
||||
nr_rlc_remove_ue(cmd->rnti);
|
||||
mac_remove_nr_ue(mac, cmd->rnti);
|
||||
} else {
|
||||
/* UE is in sync: forward release message and mark to be deleted
|
||||
* after UL failure */
|
||||
nr_rlc_srb_recv_sdu(cmd->rnti, cmd->srb_id, cmd->rrc_container, cmd->rrc_container_length);
|
||||
nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
|
||||
}
|
||||
pthread_mutex_unlock(&mac->sched_lock);
|
||||
|
||||
f1ap_ue_context_release_complete_t complete = {
|
||||
.rnti = cmd->rnti,
|
||||
};
|
||||
mac->mac_rrc.ue_context_release_complete(&complete);
|
||||
|
||||
if (cmd->rrc_container)
|
||||
free(cmd->rrc_container);
|
||||
}
|
||||
|
||||
int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
|
||||
@@ -62,7 +62,10 @@ static void ue_context_release_request_direct(const f1ap_ue_context_release_req_
|
||||
|
||||
static void ue_context_release_complete_direct(const f1ap_ue_context_release_complete_t *complete)
|
||||
{
|
||||
AssertFatal(false, "not implemented\n");
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE);
|
||||
f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg);
|
||||
*f1ap_msg = *complete;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc)
|
||||
|
||||
@@ -592,6 +592,7 @@ typedef struct {
|
||||
int pusch_consecutive_dtx_cnt;
|
||||
int pucch_consecutive_dtx_cnt;
|
||||
int ul_failure;
|
||||
int release_timer;
|
||||
struct CSI_Report CSI_report;
|
||||
bool SR;
|
||||
/// information about every HARQ process
|
||||
|
||||
+41
-38
@@ -2589,6 +2589,21 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
|
||||
* messages (UE capability, to be specific) */
|
||||
}
|
||||
|
||||
static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p)
|
||||
{
|
||||
const int instance = 0;
|
||||
f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p);
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[instance];
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, complete->rnti);
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
nr_pdcp_remove_UE(UE->rnti);
|
||||
newGtpuDeleteAllTunnels(instance, UE->rnti);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, UE->gNB_ue_ngap_id);
|
||||
LOG_I(NR_RRC, "removed UE %04x \n", UE->rnti);
|
||||
rrc_gNB_remove_ue_context(rrc, ue_context_p);
|
||||
}
|
||||
|
||||
static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance)
|
||||
{
|
||||
f1ap_ue_context_setup_t *resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
|
||||
@@ -3162,9 +3177,12 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_DU_process_ue_context_modification_request(msg_p, instance);
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_RELEASE_CMD:
|
||||
LOG_W(NR_RRC, "Received F1AP_UE_CONTEXT_RELEASE_CMD for processing at the RRC layer of the DU. Processing function "
|
||||
"implementation is pending\n");
|
||||
case F1AP_UE_CONTEXT_RELEASE_REQ:
|
||||
AssertFatal(false, "F1 UE context release request to be implemented\n");
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_RELEASE_COMPLETE:
|
||||
rrc_CU_process_ue_context_release_complete(msg_p);
|
||||
break;
|
||||
|
||||
/* Messages from X2AP */
|
||||
@@ -3292,6 +3310,24 @@ rrc_gNB_generate_UECapabilityEnquiry(
|
||||
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc);
|
||||
}
|
||||
|
||||
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
gNB_RRC_INST *rrc = deliver_pdu_data;
|
||||
uint8_t *rrc_container = malloc(size);
|
||||
AssertFatal(rrc_container != NULL, "out of memory\n");
|
||||
memcpy(rrc_container, buf, size);
|
||||
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
|
||||
.rnti = ue_id, /* TODO: proper IDs! */
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
|
||||
.srb_id = srb_id,
|
||||
.rrc_container = rrc_container,
|
||||
.rrc_container_length = size,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_release_command(&ue_context_release_cmd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
* Generate the RRC Connection Release to UE.
|
||||
@@ -3306,49 +3342,16 @@ rrc_gNB_generate_RRCRelease(
|
||||
{
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id));
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
|
||||
ue_p->ue_reestablishment_timer = 0;
|
||||
ue_p->ue_release_timer = 0;
|
||||
ue_p->ul_failure_timer = 0;
|
||||
ue_p->ue_release_timer_rrc = 0;
|
||||
LOG_I(NR_RRC,
|
||||
PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCRelease (bytes %d)\n",
|
||||
PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
|
||||
size);
|
||||
LOG_D(NR_RRC,
|
||||
PROTOCOL_NR_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcRelease MUI %d) --->[PDCP][RB %u]\n",
|
||||
PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
|
||||
size,
|
||||
rrc_gNB_mui,
|
||||
DCCH);
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc);
|
||||
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, rrc);
|
||||
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(ctxt_pP->instance, ue_context_pP->ue_context.gNB_ue_ngap_id);
|
||||
ue_context_pP->ue_context.ue_release_timer_rrc = 1;
|
||||
/* TODO: 38.331 says for RRC Release that the UE should release everything
|
||||
* after 60ms or if lower layers acked receipt of release. Hence, from the
|
||||
* gNB POV, we can free the UE's RRC context as soon as we sent the msg.
|
||||
* Currently, without the F1 interface, the ue_release timer expiration also
|
||||
* triggers MAC, so we give it some time. If we send an F1 UE Context release
|
||||
* message, we can free it immediately. The MAC should release it after these
|
||||
* 60ms, or the ack of the DLSCH transmission. */
|
||||
ue_context_pP->ue_context.ue_release_timer_thres_rrc = 5;
|
||||
LOG_I(RRC, "delaying UE %ld context removal by 5ms\n", ctxt_pP->rntiMaybeUEid);
|
||||
|
||||
if (NODE_IS_CU(rrc->node_type)) {
|
||||
uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size);
|
||||
memcpy (message_buffer, buffer, size);
|
||||
MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
|
||||
F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rntiMaybeUEid;
|
||||
F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK;
|
||||
F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release
|
||||
F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container = message_buffer;
|
||||
F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container_length = size;
|
||||
itti_send_msg_to_task(TASK_CU_F1, ctxt_pP->module_id, m);
|
||||
}
|
||||
/* UE will be freed after UE context release complete */
|
||||
}
|
||||
|
||||
int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){
|
||||
|
||||
Reference in New Issue
Block a user