Commit badb0c56 authored by Guido Casati's avatar Guido Casati

source-CU-CP: trigger UL NG RAN Status Transfer upon reception of PDCP Status...

source-CU-CP: trigger UL NG RAN Status Transfer upon reception of PDCP Status in E1 Bearer Context Modification Response

Once fetched the PDCP Status from the PDCP entity over E1, the CU-CP triggers
the NG RAN Status Transfer procedure to transfer the PDCP Status to the target
CU.

This commit is also introducing the RRC callback.
parent 44e4ebc4
......@@ -2600,10 +2600,23 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t
return;
}
// there is not really anything to do here as of now
int n_drb_mod = 0;
e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0};
for (int i = 0; i < resp->numPDUSessionsMod; ++i) {
const pdu_session_modif_t *pdu = &resp->pduSessionMod[i];
LOG_I(RRC, "UE %d: PDU session ID %ld modified %d bearers\n", resp->gNB_cu_cp_ue_id, pdu->id, pdu->numDRBModified);
for (int j = 0; j < pdu->numDRBModified; j++) {
// Trigger UL RAN Status Transfer
if (pdu->DRBnGRanModList[j].pdcp_status) {
pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status;
}
}
}
if (n_drb_mod) {
LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id);
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
if (ue->ho_context && ue->ho_context->source)
ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, pdcp_status);
}
}
......
......@@ -1165,6 +1165,52 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg)
free(msg->mobility_restriction);
}
/** @brief Send NG Uplink RAN Status Transfer message (8.4.6 3GPP TS 38.413)
* Direction: source NG-RAN node -> AMF */
int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status)
{
AssertFatal(UE != NULL, "UE context is NULL\n");
LOG_I(NR_RRC,
"Sending NGAP Uplink RAN Status Transfer (AMF_UE_NGAP_ID=%" PRIu64 ", GNB_UE_NGAP_ID=%u)\n",
UE->amf_ue_ngap_id,
UE->rrc_ue_id);
ngap_ran_status_transfer_t msg = {
.amf_ue_ngap_id = UE->amf_ue_ngap_id,
.gnb_ue_ngap_id = UE->rrc_ue_id,
};
// Loop through DRBs and extract COUNT values
for (int i = 0; i < n_to_mod; ++i) {
drb_t *drb = &UE->established_drbs[i];
if (!drb->status)
continue;
bool sn_length_18 = rrc->pdcp_config.drb.sn_size == 18;
ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++];
item->drb_id = drb->drb_id;
const e1_pdcp_count_t *ul_pdcp = &pdcp_status[i].ul_count;
const e1_pdcp_count_t *dl_pdcp = &pdcp_status[i].dl_count;
item->ul_count.pdcp_sn = ul_pdcp->sn;
item->ul_count.hfn = ul_pdcp->hfn;
item->ul_count.sn_len = sn_length_18 ? NGAP_SN_LENGTH_18 : NGAP_SN_LENGTH_12;
item->dl_count.pdcp_sn = dl_pdcp->sn;
item->dl_count.hfn = dl_pdcp->hfn;
item->dl_count.sn_len = sn_length_18 ? NGAP_SN_LENGTH_18 : NGAP_SN_LENGTH_12;
}
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UL_RAN_STATUS_TRANSFER);
NGAP_UL_RAN_STATUS_TRANSFER(msg_p) = msg;
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p);
return 0;
}
/** @brief Process NG Handover Command on Source gNB */
void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_command_t *msg)
{
......
......@@ -106,4 +106,6 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg);
void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE);
int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status);
#endif
......@@ -545,6 +545,7 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc,
ue->ho_context = alloc_ho_ctx(HO_CTX_SOURCE);
ue->ho_context->source->du = get_du_for_ue(rrc, ue->rrc_ue_id);
ue->ho_context->source->ho_status_transfer = rrc_gNB_send_NGAP_ul_ran_status_transfer;
rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo);
free_byte_array(hoPrepInfo);
......
......@@ -33,6 +33,8 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t;
typedef struct NR_CellGroupConfig NR_CellGroupConfig_t;
typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue);
typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status);
typedef struct nr_ho_source_cu {
/// pointer to the (source) DU structure
const nr_rrc_du_container_t *du;
......@@ -48,6 +50,8 @@ typedef struct nr_ho_source_cu {
/// function pointer to announce the handover cancellation, e.g.,
/// reestablishment
ho_cancel_t ho_cancel;
/// status transfer
ho_status_transfer_t ho_status_transfer;
} nr_ho_source_cu_t;
/* acknowledgement of handover request. buf+len is the RRC Reconfiguration */
......
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