update
This commit is contained in:
@@ -17,6 +17,11 @@ bool read_mac_sm(void* data)
|
||||
//fill_mac_ind_data(mac);
|
||||
|
||||
mac->msg.tstamp = time_now_us();
|
||||
// Export the physical denominator beside the per-UE TBS/PRB counters. This
|
||||
// avoids estimating PRB opportunity from a rounded, differently-windowed
|
||||
// KPM percentage in the rApp.
|
||||
mac->msg.dl_prb_opportunities = RC.nrmac[mod_id]->mac_stats.dl.total_prb_aggregate;
|
||||
mac->msg.dl_used_prbs = RC.nrmac[mod_id]->mac_stats.dl.used_prb_aggregate;
|
||||
|
||||
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
size_t num_ues = 0;
|
||||
@@ -33,6 +38,10 @@ bool read_mac_sm(void* data)
|
||||
|
||||
size_t i = 0; //TODO
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
// Bound the write against the calloc'd buffer size: a UE attach between
|
||||
// the count loop above and this iterator can grow connected_ue_list and
|
||||
// overflow mac->msg.ue_stats (corrupts the heap → later free() abort).
|
||||
if (i >= num_ues) break;
|
||||
const NR_UE_sched_ctrl_t* sched_ctrl = &UE->UE_sched_ctrl;
|
||||
mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i];
|
||||
|
||||
@@ -58,8 +67,11 @@ bool read_mac_sm(void* data)
|
||||
rd->dl_aggr_retx_prb = UE->mac_stats.dl.total_rbs_retx;
|
||||
rd->ul_aggr_retx_prb = UE->mac_stats.ul.total_rbs_retx;
|
||||
|
||||
rd->dl_aggr_bytes_sdus = UE->mac_stats.dl.lc_bytes[3];
|
||||
rd->ul_aggr_bytes_sdus = UE->mac_stats.ul.lc_bytes[3];
|
||||
// The service-model field is aggregate SDU bytes. Using LCID 3 silently
|
||||
// drops payload whenever the DRB is assigned another logical channel and
|
||||
// corrupts the MAC payload/TBS fill ratio used by capacity estimation.
|
||||
rd->dl_aggr_bytes_sdus = UE->mac_stats.dl.total_sdu_bytes;
|
||||
rd->ul_aggr_bytes_sdus = UE->mac_stats.ul.total_sdu_bytes;
|
||||
|
||||
rd->dl_aggr_sdus = UE->mac_stats.dl.num_mac_sdu;
|
||||
rd->ul_aggr_sdus = UE->mac_stats.ul.num_mac_sdu;
|
||||
@@ -68,6 +80,16 @@ bool read_mac_sm(void* data)
|
||||
rd->pucch_snr = sched_ctrl->pucch_pc.avg_snr; //: float = -64;
|
||||
|
||||
rd->wb_cqi = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
|
||||
rd->csi_valid = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report;
|
||||
rd->dl_ri = rd->csi_valid ? sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1 : 0;
|
||||
rd->dl_layers = UE->mac_stats.dl.last_layers;
|
||||
rd->pmi_x1 = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x1;
|
||||
rd->pmi_x2 = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2;
|
||||
rd->csi_frame = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.report_frame;
|
||||
rd->csi_slot = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.report_slot;
|
||||
rd->active_tx_chains = RC.nrmac[mod_id]->antenna_state != NULL
|
||||
? nr_get_active_tx_antenna_count(RC.nrmac[mod_id]->antenna_state)
|
||||
: 0;
|
||||
rd->dl_mcs1 = sched_ctrl->dl_bler_stats.mcs;
|
||||
rd->dl_bler = sched_ctrl->dl_bler_stats.bler;
|
||||
rd->ul_mcs1 = sched_ctrl->ul_bler_stats.mcs;
|
||||
@@ -110,4 +132,3 @@ sm_ag_if_ans_t write_ctrl_mac_sm(void const* data)
|
||||
sm_ag_if_ans_t ans = {0};
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#endif
|
||||
|
||||
#if defined (NGRAN_GNB_CUUP)
|
||||
void fill_pdcp_stats_for_all_rbs(pdcp_radio_bearer_stats_t* rb, const size_t num_ues, const uint64_t* ue_id_list)
|
||||
void fill_pdcp_stats_for_all_rbs(pdcp_radio_bearer_stats_t* rb, const size_t num_ues, const uint64_t* ue_id_list, const size_t rb_capacity)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < num_ues; i++) {
|
||||
@@ -37,6 +37,10 @@ void fill_pdcp_stats_for_all_rbs(pdcp_radio_bearer_stats_t* rb, const size_t num
|
||||
|
||||
if (!rc) continue;
|
||||
|
||||
// Bound the write against the original capacity: an RB activating
|
||||
// between the count loop in read_pdcp_sm and this fill can grow the
|
||||
// observed count and overflow rb[] (corrupts the heap).
|
||||
if (j >= rb_capacity) return;
|
||||
pdcp_radio_bearer_stats_t *rd = &rb[j++];
|
||||
|
||||
rd->txpdu_pkts = rb_pdcp.txpdu_pkts; /* aggregated number of tx packets */
|
||||
@@ -114,7 +118,7 @@ bool read_pdcp_sm(void* data)
|
||||
|
||||
// Filling Radio Bearer Statistics
|
||||
#if defined (NGRAN_GNB_CUUP)
|
||||
fill_pdcp_stats_for_all_rbs(pdcp->msg.rb, num_ues, ue_id_list);
|
||||
fill_pdcp_stats_for_all_rbs(pdcp->msg.rb, num_ues, ue_id_list, pdcp->msg.len);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,11 @@ bool read_rlc_sm(void* data)
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rb_rlc);
|
||||
if(!rc) continue;
|
||||
// Bound the write against the originally-calloc'd buffer size. A UE
|
||||
// attach between num_act_rb() above and this iterator can grow the
|
||||
// connected-UE list; without this check we'd overflow rlc->msg.rb
|
||||
// and corrupt the heap (crash later in free_rlc_ind_msg()).
|
||||
if (i >= act_rb) goto done_iter;
|
||||
rlc_radio_bearer_stats_t* sm_rb = &rlc->msg.rb[i];
|
||||
|
||||
/* TX */
|
||||
@@ -143,6 +148,7 @@ bool read_rlc_sm(void* data)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
done_iter:
|
||||
|
||||
return act_rb > 0;
|
||||
}
|
||||
|
||||
@@ -86,8 +86,42 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused)) const
|
||||
}
|
||||
|
||||
#if defined (NGRAN_GNB_DU)
|
||||
static uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
static uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0};
|
||||
typedef struct ue_uldlcounter {
|
||||
const NR_UE_info_t *ue;
|
||||
rnti_t rnti;
|
||||
uldlcounter_t value;
|
||||
bool dl_valid;
|
||||
bool ul_valid;
|
||||
} ue_uldlcounter_t;
|
||||
|
||||
static ue_uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
static ue_uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0};
|
||||
|
||||
/* The connected UE list is compacted when a UE leaves, so its iteration index
|
||||
* is not a stable identity. Keep baselines by the MAC-assigned UID instead and
|
||||
* reset them when that UID is reused for another UE. */
|
||||
static ue_uldlcounter_t *get_ue_counter(ue_uldlcounter_t counters[MAX_MOBILES_PER_GNB],
|
||||
const cudu_ue_info_pair_t ue_info)
|
||||
{
|
||||
AssertFatal(ue_info.ue != NULL, "KPM UE measurement requires MAC UE information\n");
|
||||
const uid_t uid = ue_info.ue->uid;
|
||||
AssertFatal(uid < MAX_MOBILES_PER_GNB, "KPM UE UID %u exceeds maximum %u\n", uid, MAX_MOBILES_PER_GNB);
|
||||
|
||||
ue_uldlcounter_t *counter = &counters[uid];
|
||||
if (counter->ue != ue_info.ue || counter->rnti != ue_info.ue->rnti)
|
||||
*counter = (ue_uldlcounter_t){.ue = ue_info.ue, .rnti = ue_info.ue->rnti};
|
||||
return counter;
|
||||
}
|
||||
|
||||
/* A new/reused UE counter and a reset/wrap have no valid preceding sample.
|
||||
* Establish a fresh baseline and report zero for that single period. */
|
||||
static uint32_t counter_delta(uint32_t current, uint32_t *previous, bool *valid)
|
||||
{
|
||||
const uint32_t delta = *valid && current >= *previous ? current - *previous : 0;
|
||||
*previous = current;
|
||||
*valid = true;
|
||||
return delta;
|
||||
}
|
||||
|
||||
static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb_id)
|
||||
{
|
||||
@@ -120,8 +154,16 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused)) const la
|
||||
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Get the value of sojourn time at the RLC buffer
|
||||
meas_record.real_val = rlc.txsdu_avg_time_to_tx; // [μs]
|
||||
// Report the windowed-average RLC SDU sojourn (mean per-packet wait over the
|
||||
// last 100 ms), not the instantaneous tx_list HOL snapshot. The snapshot
|
||||
// (txsdu_wt_us) reads 0 whenever the tx_list is momentarily drained at the
|
||||
// single sampling instant -- common with bursty DL even at high throughput --
|
||||
// which systematically under-reports delay (era/load-dependent). The averaging
|
||||
// accumulator is now activated once (reset guarded to off->on in
|
||||
// nr_rlc_activate_avg_time_to_tx), so it accumulates continuously instead of
|
||||
// being wiped on every read; it returns 0 only when no SDU was transmitted in
|
||||
// the window (genuine idle/starvation).
|
||||
meas_record.real_val = (double)rlc.txsdu_avg_time_to_tx; // [us] avg RLC SDU sojourn
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
@@ -132,7 +174,7 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused)) const la
|
||||
static meas_record_lst_t fill_DRB_UEThpDl(__attribute__((unused)) const label_info_lst_t label,
|
||||
uint32_t gran_period_ms,
|
||||
cudu_ue_info_pair_t ue_info,
|
||||
const size_t ue_idx,
|
||||
__attribute__((unused)) const size_t ue_idx,
|
||||
__attribute__((unused))e2_node_level_stats_t* node_stats)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
@@ -142,8 +184,9 @@ static meas_record_lst_t fill_DRB_UEThpDl(__attribute__((unused)) const label_in
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate DL Thp
|
||||
meas_record.real_val = (double)(rlc.txpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].dl)*8/gran_period_ms; // [kbps]
|
||||
last_rlc_pdu_total_bytes[ue_idx].dl = rlc.txpdu_bytes;
|
||||
ue_uldlcounter_t *counter = get_ue_counter(last_rlc_pdu_total_bytes, ue_info);
|
||||
const uint32_t bytes = counter_delta(rlc.txpdu_bytes, &counter->value.dl, &counter->dl_valid);
|
||||
meas_record.real_val = gran_period_ms == 0 ? 0 : (double)bytes * 8 / gran_period_ms; // [kbps]
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
@@ -154,7 +197,7 @@ static meas_record_lst_t fill_DRB_UEThpDl(__attribute__((unused)) const label_in
|
||||
static meas_record_lst_t fill_DRB_UEThpUl(__attribute__((unused)) const label_info_lst_t label,
|
||||
uint32_t gran_period_ms,
|
||||
cudu_ue_info_pair_t ue_info,
|
||||
const size_t ue_idx,
|
||||
__attribute__((unused)) const size_t ue_idx,
|
||||
__attribute__((unused))e2_node_level_stats_t* node_stats)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
@@ -166,8 +209,9 @@ static meas_record_lst_t fill_DRB_UEThpUl(__attribute__((unused)) const label_in
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate UL Thp
|
||||
meas_record.real_val = (double)(rlc.rxpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].ul)*8/gran_period_ms; // [kbps]
|
||||
last_rlc_pdu_total_bytes[ue_idx].ul = rlc.rxpdu_bytes;
|
||||
ue_uldlcounter_t *counter = get_ue_counter(last_rlc_pdu_total_bytes, ue_info);
|
||||
const uint32_t bytes = counter_delta(rlc.rxpdu_bytes, &counter->value.ul, &counter->ul_valid);
|
||||
meas_record.real_val = gran_period_ms == 0 ? 0 : (double)bytes * 8 / gran_period_ms; // [kbps]
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
@@ -177,7 +221,7 @@ static meas_record_lst_t fill_DRB_UEThpUl(__attribute__((unused)) const label_in
|
||||
static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused)) const label_info_lst_t label,
|
||||
__attribute__((unused)) uint32_t gran_period_ms,
|
||||
cudu_ue_info_pair_t ue_info,
|
||||
const size_t ue_idx,
|
||||
__attribute__((unused)) const size_t ue_idx,
|
||||
e2_node_level_stats_t* node_stats)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
@@ -185,8 +229,13 @@ static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused)) const label_i
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get the number of DL PRBs
|
||||
meas_record.int_val = (ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl) * 100 / (node_stats[1].mac_stats.dl.total_prb_aggregate - node_stats[0].mac_stats.dl.total_prb_aggregate); // [%]
|
||||
last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs;
|
||||
ue_uldlcounter_t *counter = get_ue_counter(last_total_prbs, ue_info);
|
||||
const uint32_t ue_delta = counter_delta(ue_info.ue->mac_stats.dl.total_rbs, &counter->value.dl, &counter->dl_valid);
|
||||
const uint64_t current = node_stats[1].mac_stats.dl.total_prb_aggregate;
|
||||
const uint64_t previous = node_stats[0].mac_stats.dl.total_prb_aggregate;
|
||||
const uint64_t total_delta = current >= previous ? current - previous : 0;
|
||||
const uint64_t percentage = total_delta == 0 ? 0 : (uint64_t)ue_delta * 100 / total_delta;
|
||||
meas_record.int_val = percentage > 100 ? 100 : percentage; // [%]
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
@@ -196,7 +245,7 @@ static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused)) const label_i
|
||||
static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused)) const label_info_lst_t label,
|
||||
__attribute__((unused)) uint32_t gran_period_ms,
|
||||
cudu_ue_info_pair_t ue_info,
|
||||
const size_t ue_idx,
|
||||
__attribute__((unused)) const size_t ue_idx,
|
||||
e2_node_level_stats_t* node_stats)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
@@ -204,8 +253,13 @@ static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused)) const label_i
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get the number of UL PRBs
|
||||
meas_record.int_val = (ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul) * 100 / (node_stats[1].mac_stats.ul.total_prb_aggregate - node_stats[0].mac_stats.ul.total_prb_aggregate); // [%]
|
||||
last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs;
|
||||
ue_uldlcounter_t *counter = get_ue_counter(last_total_prbs, ue_info);
|
||||
const uint32_t ue_delta = counter_delta(ue_info.ue->mac_stats.ul.total_rbs, &counter->value.ul, &counter->ul_valid);
|
||||
const uint64_t current = node_stats[1].mac_stats.ul.total_prb_aggregate;
|
||||
const uint64_t previous = node_stats[0].mac_stats.ul.total_prb_aggregate;
|
||||
const uint64_t total_delta = current >= previous ? current - previous : 0;
|
||||
const uint64_t percentage = total_delta == 0 ? 0 : (uint64_t)ue_delta * 100 / total_delta;
|
||||
meas_record.int_val = percentage > 100 ? 100 : percentage; // [%]
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
+1
-1
Submodule openair2/E2AP/flexric updated: 340c36bc83...25353bb973
Reference in New Issue
Block a user