Compare commits

...

2 Commits

9 changed files with 126 additions and 33 deletions

View File

@@ -475,6 +475,16 @@ typedef struct pdu_session_to_mod_s {
DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS];
} pdu_session_to_mod_t;
/**
* PDU Session Resource To Remove List (clause 9.3.3.12)
*/
typedef struct pdu_session_to_rem_s {
// PDU Session ID (M)
long sessionId;
// Cause (O)
e1ap_cause_t cause;
} pdu_session_to_rem_t;
/**
* Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463
*/
@@ -534,6 +544,9 @@ typedef struct e1ap_bearer_mod_req_s {
// NG-RAN PDU Session Resource To Modify List (O)
int numPDUSessionsMod;
pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
// NG-RAN PDU Session Resource To Remove List (O)
int numPDUSessionsRem;
pdu_session_to_rem_t pduSessionRem[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_mod_req_t;
typedef struct e1ap_bearer_release_cmd_s {

View File

@@ -380,7 +380,6 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
instance_t f1inst = get_f1_gtp_instance();
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
@@ -401,8 +400,6 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE,
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid);
nr_rlc_release_entity(UE->rnti, lcid);
if (f1inst >= 0)
newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
long *plcid = malloc(sizeof(*plcid));
AssertFatal(plcid, "out of memory\n");

View File

@@ -247,7 +247,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
*/
void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
{
AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n");
AssertFatal(req->numPDUSessionsMod > 0 || req->numPDUSessionsRem > 0, "need at least one PDU session to modify\n");
e1ap_bearer_modif_resp_t modif = {
.gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id,
@@ -330,6 +330,16 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
}
}
/* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */
for (int i = 0; i < req->numPDUSessionsRem; i++) {
instance_t f1inst = get_f1_gtp_instance();
instance_t n3inst = get_n3_gtp_instance();
instance_t inst = f1inst >= 0 ? f1inst : n3inst; // is there F1-U?
newGtpuDeleteOneTunnel(inst, req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId);
nr_pdcp_release_from_pdusession(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId);
nr_sdap_delete_entity(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId);
}
get_e1_if()->bearer_modif_response(&modif);
}

View File

@@ -926,6 +926,18 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id)
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
void nr_pdcp_release_from_pdusession(ue_id_t ue_id, long pdusession_id)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
const nr_pdcp_entity_t *drb = ue->drb[i];
if (drb && drb->pdusession_id == pdusession_id)
nr_pdcp_release_drb(ue_id, i + 1);
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
void nr_pdcp_reestablishment(ue_id_t ue_id,
int rb_id,
bool srb_flag,

View File

@@ -69,6 +69,7 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering);
void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_config);
void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id);
void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id);
void nr_pdcp_release_from_pdusession(ue_id_t ue_id, long pdusession_id);
void add_srb(int is_gnb,
ue_id_t UEid,

View File

@@ -689,7 +689,7 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
{
/* do not re-establish PDCP for any bearer */
nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false);
ue_p->xids[params.transaction_id] = RRC_PDUSESSION_ESTABLISH;
ue_p->xids[params.transaction_id] = RRC_DEDICATED_RECONF;
byte_array_t msg = rrc_gNB_encode_RRCReconfiguration(rrc, ue_p, params);
if (msg.len <= 0) {
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
@@ -697,10 +697,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
}
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) {
if (params.num_nas_msg > 0) {
ue_p->pduSession[i].xid = params.transaction_id;
ue_p->xids[params.transaction_id] = RRC_PDUSESSION_ESTABLISH;
}
if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) {
if (ue_p->pduSession[i].status == PDU_SESSION_STATUS_NEW || ue_p->pduSession[i].status == PDU_SESSION_STATUS_RELEASED) {
ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
}
}
@@ -792,24 +793,46 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
free_byte_array(msg);
}
//-----------------------------------------------------------------------------
typedef struct deliver_ue_ctxt_modification_data_t {
gNB_RRC_INST *rrc;
f1ap_ue_context_mod_req_t *modification_req;
sctp_assoc_t assoc_id;
} deliver_ue_ctxt_modification_data_t;
static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
{
DevAssert(deliver_pdu_data != NULL);
deliver_ue_ctxt_modification_data_t *data = deliver_pdu_data;
byte_array_t rrc_cont = {.buf = (uint8_t *)buf, .len = size};
data->modification_req->rrc_container = &rrc_cont;
data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req);
}
void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *ue_p,
uint8_t xid,
uint32_t nas_length,
uint8_t *nas_buffer)
//-----------------------------------------------------------------------------
{
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1);
f1ap_drb_to_release_t rel_drbs[32];
int n_rel_drbs = 0;
NR_DRB_ToReleaseList_t *drb_release_list = calloc_or_fail(1, sizeof(*drb_release_list));
if (!ue_p->DRB_ReleaseList)
ue_p->DRB_ReleaseList = calloc_or_fail(1, sizeof(*ue_p->DRB_ReleaseList));
for (int i = 0; i < NB_RB_MAX; i++) {
if ((ue_p->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_p->pduSession[i].xid == xid) {
asn1cSequenceAdd(DRB_Release_configList2->list, NR_DRB_Identity_t, DRB_release);
asn1cSequenceAdd(drb_release_list->list, NR_DRB_Identity_t, DRB_release);
asn1cSequenceAdd(ue_p->DRB_ReleaseList->list, NR_DRB_Identity_t, DRB_release2);
*DRB_release = i + 1;
*DRB_release2 = i + 1;
rel_drbs[n_rel_drbs].id = *DRB_release;
n_rel_drbs++;
memset(&ue_p->established_drbs[i], 0, sizeof(drb_t));
}
}
nr_rrc_reconfig_param_t params = {.drb_release_list = DRB_Release_configList2, .transaction_id = xid};
nr_rrc_reconfig_param_t params = {.drb_release_list = drb_release_list, .transaction_id = xid};
if (nas_length > 0) {
params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer;
params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length;
@@ -821,8 +844,30 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
}
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n");
LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %ld)\n", ue_p->rrc_ue_id, msg.len);
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
plmn_id_t plmn = rrc->configuration.plmn[0];
uint64_t nr_cellid = rrc->nr_cellid;
f1ap_ue_context_mod_req_t ue_context_modif_req = {
.gNB_CU_ue_id = ue_p->rrc_ue_id,
.gNB_DU_ue_id = ue_data.secondary_ue,
.plmn = &plmn,
.nr_cellid = &nr_cellid,
.servCellIndex = 0,
.drbs_rel_len = n_rel_drbs,
.drbs_rel = (f1ap_drb_to_release_t *)rel_drbs,
};
deliver_ue_ctxt_modification_data_t data = {.rrc = rrc,
.modification_req = &ue_context_modif_req,
.assoc_id = ue_data.du_assoc_id};
nr_pdcp_data_req_srb(ue_p->rrc_ue_id,
DL_SCH_LCID_DCCH,
rrc_gNB_mui++,
msg.len,
(unsigned char *const)msg.buf,
rrc_deliver_ue_ctxt_modif_req,
&data);
free_RRCReconfiguration_params(params);
free_byte_array(msg);
}
@@ -1771,8 +1816,6 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U
switch (UE->xids[xid]) {
case RRC_PDUSESSION_RELEASE: {
gtpv1u_gnb_delete_tunnel_req_t req = {0};
gtpv1u_delete_ngu_tunnel(rrc->module_id, &req);
// NGAP_PDUSESSION_RELEASE_RESPONSE
rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(rrc, UE, xid);
} break;

View File

@@ -1436,14 +1436,15 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE
memset(resp, 0, sizeof(*resp));
resp->gNB_ue_ngap_id = UE->rrc_ue_id;
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
if (xid == UE->pduSession[i].xid) {
for (int i = 0; i < NGAP_MAX_PDU_SESSION; i++) {
if (UE->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE && xid == UE->pduSession[i].xid) {
resp->pdusession_release[pdu_sessions_released].pdusession_id = UE->pduSession[i].param.pdusession_id;
pdu_sessions_released++;
//clear
memset(&UE->pduSession[i], 0, sizeof(*UE->pduSession));
UE->pduSession[i].status = PDU_SESSION_STATUS_RELEASED;
LOG_W(NR_RRC, "Released pdu session, but code to finish to free memory\n");
UE->nb_of_pdusessions--;
LOG_W(NR_RRC, "Released pdu session, current nb_of_pdusessions %d for UE %x\n", UE->nb_of_pdusessions, UE->rnti);
}
}
@@ -1472,7 +1473,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
LOG_I(
NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu rrc_ue_id %u release_pdusessions %d \n", cmd->amf_ue_ngap_id, gNB_ue_ngap_id, cmd->nb_pdusessions_torelease);
bool found = false;
e1ap_bearer_mod_req_t req = {0};
uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
UE->xids[xid] = RRC_PDUSESSION_RELEASE;
for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) {
@@ -1491,14 +1492,23 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
continue;
}
if (pduSession->status == PDU_SESSION_STATUS_ESTABLISHED) {
found = true;
LOG_I(NR_RRC, "RELEASE pdusession %d \n", pduSession->param.pdusession_id);
req.pduSessionRem[req.numPDUSessionsRem].sessionId = pduSession->param.pdusession_id;
req.pduSessionRem[req.numPDUSessionsRem].cause.type = E1AP_CAUSE_RADIO_NETWORK;
req.pduSessionRem[req.numPDUSessionsRem].cause.value = E1AP_RADIO_CAUSE_NORMAL_RELEASE;
req.numPDUSessionsRem++;
pduSession->status = PDU_SESSION_STATUS_TORELEASE;
pduSession->xid = xid;
}
}
if (found) {
if (req.numPDUSessionsRem > 0) {
if (ue_associated_to_cuup(rrc, UE)) {
req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
req.gNB_cu_up_ue_id = UE->rrc_ue_id;
sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
rrc->cucp_cuup.bearer_context_mod(assoc_id, &req);
}
// TODO RRCReconfiguration To UE
LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n");
rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.len, cmd->nas_pdu.buf);

View File

@@ -43,17 +43,23 @@ void cp_pdusession(pdusession_t *dst, const pdusession_t *src)
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
{
int j;
for (j = 0; j < ue->nb_of_pdusessions; j++)
if (id == ue->pduSession[j].param.pdusession_id)
break;
if (j == ue->nb_of_pdusessions) {
if (create)
ue->nb_of_pdusessions++;
else
return NULL;
for (int j = 0; j < NGAP_MAX_PDU_SESSION; j++) {
if (ue->pduSession[j].param.pdusession_id == id)
return &ue->pduSession[j];
}
return ue->pduSession + j;
if (create && ue->nb_of_pdusessions < NGAP_MAX_PDU_SESSION) {
ue->nb_of_pdusessions++;
AssertFatal(ue->nb_of_pdusessions <= NGAP_MAX_PDU_SESSION,
"nb_of_pdusessions %i exceeds NGAP_MAX_PDU_SESSION %i\n",
ue->nb_of_pdusessions,
NGAP_MAX_PDU_SESSION);
for (int j = 0; j < NGAP_MAX_PDU_SESSION; j++) {
if (ue->pduSession[j].param.pdusession_id == 0)
return &ue->pduSession[j];
}
}
return NULL;
}
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id)

View File

@@ -611,7 +611,8 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
ret = true;
}
}
LOG_E(SDAP, "Entity does not exist or it was not found.\n");
if (!ret)
LOG_E(SDAP, "Entity does not exist or it was not found.\n");
return ret;
}