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:
Guido Casati
2025-09-24 14:38:36 +02:00
parent e4a910f0bb
commit 5bcc9b9e5e
11 changed files with 261 additions and 234 deletions
+1
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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(&params);
@@ -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
View File
@@ -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;
}
}
+1 -4
View File
@@ -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);
+4 -3
View File
@@ -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",
+1
View File
@@ -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");
+56 -24
View File
@@ -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;
+8 -7
View File
@@ -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