Adopt dynamic seq_arr in PDU Session handling (RRC PDU Session)
The RRC PDU Session struct is converted from a fixed-size array to a dynamically sized seq_arr. This improves flexibility and simplifies session management by eliminating arbitrary size limits and enabling dynamic addition/removal of PDU sessions. Helper functions and loops have been adapted to use the seq_arr API. This change is a step toward more robust and maintainable handling of PDU sessions in the gNB RRC layer. The "status" state machine remains untouched in this commit and is refactored in a later commit. Also: * add macro to push to seq_arr and return the new element * move initialization of xid (RRC PDU Session struct) to find_pduSession (temporary, will be finalized in a later commit) since with the new seq_arr design the initialization is no longer possible in the UE context generation (also does not belong to it, initialize when adding a new PDU Session)
This commit is contained in:
@@ -1893,6 +1893,7 @@ target_link_libraries(nr-cuup PRIVATE
|
||||
CONFIG_LIB ITTI SCTP_CLIENT
|
||||
GTPV1U e1ap f1ap
|
||||
time_management
|
||||
alg
|
||||
z dl pthread shlib_loader ${T_LIB})
|
||||
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
if(E2_AGENT)
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
#include "ds/seq_arr.h"
|
||||
|
||||
#if defined (NGRAN_GNB_CUCP)
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h"
|
||||
#endif
|
||||
|
||||
bool read_gtp_sm(void * data)
|
||||
@@ -62,16 +63,15 @@ bool read_gtp_sm(void * data)
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ue_id_list[i]);
|
||||
|
||||
gtp->msg.ngut[i].rnti = ue_id_list[i];
|
||||
int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions;
|
||||
if (nb_pdu_session > 0) {
|
||||
int nb_pdu_idx = nb_pdu_session - 1;
|
||||
gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_outgoing.teid;
|
||||
gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_incoming.teid;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &ue_context_p->ue_context.pduSessions) {
|
||||
gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid;
|
||||
gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid;
|
||||
// TODO: one PDU session has multiple QoS Flow
|
||||
int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos;
|
||||
int nb_qos_flow = session->param.nb_qos;
|
||||
if (nb_qos_flow > 0) {
|
||||
gtp->msg.ngut[i].qfi = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.qos[nb_qos_flow - 1].qfi;
|
||||
gtp->msg.ngut[i].qfi = session->param.qos[nb_qos_flow - 1].qfi;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "openair2/E1AP/e1ap_common.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "ds/seq_arr.h"
|
||||
|
||||
static pthread_once_t once_kpm_mutex = PTHREAD_ONCE_INIT;
|
||||
|
||||
@@ -212,8 +213,8 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info)
|
||||
/* UE has no AMF UE NGAP ID yet => can't send message */
|
||||
if (ue->amf_ue_ngap_id >= (1LL << 40))
|
||||
continue;
|
||||
for (int p = 0; p < ue->nb_of_pdusessions; ++p) {
|
||||
pdusession_t *pdu = &ue->pduSession[p].param;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, item, &ue->pduSessions) {
|
||||
pdusession_t* pdu = &item->param;
|
||||
if (nssai_matches(pdu->nssai, sst, sd)) {
|
||||
arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_CU](ue, 0, 0);
|
||||
|
||||
|
||||
@@ -238,8 +238,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
rb_id_t nsa_gtp_psi[S1AP_MAX_E_RAB];
|
||||
|
||||
//SA block
|
||||
int nb_of_pdusessions;
|
||||
rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION];
|
||||
seq_arr_t pduSessions;
|
||||
|
||||
rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
|
||||
uint8_t e_rab_release_command_flag;
|
||||
uint32_t ue_rrc_inactivity_timer;
|
||||
|
||||
+54
-51
@@ -656,14 +656,16 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC
|
||||
.srb_config_list = SRBs};
|
||||
UE->DRB_ReleaseList = NULL; // pointer transferred to params
|
||||
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
|
||||
if (UE->pduSession[i].param.nas_pdu.len > 0) {
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->pduSession[i].param.nas_pdu;
|
||||
UE->pduSession[i].param.nas_pdu.buf = NULL;
|
||||
UE->pduSession[i].param.nas_pdu.len = 0;
|
||||
LOG_D(NR_RRC, "Transfer NAS info with size %ld (pdusession idx %d) to RRCReconfiguration params\n", UE->pduSession[i].param.nas_pdu.len, i);
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &UE->pduSessions) {
|
||||
pdusession_t *session = &item->param;
|
||||
if (session->nas_pdu.len > 0) {
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++] = session->nas_pdu;
|
||||
session->nas_pdu.buf = NULL;
|
||||
session->nas_pdu.len = 0;
|
||||
LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", session->nas_pdu.len);
|
||||
}
|
||||
}
|
||||
|
||||
if (UE->nas_pdu.len > 0) {
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->nas_pdu;
|
||||
UE->nas_pdu.buf = NULL;
|
||||
@@ -696,12 +698,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) {
|
||||
ue_p->pduSession[i].xid = params.transaction_id;
|
||||
}
|
||||
if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) {
|
||||
if (item->param.nas_pdu.buf)
|
||||
item->xid = params.transaction_id;
|
||||
if (item->status < PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
item->status = PDU_SESSION_STATUS_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,40 +719,41 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false);
|
||||
ue_p->xids[params.transaction_id] = RRC_PDUSESSION_MODIFY;
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
rrc_pdu_session_param_t *session = &ue_p->pduSession[i];
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) {
|
||||
pdusession_t *session = &item->param;
|
||||
// bypass the new and already configured pdu sessions
|
||||
if (session->status >= PDU_SESSION_STATUS_DONE) {
|
||||
session->xid = params.transaction_id;
|
||||
if (item->status >= PDU_SESSION_STATUS_DONE) {
|
||||
item->xid = params.transaction_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session->cause.type != NGAP_CAUSE_NOTHING) {
|
||||
if (item->cause.type != NGAP_CAUSE_NOTHING) {
|
||||
// set xid of failure pdu session
|
||||
session->xid = params.transaction_id;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
item->xid = params.transaction_id;
|
||||
item->status = PDU_SESSION_STATUS_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
// search exist DRB_config
|
||||
int j;
|
||||
for (j = 0; i < MAX_DRBS_PER_UE; j++) {
|
||||
for (j = 0; j < MAX_DRBS_PER_UE; j++) {
|
||||
if (ue_p->established_drbs[j].status != DRB_INACTIVE
|
||||
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->param.pdusession_id)
|
||||
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->pdusession_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == MAX_DRBS_PER_UE) {
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified};
|
||||
session->xid = params.transaction_id;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->cause = cause;
|
||||
item->xid = params.transaction_id;
|
||||
item->status = PDU_SESSION_STATUS_FAILED;
|
||||
item->cause = cause;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
|
||||
for (qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
|
||||
switch (session->param.qos[qos_flow_index].fiveQI) {
|
||||
for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) {
|
||||
pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index];
|
||||
switch (qos->fiveQI) {
|
||||
case 1: //100ms
|
||||
case 2: //150ms
|
||||
case 3: //50ms
|
||||
@@ -765,18 +767,17 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", session->param.qos[qos_flow_index].fiveQI);
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->fiveQI);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value};
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->xid = params.transaction_id;
|
||||
session->cause = cause;
|
||||
item->status = PDU_SESSION_STATUS_FAILED;
|
||||
item->xid = params.transaction_id;
|
||||
item->cause = cause;
|
||||
continue;
|
||||
}
|
||||
LOG_I(NR_RRC, "index %d, QOS flow %d, 5QI %ld \n", i, qos_flow_index, session->param.qos[qos_flow_index].fiveQI);
|
||||
LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->fiveQI);
|
||||
}
|
||||
|
||||
session->status = PDU_SESSION_STATUS_DONE;
|
||||
session->xid = params.transaction_id;
|
||||
item->status = PDU_SESSION_STATUS_DONE;
|
||||
item->xid = params.transaction_id;
|
||||
}
|
||||
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
@@ -800,16 +801,18 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
|
||||
uint8_t *nas_buffer)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1);
|
||||
nr_rrc_reconfig_param_t params = {.transaction_id = xid};
|
||||
|
||||
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);
|
||||
*DRB_release = i + 1;
|
||||
NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1);
|
||||
int i = 0;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) {
|
||||
if ((item->status == PDU_SESSION_STATUS_TORELEASE) && item->xid == xid) {
|
||||
asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release);
|
||||
*DRB_release = ++i; // DRB ID
|
||||
}
|
||||
}
|
||||
params.drb_release_list = to_release;
|
||||
|
||||
nr_rrc_reconfig_param_t params = {.drb_release_list = DRB_Release_configList2, .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;
|
||||
@@ -1783,8 +1786,12 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U
|
||||
UE->n_initial_pdu = 0;
|
||||
free(UE->initial_pdus);
|
||||
UE->initial_pdus = NULL;
|
||||
} else if (UE->nb_of_pdusessions > 0)
|
||||
} else if (seq_arr_size(&UE->pduSessions) > 0)
|
||||
rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(rrc, UE, xid);
|
||||
else
|
||||
LOG_W(NR_RRC,
|
||||
"UE %d: RRC Reconfiguration Complete for PDU session establishment, but no PDU sessions were setup\n",
|
||||
UE->rrc_ue_id);
|
||||
break;
|
||||
case RRC_PDUSESSION_MODIFY:
|
||||
rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(rrc, UE, xid);
|
||||
@@ -2288,6 +2295,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE)
|
||||
free_MeasConfig(UE->measConfig);
|
||||
free(UE->redcap_cap);
|
||||
UE->redcap_cap = NULL;
|
||||
seq_arr_free(&UE->pduSessions, free_pdusession);
|
||||
}
|
||||
|
||||
void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p)
|
||||
@@ -2318,9 +2326,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p)
|
||||
/* only trigger release if it has been requested by core
|
||||
* otherwise, it might be CU that requested release on a DU during normal
|
||||
* operation (i.e, handover) */
|
||||
uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION];
|
||||
get_pduSession_array(UE, pdu_sessions);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions);
|
||||
rrc_remove_ue(RC.nrrrc[0], ue_context_p);
|
||||
}
|
||||
}
|
||||
@@ -2500,7 +2506,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
|
||||
{
|
||||
int nb_drb = 0;
|
||||
for (int p = 0; p < numPduSession; ++p) {
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false);
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession(&UE->pduSessions, pduSession[p].id);
|
||||
DevAssert(pdu);
|
||||
for (int i = 0; i < pduSession[p].numDRBSetup; i++) {
|
||||
const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i];
|
||||
@@ -2569,7 +2575,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
|
||||
// save the tunnel address for the PDU sessions
|
||||
for (int i = 0; i < resp->numPDUSessions; i++) {
|
||||
pdu_session_setup_t *e1_pdu = &resp->pduSession[i];
|
||||
rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false);
|
||||
rrc_pdu_session_param_t *rrc_pdu = find_pduSession(&UE->pduSessions, e1_pdu->id);
|
||||
if (rrc_pdu == NULL) {
|
||||
LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id);
|
||||
continue;
|
||||
@@ -2774,11 +2780,8 @@ static bool write_rrc_stats(const gNB_RRC_INST *rrc)
|
||||
time_t last_seen = now - ue_ctxt->last_seen;
|
||||
fprintf(f, " last RRC activity: %ld seconds ago\n", last_seen);
|
||||
|
||||
if (ue_ctxt->nb_of_pdusessions == 0)
|
||||
fprintf(f, " (no PDU sessions)\n");
|
||||
for (int nb_pdu = 0; nb_pdu < ue_ctxt->nb_of_pdusessions; ++nb_pdu) {
|
||||
const rrc_pdu_session_param_t *pdu = &ue_ctxt->pduSession[nb_pdu];
|
||||
fprintf(f, " PDU session %d ID %d status %s\n", nb_pdu, pdu->param.pdusession_id, get_pdusession_status_text(pdu->status));
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, pdu, &ue_ctxt->pduSessions) {
|
||||
fprintf(f, " PDU session ID %d status %s\n", pdu->param.pdusession_id, get_pdusession_status_text(pdu->status));
|
||||
}
|
||||
|
||||
fprintf(f, " associated DU: ");
|
||||
|
||||
+123
-133
@@ -88,6 +88,7 @@
|
||||
#include "uper_encoder.h"
|
||||
#include "rrc_gNB_mobility.h"
|
||||
#include "rrc_gNB_du.h"
|
||||
#include "common/utils/alg/find.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
|
||||
@@ -278,9 +279,14 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
|
||||
|
||||
e1ap_nssai_t cuup_nssai = {0};
|
||||
for (int i = 0; i < n; i++) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true);
|
||||
rrc_pdu_session_param_t *pduSession = add_pduSession(&UE->pduSessions, &sessions[i]);
|
||||
if (!pduSession) {
|
||||
LOG_E(NR_RRC, "Could not add PDU Session %d for UE %d\n", sessions[i].pdusession_id, UE->rrc_ue_id);
|
||||
continue;
|
||||
}
|
||||
pdusession_t *session = &pduSession->param;
|
||||
cp_pdusession(session, &sessions[i]);
|
||||
LOG_I(NR_RRC, "Add PDU Session %d (total nb of sessions = %ld)\n", session->pdusession_id, seq_arr_size(&UE->pduSessions));
|
||||
// Fill E1 Bearer Context Modification Request
|
||||
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
|
||||
security_information_t *secInfo = &bearer_req.secInfo;
|
||||
secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
|
||||
@@ -312,7 +318,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
|
||||
int drb_id = get_next_available_drb_id(UE);
|
||||
drb_t *rrc_drb = generateDRB(UE,
|
||||
drb_id,
|
||||
pduSession,
|
||||
session,
|
||||
rrc->configuration.enable_sdap,
|
||||
rrc->security.do_drb_integrity,
|
||||
rrc->security.do_drb_ciphering,
|
||||
@@ -522,8 +528,8 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_
|
||||
|
||||
resp->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
|
||||
for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) {
|
||||
rrc_pdu_session_param_t *session = &UE->pduSession[pdusession];
|
||||
// Optional: PDU Sessions to Setup
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
if (session->status == PDU_SESSION_STATUS_DONE) {
|
||||
resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param);
|
||||
} else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
@@ -705,8 +711,7 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
ngap_pdusession_setup_resp_t *resp = &NGAP_PDUSESSION_SETUP_RESP(msg_p);
|
||||
resp->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
|
||||
for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) {
|
||||
rrc_pdu_session_param_t *session = &UE->pduSession[pdusession];
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
if (session->status == PDU_SESSION_STATUS_DONE) {
|
||||
resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param);
|
||||
session->status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
@@ -727,8 +732,8 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p);
|
||||
}
|
||||
|
||||
for(int i = 0; i < NB_RB_MAX; i++) {
|
||||
UE->pduSession[i].xid = -1;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
session->xid = -1;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -816,7 +821,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
|
||||
// might be more work than is worth it. See 8.2.1.4 in 38.413
|
||||
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) {
|
||||
const pdusession_resource_item_t *p = &msg->pdusession[i];
|
||||
rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */);
|
||||
rrc_pdu_session_param_t *exist = find_pduSession(&UE->pduSessions, p->pdusession_id);
|
||||
if (exist) {
|
||||
LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES};
|
||||
@@ -883,33 +888,21 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
bool all_failed = true;
|
||||
for (int i = 0; i < req->nb_pdusessions_tomodify; i++) {
|
||||
rrc_pdu_session_param_t *sess;
|
||||
const pdusession_resource_item_t *sessMod = req->pdusession + i;
|
||||
for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++)
|
||||
if (sess->param.pdusession_id == sessMod->pdusession_id)
|
||||
break;
|
||||
if (sess == UE->pduSession + UE->nb_of_pdusessions) {
|
||||
const pdusession_resource_item_t *sessMod = &req->pdusession[i];
|
||||
rrc_pdu_session_param_t *session = find_pduSession(&UE->pduSessions, sessMod->pdusession_id);
|
||||
if (!session) {
|
||||
LOG_W(NR_RRC, "Requested modification of non-existing PDU session, refusing modification\n");
|
||||
UE->nb_of_pdusessions++;
|
||||
sess->status = PDU_SESSION_STATUS_FAILED;
|
||||
sess->param.pdusession_id = sessMod->pdusession_id;
|
||||
sess->cause.type = NGAP_CAUSE_RADIO_NETWORK;
|
||||
UE->pduSession[i].cause.type = NGAP_CAUSE_RADIO_NETWORK;
|
||||
UE->pduSession[i].cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID;
|
||||
rrc_pdu_session_param_t to_add = {0};
|
||||
to_add.status = PDU_SESSION_STATUS_FAILED;
|
||||
to_add.param.pdusession_id = sessMod->pdusession_id;
|
||||
to_add.cause.type = NGAP_CAUSE_RADIO_NETWORK;
|
||||
to_add.cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID;
|
||||
seq_arr_push_back(&UE->pduSessions, &to_add, sizeof(to_add));
|
||||
} else {
|
||||
all_failed = false;
|
||||
sess->status = PDU_SESSION_STATUS_NEW;
|
||||
sess->param.pdusession_id = sessMod->pdusession_id;
|
||||
sess->cause.type = NGAP_CAUSE_RADIO_NETWORK;
|
||||
sess->cause.value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES;
|
||||
sess->status = PDU_SESSION_STATUS_NEW;
|
||||
sess->param.pdusession_id = sessMod->pdusession_id;
|
||||
sess->cause.type = NGAP_CAUSE_NOTHING;
|
||||
if (sessMod->nas_pdu.buf != NULL) {
|
||||
UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
|
||||
}
|
||||
for (int i = 0; i < req->nb_pdusessions_tomodify; ++i)
|
||||
cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]);
|
||||
session->status = PDU_SESSION_STATUS_NEW;
|
||||
session->cause.type = NGAP_CAUSE_NOTHING;
|
||||
cp_pdusession_resource_item_to_pdusession(&session->param, sessMod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,11 +920,12 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
|
||||
msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id;
|
||||
msg->nb_of_pdusessions = 0;
|
||||
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
|
||||
if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) {
|
||||
msg->pdusessions_failed[i].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
msg->pdusessions_failed[i].cause.type = UE->pduSession[i].cause.type;
|
||||
msg->pdusessions_failed[i].cause.value = UE->pduSession[i].cause.value;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
if (session->status == PDU_SESSION_STATUS_FAILED) {
|
||||
msg->pdusessions_failed[msg->nb_of_pdusessions_failed].pdusession_id = session->param.pdusession_id;
|
||||
msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.type = session->cause.type;
|
||||
msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.value = session->cause.value;
|
||||
msg->nb_of_pdusessions_failed++;
|
||||
}
|
||||
}
|
||||
itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
|
||||
@@ -945,6 +939,11 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
uint16_t pdu_sessions_failed = 0;
|
||||
uint16_t pdu_sessions_done = 0;
|
||||
|
||||
if (!seq_arr_size(&UE->pduSessions)) {
|
||||
LOG_W(NR_RRC, "UE %d: No PDU sessions in the list, don't send NG PDU Session Modify Response\n", UE->rrc_ue_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg_p = itti_alloc_new_message (TASK_RRC_GNB, rrc->module_id, NGAP_PDUSESSION_MODIFY_RESP);
|
||||
if (msg_p == NULL) {
|
||||
LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_p is NULL \n");
|
||||
@@ -955,63 +954,54 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
|
||||
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) {
|
||||
LOG_W(NR_RRC, "xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ", i, UE->pduSession[i].status, xid, UE->pduSession[i].xid);
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
if (xid != session->xid) {
|
||||
LOG_W(NR_RRC,
|
||||
"xid does not correspond (PDU Session %d, status %d, xid %d/%d) \n ",
|
||||
session->param.pdusession_id,
|
||||
session->status,
|
||||
xid,
|
||||
session->xid);
|
||||
continue;
|
||||
}
|
||||
if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false);
|
||||
if (pduSession) {
|
||||
LOG_I(NR_RRC, "update pdu session %d \n", pduSession->param.pdusession_id);
|
||||
// Update UE->pduSession
|
||||
pduSession->status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
pduSession->cause.type = NGAP_CAUSE_NOTHING;
|
||||
for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) {
|
||||
pduSession->param.qos[qos_flow_index] = UE->pduSession[i].param.qos[qos_flow_index];
|
||||
}
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) {
|
||||
resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = UE->pduSession[i].param.qos[qos_flow_index].qfi;
|
||||
}
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = UE->pduSession[i].param.nb_qos;
|
||||
LOG_I(NR_RRC,
|
||||
"Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_pduSessions %d, pdusession_id %d \n ",
|
||||
pdu_sessions_done,
|
||||
i,
|
||||
UE->pduSession[i].status,
|
||||
xid,
|
||||
UE->nb_of_pdusessions,
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id);
|
||||
pdu_sessions_done++;
|
||||
} else {
|
||||
LOG_W(NR_RRC, "PDU SESSION modify of a not existing pdu session %d \n", UE->pduSession[i].param.pdusession_id);
|
||||
resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID};
|
||||
resp->pdusessions_failed[pdu_sessions_failed].cause = cause;
|
||||
pdu_sessions_failed++;
|
||||
if (session->status == PDU_SESSION_STATUS_DONE) {
|
||||
LOG_I(NR_RRC, "Successfully modified PDU Session %d \n", session->param.pdusession_id);
|
||||
// Update status
|
||||
session->status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
session->cause.type = NGAP_CAUSE_NOTHING;
|
||||
// Fill response
|
||||
DevAssert(pdu_sessions_done < NGAP_MAX_PDU_SESSION);
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id;
|
||||
for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
|
||||
resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
|
||||
}
|
||||
} else if ((UE->pduSession[i].status == PDU_SESSION_STATUS_NEW) || (UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) {
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id;
|
||||
resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = session->param.nb_qos;
|
||||
LOG_I(NR_RRC,
|
||||
"Modify Resp (msg index %d, status %d, xid %d): nb_of_pduSessions %ld, pdusession_id %d \n ",
|
||||
pdu_sessions_done,
|
||||
session->status,
|
||||
xid,
|
||||
seq_arr_size(&UE->pduSessions),
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id);
|
||||
pdu_sessions_done++;
|
||||
} else if ((session->status == PDU_SESSION_STATUS_NEW) || (session->status == PDU_SESSION_STATUS_ESTABLISHED)) {
|
||||
LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n");
|
||||
} else if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) {
|
||||
resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
resp->pdusessions_failed[pdu_sessions_failed].cause.type = UE->pduSession[i].cause.type;
|
||||
resp->pdusessions_failed[pdu_sessions_failed].cause.value = UE->pduSession[i].cause.value;
|
||||
} else if (session->status == PDU_SESSION_STATUS_FAILED) {
|
||||
DevAssert(pdu_sessions_failed < NGAP_MAX_PDU_SESSION);
|
||||
resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = session->param.pdusession_id;
|
||||
resp->pdusessions_failed[pdu_sessions_failed].cause.type = session->cause.type;
|
||||
resp->pdusessions_failed[pdu_sessions_failed].cause.value = session->cause.value;
|
||||
pdu_sessions_failed++;
|
||||
}
|
||||
else
|
||||
LOG_W(NR_RRC,
|
||||
"Modify pdu session %d, unknown state %d \n ",
|
||||
UE->pduSession[i].param.pdusession_id,
|
||||
UE->pduSession[i].status);
|
||||
} else
|
||||
LOG_W(NR_RRC, "Modify pdu session %d, unknown state %d \n ", session->param.pdusession_id, session->status);
|
||||
}
|
||||
|
||||
resp->nb_of_pdusessions = pdu_sessions_done;
|
||||
resp->nb_of_pdusessions_failed = pdu_sessions_failed;
|
||||
|
||||
if (pdu_sessions_done > 0 || pdu_sessions_failed > 0) {
|
||||
LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %d)\n", UE->nb_of_pdusessions);
|
||||
LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %ld)\n", seq_arr_size(&UE->pduSessions));
|
||||
itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p);
|
||||
} else {
|
||||
itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
||||
@@ -1036,8 +1026,10 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP,
|
||||
req->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
req->cause.type = causeP.type;
|
||||
req->cause.value = causeP.value;
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
|
||||
req->pdusessions[i].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
// PDU Session Resource List (optional)
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
DevAssert(req->nb_of_pdusessions < NGAP_MAX_PDU_SESSION);
|
||||
req->pdusessions[req->nb_of_pdusessions].pdusession_id = session->param.pdusession_id;
|
||||
req->nb_of_pdusessions++;
|
||||
}
|
||||
itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg);
|
||||
@@ -1255,7 +1247,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_
|
||||
LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n",
|
||||
instance,
|
||||
gNB_ue_ngap_id);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, 0, NULL);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1286,25 +1278,24 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_
|
||||
/* UE will be freed after UE context release complete */
|
||||
} else {
|
||||
// the DU is offline already
|
||||
uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION];
|
||||
get_pduSession_array(UE, pdu_sessions);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions);
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions);
|
||||
rrc_remove_ue(rrc, ue_context_p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
|
||||
uint32_t gNB_ue_ngap_id,
|
||||
int num_pdu,
|
||||
uint32_t pdu_session_id[256])
|
||||
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pdusessions)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE);
|
||||
NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||
NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).num_pdu_sessions = num_pdu;
|
||||
for (int i = 0; i < num_pdu; ++i)
|
||||
NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).pdu_session_id[i] = pdu_session_id[i];
|
||||
ngap_ue_release_complete_t *complete = &NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg);
|
||||
complete->gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||
// PDU Session Resource List (Optional)
|
||||
if (pdusessions && seq_arr_size(pdusessions)) {
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, pdusessions) {
|
||||
complete->pdu_session_id[complete->num_pdu_sessions++] = session->param.pdusession_id;
|
||||
}
|
||||
}
|
||||
itti_send_msg_to_task(TASK_NGAP, instance, msg);
|
||||
}
|
||||
|
||||
@@ -1361,14 +1352,14 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U
|
||||
// AMF UE NGAP ID
|
||||
msg->amf_ue_ngap_id = UE->amf_ue_ngap_id;
|
||||
// PDU Session Resource Admitted List
|
||||
msg->nb_of_pdusessions = UE->nb_of_pdusessions;
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
|
||||
rrc_pdu_session_param_t *session = &UE->pduSession[i];
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &UE->pduSessions) {
|
||||
session->status = PDU_SESSION_STATUS_ESTABLISHED;
|
||||
// PDU Session ID
|
||||
msg->pdusessions[i].pdu_session_id = session->param.pdusession_id;
|
||||
DevAssert(msg->nb_of_pdusessions < NGAP_MAX_PDU_SESSION);
|
||||
pdu_session_resource_admitted_t *pdu = &msg->pdusessions[msg->nb_of_pdusessions++];
|
||||
pdu->pdu_session_id = session->param.pdusession_id;
|
||||
// Handover Request Acknowledge Transfer
|
||||
ho_request_ack_transfer_t *transfer = &msg->pdusessions[i].ack_transfer;
|
||||
ho_request_ack_transfer_t *transfer = &pdu->ack_transfer;
|
||||
transfer->gtp_teid = session->param.n3_outgoing.teid;
|
||||
memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length);
|
||||
transfer->gNB_addr.length = session->param.n3_outgoing.addr.length;
|
||||
@@ -1439,19 +1430,19 @@ 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) {
|
||||
resp->pdusession_release[pdu_sessions_released].pdusession_id = UE->pduSession[i].param.pdusession_id;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) {
|
||||
if (xid == session->xid) {
|
||||
const pdusession_t *pdusession = &session->param;
|
||||
resp->pdusession_release[pdu_sessions_released].pdusession_id = pdusession->pdusession_id;
|
||||
session->status = PDU_SESSION_STATUS_RELEASED;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
resp->nb_of_pdusessions_released = pdu_sessions_released;
|
||||
resp->nb_of_pdusessions_failed = 0;
|
||||
DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION);
|
||||
|
||||
LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, pdu_sessions_released);
|
||||
itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p);
|
||||
}
|
||||
@@ -1479,14 +1470,15 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
|
||||
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++) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, cmd->pdusession_release_params[pdusession].pdusession_id, false);
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id);
|
||||
if (!pduSession) {
|
||||
LOG_I(NR_RRC, "no pdusession_id, AMF requested to close it id=%d\n", cmd->pdusession_release_params[pdusession].pdusession_id);
|
||||
int j=UE->nb_of_pdusessions++;
|
||||
UE->pduSession[j].status = PDU_SESSION_STATUS_FAILED;
|
||||
UE->pduSession[j].param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id;
|
||||
rrc_pdu_session_param_t item = {0};
|
||||
item.status = PDU_SESSION_STATUS_FAILED;
|
||||
item.param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id;
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID};
|
||||
UE->pduSession[j].cause = cause;
|
||||
item.cause = cause;
|
||||
seq_arr_push_back(&UE->pduSessions, &item, sizeof(item));
|
||||
continue;
|
||||
}
|
||||
if (pduSession->status == PDU_SESSION_STATUS_FAILED) {
|
||||
@@ -1578,7 +1570,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc,
|
||||
ngap_handover_required_t msg = {
|
||||
.amf_ue_ngap_id = UE->amf_ue_ngap_id,
|
||||
.gNB_ue_ngap_id = UE->rrc_ue_id,
|
||||
.nb_of_pdusessions = UE->nb_of_pdusessions,
|
||||
.cause.type = NGAP_CAUSE_RADIO_NETWORK,
|
||||
.cause.value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON,
|
||||
.handoverType = HANDOVER_TYPE_INTRA5GS,
|
||||
@@ -1607,22 +1598,21 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc,
|
||||
/* Fill both PDU Session Resource List IE (M) in Handover Required
|
||||
and PDU Session Resource Information List IE (O) in the Source NG-RAN
|
||||
Node to Target NG-RAN Node Transparent Container */
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; ++i) {
|
||||
if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE || UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false);
|
||||
if (!pduSession)
|
||||
continue;
|
||||
pdusession_t *session = &pduSession->param;
|
||||
// PDU Session ID
|
||||
msg.pdusessions[i].pdusession_id = session->pdusession_id;
|
||||
// PDU Session Resource Information List (O)
|
||||
pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++];
|
||||
pdu_info->pdusession_id = session->pdusession_id;
|
||||
pdu_info->nb_of_qos_flow = session->nb_qos;
|
||||
for (int j = 0; j < session->nb_qos; ++j) {
|
||||
pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi;
|
||||
}
|
||||
msg.source2target->nb_pdu_session_resource++;
|
||||
FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, pduSession, &UE->pduSessions) {
|
||||
if (pduSession->status != PDU_SESSION_STATUS_DONE && pduSession->status != PDU_SESSION_STATUS_ESTABLISHED)
|
||||
continue;
|
||||
pdusession_t *session = &pduSession->param;
|
||||
DevAssert(msg.nb_of_pdusessions < NGAP_MAX_PDU_SESSION);
|
||||
pdusession_resource_t *pdu = &msg.pdusessions[msg.nb_of_pdusessions++];
|
||||
// PDU Session ID
|
||||
pdu->pdusession_id = session->pdusession_id;
|
||||
// PDU Session Resource Information List (O)
|
||||
DevAssert(msg.source2target->nb_pdu_session_resource < NGAP_MAX_PDU_SESSION);
|
||||
pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++];
|
||||
pdu_info->pdusession_id = session->pdusession_id;
|
||||
pdu_info->nb_of_qos_flow = session->nb_qos;
|
||||
for (int j = 0; j < pdu_info->nb_of_qos_flow; ++j) {
|
||||
pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,10 +74,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in
|
||||
|
||||
int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
|
||||
|
||||
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
|
||||
uint32_t gNB_ue_ngap_id,
|
||||
int num_pdu,
|
||||
uint32_t pdu_session_id[256]);
|
||||
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pduSessions);
|
||||
|
||||
void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "linear_alloc.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "tree.h"
|
||||
#include "rrc_gNB_radio_bearers.h"
|
||||
|
||||
static void rrc_gNB_ue_context_update_time(rrc_gNB_ue_context_t *ctxt)
|
||||
{
|
||||
@@ -78,9 +79,6 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance
|
||||
new_p->ue_context.rrc_ue_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator) + 1;
|
||||
rrc_gNB_ue_context_update_time(new_p);
|
||||
|
||||
for(int i = 0; i < NB_RB_MAX; i++)
|
||||
new_p->ue_context.pduSession[i].xid = -1;
|
||||
|
||||
LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id);
|
||||
return(new_p);
|
||||
}
|
||||
@@ -211,6 +209,9 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
|
||||
ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */
|
||||
ue->ongoing_pdusession_setup_request = false;
|
||||
|
||||
// Initialise setup PDU Sessions list
|
||||
seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t));
|
||||
|
||||
RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p);
|
||||
LOG_UE_EVENT(ue,
|
||||
"Create UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n",
|
||||
|
||||
@@ -76,6 +76,7 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
|
||||
/* fetch an existing PDU session for this DRB */
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id);
|
||||
|
||||
// for the moment, we only support one QoS flow. Put a reminder in case
|
||||
// this changes
|
||||
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
#include "ngap_messages_types.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
|
||||
#include "common/utils/alg/find.h"
|
||||
|
||||
static bool eq_pdu_session_id(const void *vval, const void *vit)
|
||||
{
|
||||
const int id = *(const int *)vval;
|
||||
const rrc_pdu_session_param_t *elem = vit;
|
||||
return elem->param.pdusession_id == id;
|
||||
}
|
||||
|
||||
/** @brief Deep copy pdusession_t */
|
||||
void cp_pdusession(pdusession_t *dst, const pdusession_t *src)
|
||||
@@ -41,19 +49,49 @@ void cp_pdusession(pdusession_t *dst, const pdusession_t *src)
|
||||
dst->nas_pdu = copy_byte_array(src->nas_pdu);
|
||||
}
|
||||
|
||||
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
|
||||
/** @brief Free pdusession_t */
|
||||
void free_pdusession(void *ptr)
|
||||
{
|
||||
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;
|
||||
rrc_pdu_session_param_t *elem = ptr;
|
||||
free_byte_array(elem->param.nas_pdu);
|
||||
}
|
||||
|
||||
/** @brief Retrieves PDU Session for the input ID
|
||||
* @return pointer to the found PDU Session, NULL if not found */
|
||||
rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id)
|
||||
{
|
||||
DevAssert(seq);
|
||||
elm_arr_t elm = find_if(seq, &id, eq_pdu_session_id);
|
||||
if (elm.found)
|
||||
return (rrc_pdu_session_param_t *)elm.it;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @brief Adds a new PDU Session to the list
|
||||
* @return pointer to the new PDU Session */
|
||||
rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in)
|
||||
{
|
||||
DevAssert(sessions_ptr);
|
||||
DevAssert(in);
|
||||
|
||||
if (seq_arr_size(sessions_ptr) == NGAP_MAX_PDU_SESSION) {
|
||||
LOG_W(NR_RRC, "Reached maximum number of PDU Session = %ld\n", seq_arr_size(sessions_ptr));
|
||||
return NULL;
|
||||
}
|
||||
return ue->pduSession + j;
|
||||
|
||||
rrc_pdu_session_param_t *exists = find_pduSession(sessions_ptr, in->pdusession_id);
|
||||
if (exists) {
|
||||
LOG_E(NR_RRC, "Trying to add an already existing PDU Session with ID=%d\n", in->pdusession_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rrc_pdu_session_param_t new = {.param = *in, .status = PDU_SESSION_STATUS_NEW, .xid = -1};
|
||||
seq_arr_push_back(sessions_ptr, &new, sizeof(rrc_pdu_session_param_t));
|
||||
rrc_pdu_session_param_t *added = find_pduSession(sessions_ptr, in->pdusession_id);
|
||||
DevAssert(added);
|
||||
LOG_I(NR_RRC, "Added PDU Session %d, (total nb of sessions = %ld)\n", in->pdusession_id, seq_arr_size(sessions_ptr));
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id)
|
||||
@@ -65,13 +103,7 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id
|
||||
return NULL;
|
||||
}
|
||||
int id = drb->cnAssociation.sdap_config.pdusession_id;
|
||||
return find_pduSession(ue, id, false);
|
||||
}
|
||||
|
||||
void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION])
|
||||
{
|
||||
for (int i = 0; i < ue->nb_of_pdusessions && i < NGAP_MAX_PDU_SESSION; ++i)
|
||||
pdu_sessions[i] = ue->pduSession[i].param.pdusession_id;
|
||||
return find_pduSession(&ue->pduSessions, id);
|
||||
}
|
||||
|
||||
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
@@ -117,7 +149,7 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d
|
||||
|
||||
drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
const pdusession_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering,
|
||||
@@ -125,7 +157,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
{
|
||||
DevAssert(ue != NULL);
|
||||
|
||||
LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->param.pdusession_id);
|
||||
LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->pdusession_id);
|
||||
|
||||
drb_t *est_drb = &ue->established_drbs[drb_id - 1];
|
||||
DevAssert(est_drb->status == DRB_INACTIVE);
|
||||
@@ -136,7 +168,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
|
||||
/* SDAP Configuration */
|
||||
est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
|
||||
est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id;
|
||||
est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->pdusession_id;
|
||||
if (enable_sdap) {
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present;
|
||||
@@ -144,9 +176,9 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent;
|
||||
}
|
||||
for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) {
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi;
|
||||
if (pduSession->param.qos[qos_flow_index].fiveQI > 5)
|
||||
for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) {
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi;
|
||||
if (pduSession->qos[qos_flow_index].fiveQI > 5)
|
||||
est_drb->status = DRB_ACTIVE_NONGBR;
|
||||
else
|
||||
est_drb->status = DRB_ACTIVE;
|
||||
|
||||
@@ -53,7 +53,7 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id);
|
||||
/// @return returns a pointer to the generated DRB structure
|
||||
drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
const pdusession_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering,
|
||||
@@ -65,20 +65,21 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
|
||||
/// @brief returns the number of active DRBs for this UE
|
||||
int get_number_active_drbs(gNB_RRC_UE_t *ue);
|
||||
|
||||
/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if
|
||||
/// create is true
|
||||
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create);
|
||||
/// @brief retrieve PDU session of UE ue with ID id
|
||||
rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id);
|
||||
|
||||
/// @brief Add a new PDU session for UE @param ue and configuration @param in
|
||||
rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in);
|
||||
|
||||
/// @brief get PDU session of UE ue through the DRB drb_id
|
||||
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id);
|
||||
|
||||
/// @brief get the PDU sessions of this UE in a single array
|
||||
void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]);
|
||||
|
||||
/// @brief set PDCP configuration in a bearer context management message
|
||||
void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb);
|
||||
|
||||
/// @brief Deep copy an instance of struct pdusession_t
|
||||
void cp_pdusession(pdusession_t *dst, const pdusession_t *src);
|
||||
|
||||
void free_pdusession(void *ptr);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user