Commit 7fa0ebb6 authored by Guido Casati's avatar Guido Casati

Adopt dynamic seq_arr in DRB handling (RRC PDU Session)

The previous DRB management relied on a fixed-size array (established_drbs[MAX_DRBS_PER_UE])
and manual status tracking using DRB_ACTIVE/INACTIVE flags. This approach was inefficient,
and made assumptions about DRB ID allocation that do not generalize well
to dynamic procedures like bearer modification or removal.

* Replace fixed-size array established_drbs[] with dynamic
  seq_arr_t *drbs in gNB_RRC_UE_t
* Refactor get_drb() and added nr_rrc_add_drb() with clean abstractions
  using find and seq_arr lib
* Updated all DRB-related logic (e.g., generateDRB,
  F1AP/E1AP tunnel config, reestablishment, mobility) to use seq_arr.
* Removed status field and DRB_ACTIVE/INACTIVE logic: list presence implies active
* DRB ID allocation now tracked via seq_arr size : simplifies DRB management and
  avoids DRB ID–indexed assumptions: code assumed DRB IDs mapped directly to
  array indices: established_drbs[drb_id - 1]. This could break when:
  DRB IDs are not sequential, DRBs are removed and re-added, or there are gaps in IDs
parent f15af772
...@@ -182,7 +182,6 @@ typedef struct nr_handover_context_s nr_handover_context_t; ...@@ -182,7 +182,6 @@ typedef struct nr_handover_context_s nr_handover_context_t;
typedef struct gNB_RRC_UE_s { typedef struct gNB_RRC_UE_s {
time_t last_seen; // last time this UE has been accessed time_t last_seen; // last time this UE has been accessed
drb_t established_drbs[MAX_DRBS_PER_UE];
NR_DRB_ToReleaseList_t *DRB_ReleaseList; NR_DRB_ToReleaseList_t *DRB_ReleaseList;
NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB];
...@@ -239,6 +238,8 @@ typedef struct gNB_RRC_UE_s { ...@@ -239,6 +238,8 @@ typedef struct gNB_RRC_UE_s {
//SA block //SA block
seq_arr_t pduSessions; seq_arr_t pduSessions;
// Established DRBs
seq_arr_t drbs;
rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
uint8_t e_rab_release_command_flag; uint8_t e_rab_release_command_flag;
......
...@@ -334,14 +334,12 @@ NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) ...@@ -334,14 +334,12 @@ NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish)
NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddMod_t *DRB_config = NULL;
NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1);
for (int i = 0; i < MAX_DRBS_PER_UE; i++) { FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) {
if (ue->established_drbs[i].status != DRB_INACTIVE) { DRB_config = generateDRB_ASN1(drb);
DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); if (reestablish) {
if (reestablish) { asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true);
asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true);
}
asn1cSeqAdd(&DRB_configList->list, DRB_config);
} }
asn1cSeqAdd(&DRB_configList->list, DRB_config);
} }
if (DRB_configList->list.count == 0) { if (DRB_configList->list.count == 0) {
free(DRB_configList); free(DRB_configList);
...@@ -734,22 +732,6 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t ...@@ -734,22 +732,6 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
continue; continue;
} }
// search exist DRB_config
int 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->pdusession_id)
break;
}
if (j == MAX_DRBS_PER_UE) {
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified};
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 // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) { 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]; pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index];
...@@ -873,8 +855,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) ...@@ -873,8 +855,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
return; return;
/* loop through active DRBs */ /* loop through active DRBs */
for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) {
drb_t *drb = get_drb(ue_p, drb_id); drb_t *drb = get_drb(&ue_p->drbs, drb_id);
if (drb->status == DRB_INACTIVE) if (!drb)
continue; continue;
/* fetch an existing PDU session for this DRB */ /* fetch an existing PDU session for this DRB */
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id); rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id);
...@@ -2078,7 +2060,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_ ...@@ -2078,7 +2060,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_
const f1ap_drb_setup_t *drb_f1 = &drbs[i]; const f1ap_drb_setup_t *drb_f1 = &drbs[i];
AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n"); AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n");
AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id); AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id);
drb_t *drb = get_drb(ue, drb_f1->id); drb_t *drb = get_drb(&ue->drbs, drb_f1->id);
DevAssert(drb);
drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address);
} }
} }
...@@ -2094,7 +2077,7 @@ static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE, ...@@ -2094,7 +2077,7 @@ static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE,
drb_to_mod->pdcp_sn_status_requested = false; drb_to_mod->pdcp_sn_status_requested = false;
// PDCP SN Status Information // PDCP SN Status Information
drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config)); drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config));
set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(UE, drb_id), um_on_default_drb); set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(&UE->drbs, drb_id), um_on_default_drb);
drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status)); drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status));
drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn;
drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn;
...@@ -2130,8 +2113,11 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb ...@@ -2130,8 +2113,11 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb
fill_e1_bearer_modif(&drb_to_mod, drb_f1); fill_e1_bearer_modif(&drb_to_mod, drb_f1);
} else if (is_inter_cu_ho) { } else if (is_inter_cu_ho) {
/* On-going handover: send PDCP Status Request */ /* On-going handover: send PDCP Status Request */
if (UE->established_drbs[i].status == DRB_INACTIVE) drb_t *drb = get_drb(&UE->drbs, drb_id);
if (!drb) {
LOG_E(NR_RRC, "Failed to send PDCP Status Request: DRB %d not found\n", drb_id);
continue; continue;
}
drb_to_mod.id = drb_id; drb_to_mod.id = drb_id;
// PDCP SN Status Request // PDCP SN Status Request
drb_to_mod.pdcp_sn_status_requested = true; drb_to_mod.pdcp_sn_status_requested = true;
...@@ -2204,7 +2190,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance ...@@ -2204,7 +2190,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
} }
if (resp->drbs_len > 0) { if (resp->drbs_len > 0) {
int num_drb = get_number_active_drbs(UE); int num_drb = seq_arr_size(&UE->drbs);
DevAssert(num_drb == 0 || num_drb == resp->drbs_len); DevAssert(num_drb == 0 || num_drb == resp->drbs_len);
/* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU
...@@ -2296,6 +2282,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ...@@ -2296,6 +2282,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE)
free(UE->redcap_cap); free(UE->redcap_cap);
UE->redcap_cap = NULL; UE->redcap_cap = NULL;
seq_arr_free(&UE->pduSessions, free_pdusession); seq_arr_free(&UE->pduSessions, free_pdusession);
seq_arr_free(&UE->drbs, free_drb);
} }
void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p)
...@@ -2510,9 +2497,10 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, ...@@ -2510,9 +2497,10 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
DevAssert(pdu); DevAssert(pdu);
for (int i = 0; i < pduSession[p].numDRBSetup; i++) { for (int i = 0; i < pduSession[p].numDRBSetup; i++) {
const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i];
drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id); drb_t *rrc_drb = get_drb(&UE->drbs, pduSession[p].DRBnGRanList[i].id);
DevAssert(rrc_drb); DevAssert(rrc_drb);
DevAssert(nb_drb < MAX_DRBS_PER_UE);
f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; f1ap_drb_to_setup_t *drb = &drbs[nb_drb];
drb->id = rrc_drb->drb_id; drb->id = rrc_drb->drb_id;
...@@ -2587,7 +2575,11 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp ...@@ -2587,7 +2575,11 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[j]; DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[j];
// numUpParam only relevant in F1, but not monolithic // numUpParam only relevant in F1, but not monolithic
AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n"); AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n");
drb_t *drb = get_drb(UE, drb_config->id); drb_t *drb = get_drb(&UE->drbs, drb_config->id);
if (!drb) {
LOG_E(RRC, "E1: DRB %ld not found for PDU session %ld\n", drb_config->id, e1_pdu->id);
continue;
}
UP_TL_information_t *tl_info = &drb_config->UpParamList[0].tl_info; UP_TL_information_t *tl_info = &drb_config->UpParamList[0].tl_info;
drb->cuup_tunnel_config = f1u_gtp_update(tl_info->teId, tl_info->tlAddress); drb->cuup_tunnel_config = f1u_gtp_update(tl_info->teId, tl_info->tlAddress);
} }
...@@ -2629,6 +2621,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t ...@@ -2629,6 +2621,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t
} }
int n_drb_mod = 0; int n_drb_mod = 0;
int drb_ids[MAX_DRBS_PER_UE] = {0};
e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0}; e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0};
for (int i = 0; i < resp->numPDUSessionsMod; ++i) { for (int i = 0; i < resp->numPDUSessionsMod; ++i) {
const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; const pdu_session_modif_t *pdu = &resp->pduSessionMod[i];
...@@ -2636,6 +2629,8 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t ...@@ -2636,6 +2629,8 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t
for (int j = 0; j < pdu->numDRBModified; j++) { for (int j = 0; j < pdu->numDRBModified; j++) {
// Trigger UL RAN Status Transfer // Trigger UL RAN Status Transfer
if (pdu->DRBnGRanModList[j].pdcp_status) { if (pdu->DRBnGRanModList[j].pdcp_status) {
DevAssert(n_drb_mod < MAX_DRBS_PER_UE);
drb_ids[n_drb_mod] = pdu->DRBnGRanModList[j].id;
pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status; pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status;
} }
} }
...@@ -2644,7 +2639,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t ...@@ -2644,7 +2639,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t
LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id); LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id);
gNB_RRC_UE_t *ue = &ue_context_p->ue_context; gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
if (ue->ho_context && ue->ho_context->source) if (ue->ho_context && ue->ho_context->source)
ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, pdcp_status); ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, drb_ids, pdcp_status);
} }
} }
......
...@@ -315,9 +315,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession ...@@ -315,9 +315,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
/* we assume for the moment one DRB per PDU session. Activate the bearer, /* we assume for the moment one DRB per PDU session. Activate the bearer,
* and configure in RRC. */ * and configure in RRC. */
int drb_id = get_next_available_drb_id(UE);
drb_t *rrc_drb = generateDRB(UE, drb_t *rrc_drb = generateDRB(UE,
drb_id,
session, session,
rrc->configuration.enable_sdap, rrc->configuration.enable_sdap,
rrc->security.do_drb_integrity, rrc->security.do_drb_integrity,
...@@ -1162,9 +1160,15 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg) ...@@ -1162,9 +1160,15 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg)
/** @brief Send NG Uplink RAN Status Transfer message (8.4.6 3GPP TS 38.413) /** @brief Send NG Uplink RAN Status Transfer message (8.4.6 3GPP TS 38.413)
* Direction: source NG-RAN node -> AMF */ * Direction: source NG-RAN node -> AMF */
int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status) int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *UE,
const int n_to_mod,
const int *drb_ids,
const e1_pdcp_status_info_t *pdcp_status)
{ {
AssertFatal(UE != NULL, "UE context is NULL\n"); AssertFatal(UE != NULL, "UE context is NULL\n");
DevAssert(n_to_mod <= MAX_DRBS_PER_UE);
DevAssert(drb_ids);
LOG_I(NR_RRC, LOG_I(NR_RRC,
"Sending NGAP Uplink RAN Status Transfer (AMF_UE_NGAP_ID=%" PRIu64 ", GNB_UE_NGAP_ID=%u)\n", "Sending NGAP Uplink RAN Status Transfer (AMF_UE_NGAP_ID=%" PRIu64 ", GNB_UE_NGAP_ID=%u)\n",
...@@ -1178,14 +1182,20 @@ int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE ...@@ -1178,14 +1182,20 @@ int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
// Loop through DRBs and extract COUNT values // Loop through DRBs and extract COUNT values
for (int i = 0; i < n_to_mod; ++i) { for (int i = 0; i < n_to_mod; ++i) {
drb_t *drb = &UE->established_drbs[i]; int drb_id = drb_ids[i];
if (!drb->status)
// Find the DRB in the UE's DRB list
drb_t *drb = get_drb(&UE->drbs, drb_id);
if (!drb) {
LOG_E(NR_RRC, "Failed to send UL RAN Status Transfer: DRB %d not found\n", drb_id);
continue; continue;
}
bool sn_length_18 = rrc->pdcp_config.drb.sn_size == 18; bool sn_length_18 = drb->pdcp_config.pdcp_SN_SizeDL == NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
DevAssert(msg.ran_status.nb_drb < MAX_DRBS_PER_UE);
ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++]; ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++];
item->drb_id = drb->drb_id; item->drb_id = drb_id;
const e1_pdcp_count_t *ul_pdcp = &pdcp_status[i].ul_count; const e1_pdcp_count_t *ul_pdcp = &pdcp_status[i].ul_count;
const e1_pdcp_count_t *dl_pdcp = &pdcp_status[i].dl_count; const e1_pdcp_count_t *dl_pdcp = &pdcp_status[i].dl_count;
......
...@@ -104,7 +104,11 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); ...@@ -104,7 +104,11 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg);
void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE);
void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause); void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause);
int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *UE,
const int n_to_mod,
const int *drb_ids,
const e1_pdcp_status_info_t *pdcp_status);
int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance); int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance);
......
...@@ -211,6 +211,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, ...@@ -211,6 +211,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
// Initialise setup PDU Sessions list // Initialise setup PDU Sessions list
seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t));
// Initialise setup DRBs list
seq_arr_init(&ue->drbs, sizeof(drb_t));
RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p);
LOG_UE_EVENT(ue, LOG_UE_EVENT(ue,
......
...@@ -63,14 +63,14 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) ...@@ -63,14 +63,14 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx)
free(ho_ctx); free(ho_ctx);
} }
/** @brief Fill DRB to Be Setup List in F1 UE Context Setup Request (optional list)
* @return 0 if list is empty, list size otherwise */
static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE])
{ {
int nb_drb = 0; int nb_drb = 0;
for (int i = 0; i < MAX_DRBS_PER_UE; ++i) {
drb_t *rrc_drb = &ue->established_drbs[i];
if (rrc_drb->status == DRB_INACTIVE)
continue;
FOR_EACH_SEQ_ARR(drb_t *, rrc_drb, &ue->drbs) {
DevAssert(nb_drb < MAX_DRBS_PER_UE);
f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; f1ap_drb_to_setup_t *drb = &drbs[nb_drb];
nb_drb++; nb_drb++;
/* fetch an existing PDU session for this DRB */ /* fetch an existing PDU session for this DRB */
......
...@@ -33,7 +33,11 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t; ...@@ -33,7 +33,11 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t;
typedef struct NR_CellGroupConfig NR_CellGroupConfig_t; typedef struct NR_CellGroupConfig NR_CellGroupConfig_t;
typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue);
typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc,
gNB_RRC_UE_t *UE,
const int n_to_mod,
const int *drb_ids,
const e1_pdcp_status_info_t *pdcp_status);
typedef struct nr_ho_source_cu { typedef struct nr_ho_source_cu {
/// pointer to the (source) DU structure /// pointer to the (source) DU structure
......
...@@ -85,24 +85,68 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio ...@@ -85,24 +85,68 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio
return added; return added;
} }
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) /** @brief Add drb_t item in the UE context list for @param pdusession_id */
drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id)
{ {
DevAssert(drb_id > 0 && drb_id <= 32); DevAssert(drb_ptr);
const drb_t *drb = &ue->established_drbs[drb_id - 1];
if (drb->status == DRB_INACTIVE) { // Get next available DRB ID
LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id); int drb_id = 0;
// First, try to find the lowest available ID (prefer smaller IDs)
for (drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) {
if (get_drb(drb_ptr, drb_id) == NULL) {
break; // Found available ID
}
}
if (drb_id > MAX_DRBS_PER_UE) {
LOG_E(NR_RRC, "Cannot set up new DRB for pdusession_id=%d - reached maximum capacity\n", pdusession_id);
return NULL; return NULL;
} }
int id = drb->cnAssociation.sdap_config.pdusession_id;
return find_pduSession(&ue->pduSessions, id); // Add item to the list
drb_t in = {.drb_id = drb_id, .cnAssociation.sdap_config.pdusession_id = pdusession_id};
seq_arr_push_back(drb_ptr, &in, sizeof(drb_t));
drb_t *out = get_drb(drb_ptr, drb_id);
DevAssert(out);
LOG_I(NR_RRC, "Added DRB %d to established list (PDU Session ID=%d, total DRBs = %ld)\n", out->drb_id, pdusession_id, seq_arr_size(drb_ptr));
return out;
} }
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) static bool eq_drb_id(const void *vval, const void *vit)
{ {
DevAssert(drb_id > 0 && drb_id <= 32); const int id = *(const int *)vval;
DevAssert(ue != NULL); const drb_t *elem = (const drb_t *)vit;
return elem->drb_id == id;
}
/** @brief Retrieves DRB for the input ID
* @return pointer to the found DRB, NULL if not found */
drb_t *get_drb(seq_arr_t *seq, int id)
{
DevAssert(id > 0 && id <= MAX_DRBS_PER_UE);
elm_arr_t elm = find_if(seq, &id, eq_drb_id);
if (elm.found)
return (drb_t *)elm.it;
return NULL;
}
/** @brief Free pdusession_t */
void free_drb(void *ptr)
{
// do nothing
}
return &ue->established_drbs[drb_id - 1]; rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id)
{
const drb_t *drb = get_drb(&ue->drbs, drb_id);
if (!drb) {
LOG_E(NR_RRC, "UE %d: DRB %d not found\n", ue->rrc_ue_id, drb_id);
return NULL;
}
int id = drb->cnAssociation.sdap_config.pdusession_id;
return find_pduSession(&ue->pduSessions, id);
} }
void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config,
...@@ -139,7 +183,6 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d ...@@ -139,7 +183,6 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d
} }
drb_t *generateDRB(gNB_RRC_UE_t *ue, drb_t *generateDRB(gNB_RRC_UE_t *ue,
uint8_t drb_id,
const pdusession_t *pduSession, const pdusession_t *pduSession,
bool enable_sdap, bool enable_sdap,
int do_drb_integrity, int do_drb_integrity,
...@@ -148,13 +191,13 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, ...@@ -148,13 +191,13 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
{ {
DevAssert(ue != NULL); 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->pdusession_id); drb_t *est_drb = nr_rrc_add_drb(&ue->drbs, pduSession->pdusession_id);
if (!est_drb) {
drb_t *est_drb = &ue->established_drbs[drb_id - 1]; LOG_E(NR_RRC, "UE %d: failed to add DRB for PDU session ID %d\n", ue->rrc_ue_id, pduSession->pdusession_id);
DevAssert(est_drb->status == DRB_INACTIVE); return NULL;
}
LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, est_drb->drb_id, pduSession->pdusession_id);
est_drb->status = DRB_ACTIVE;
est_drb->drb_id = drb_id;
est_drb->cnAssociation.sdap_config.defaultDRB = true; est_drb->cnAssociation.sdap_config.defaultDRB = true;
/* SDAP Configuration */ /* SDAP Configuration */
...@@ -169,16 +212,12 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, ...@@ -169,16 +212,12 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
} }
for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) { 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; 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;
} }
/* PDCP Configuration */ /* PDCP Configuration */
set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap);
drb_t *rrc_drb = get_drb(ue, drb_id); drb_t *rrc_drb = get_drb(&ue->drbs, est_drb->drb_id);
DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */ DevAssert(rrc_drb);
return rrc_drb; return rrc_drb;
} }
...@@ -229,22 +268,3 @@ NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) ...@@ -229,22 +268,3 @@ NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1)
return DRB_config; return DRB_config;
} }
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue)
{
for (uint8_t drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
if (ue->established_drbs[drb_id].status == DRB_INACTIVE)
return drb_id + 1;
/* From this point, we need to handle the case that all DRBs are already used by the UE. */
LOG_E(RRC, "Error - All the DRBs are used - Handle this\n");
return DRB_INACTIVE;
}
int get_number_active_drbs(gNB_RRC_UE_t *ue)
{
int n = 0;
for (int i = 0; i < MAX_DRBS_PER_UE; ++i)
if (ue->established_drbs[i].status != DRB_INACTIVE)
n++;
return n;
}
...@@ -28,19 +28,13 @@ ...@@ -28,19 +28,13 @@
#include "e1ap_messages_types.h" #include "e1ap_messages_types.h"
#include "nr_rrc_defs.h" #include "nr_rrc_defs.h"
#define DRB_ACTIVE_NONGBR (2) /* DRB is used for Non-GBR Flows */
#define DRB_ACTIVE (1)
#define DRB_INACTIVE (0)
#define GBR_FLOW (1)
#define NONGBR_FLOW (0)
/// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t. /// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t.
/// @param drb_t drb_asn1 /// @param drb_t drb_asn1
/// @return Returns the ASN1 DRB-ToAddMod structs. /// @return Returns the ASN1 DRB-ToAddMod structs.
NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1); NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1);
/// @brief retrieve the data structure representing DRB with ID drb_id of UE ue /// @brief retrieve the data structure representing DRB with ID drb_id of UE ue
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); drb_t *get_drb(seq_arr_t *seq, int id);
/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct /// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct
/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs /// @param ue The gNB_RRC_UE_t struct that holds information for the UEs
...@@ -52,19 +46,12 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); ...@@ -52,19 +46,12 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id);
/// @param pdcp_config /// @param pdcp_config
/// @return returns a pointer to the generated DRB structure /// @return returns a pointer to the generated DRB structure
drb_t *generateDRB(gNB_RRC_UE_t *ue, drb_t *generateDRB(gNB_RRC_UE_t *ue,
uint8_t drb_id,
const pdusession_t *pduSession, const pdusession_t *pduSession,
bool enable_sdap, bool enable_sdap,
int do_drb_integrity, int do_drb_integrity,
int do_drb_ciphering, int do_drb_ciphering,
const nr_pdcp_configuration_t *pdcp_config); const nr_pdcp_configuration_t *pdcp_config);
/// @brief return the next available (inactive) DRB ID of UE ue
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 /// @brief retrieve PDU session of UE ue with ID id
rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id); rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id);
...@@ -79,4 +66,10 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d ...@@ -79,4 +66,10 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d
void free_pdusession(void *ptr); void free_pdusession(void *ptr);
/// @brief Add DRB to RRC list
drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id);
/// @brief Function to free DRB in RRC
void free_drb(void *ptr);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment