srsenb,metrics: add PUSCH/PUCCH RSSI metrics. Add bearer DL total data metric for RLC UM

master
Ismael Gomez 3 years ago
parent 9a0d7113bc
commit cf647b1fd5

@ -75,6 +75,7 @@ typedef struct SRSRAN_API {
srsran_uci_value_t uci_data;
float dmrs_correlation;
float snr_db;
float rsrp_db;
float correlation;
bool detected;

@ -61,6 +61,15 @@ extern "C" {
// Proportional moving average
#define SRSRAN_VEC_PMA(average1, n1, average2, n2) (((average1) * (n1) + (average2) * (n2)) / ((n1) + (n2)))
// Safe Proportional moving average
#ifdef __cplusplus
#define SRSRAN_VEC_SAFE_PMA(average1, n1, average2, n2) \
(std::isnormal((n1) + (n2)) ? SRSRAN_VEC_PMA(average1, n1, average2, n2) : (0))
#else
#define SRSRAN_VEC_SAFE_PMA(average1, n1, average2, n2) \
(isnormal((n1) + (n2)) ? SRSRAN_VEC_PMA(average1, n1, average2, n2) : (0))
#endif
// Exponential moving average
#define SRSRAN_VEC_EMA(data, average, alpha) ((alpha) * (data) + (1 - alpha) * (average))

@ -221,6 +221,10 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
// Pass PDU to lower layers
metrics.num_tx_pdus++;
metrics.num_tx_pdu_bytes += sdu->N_bytes;
// Count TX'd bytes as if they were ACK'd if RLC is UM
if (rlc->rb_is_um(lcid)) {
metrics.num_tx_acked_bytes = metrics.num_tx_pdu_bytes;
}
rlc->write_sdu(lcid, std::move(sdu));
}

@ -347,13 +347,16 @@ static void chest_ul_estimate(srsran_chest_ul_t* q,
}
// Estimate received pilot power
float signal_power = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym);
if (isnormal(res->noise_estimate)) {
res->snr = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym) / res->noise_estimate;
res->snr = signal_power / res->noise_estimate;
} else {
res->snr = NAN;
}
// Convert measurements in logarithm scale
res->rsrp = signal_power;
res->rsrp_dBfs = srsran_convert_power_to_dB(signal_power);
res->snr_db = srsran_convert_power_to_dB(res->snr);
res->noise_estimate_dbm = srsran_convert_power_to_dBm(res->noise_estimate);
}

@ -184,7 +184,8 @@ static int get_pucch(srsran_enb_ul_t* q, srsran_ul_sf_cfg_t* ul_sf, srsran_pucch
ERROR("Error estimating PUCCH DMRS");
return SRSRAN_ERROR;
}
pucch_res.snr_db = q->chest_res.snr_db;
pucch_res.snr_db = q->chest_res.snr_db;
pucch_res.rsrp_db = q->chest_res.rsrp_dBfs;
ret = srsran_pucch_decode(&q->pucch, ul_sf, cfg, &q->chest_res, q->sf_symbols, &pucch_res);
if (ret < SRSRAN_SUCCESS) {

@ -387,7 +387,7 @@ nr_pdsch_mcs=28
# rlf_release_timer_ms: Time taken by eNB to release UE context after it detects a RLF
# rlf_min_ul_snr_estim: SNR threshold in dB below which the enb is notified with RLF ko
# s1_setup_max_retries: Maximum amount of retries to setup the S1AP connection. If this value is exceeded, an alarm is written to the log. -1 means infinity.
#
# rx_gain_offset: RX Gain offset to add to rx_gain to calibrate RSRP readings
#####################################################################
[expert]
#pusch_max_its = 8 # These are half iterations
@ -423,3 +423,4 @@ nr_pdsch_mcs=28
#rlf_release_timer_ms = 4000
#rlf_min_ul_snr_estim = -2
#s1_setup_max_retries = -1
#rx_gain_offset = 62

@ -100,7 +100,7 @@ private:
void metrics_read(phy_metrics_t* metrics);
void metrics_dl(uint32_t mcs);
void metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo_iters);
void metrics_ul_pucch(float sinr);
void metrics_ul_pucch(float rssi, float sinr);
uint32_t get_rnti() const { return rnti; }
private:

@ -50,6 +50,7 @@ struct phy_args_t {
std::string type;
srsran::phy_log_args_t log;
float rx_gain_offset = 62;
float max_prach_offset_us = 10;
uint32_t pusch_max_its = 10;
uint32_t nr_pusch_max_its = 10;

@ -20,28 +20,22 @@ namespace srsenb {
// PHY metrics per user
struct ul_metrics_t {
float n;
float pusch_sinr;
// Initialize this member with an invalid value as this field is optional.
float pusch_rssi = std::numeric_limits<float>::quiet_NaN();
// Initialize this member with an invalid value as this field is optional.
int64_t pusch_tpc = 0;
float n;
float pusch_sinr;
float pusch_rssi;
int64_t pusch_tpc;
float pucch_sinr;
// Initialize this member with an invalid value as this field is optional.
float pucch_rssi = std::numeric_limits<float>::quiet_NaN();
// Initialize this member with an invalid value as this field is optional.
float pucch_ni = std::numeric_limits<float>::quiet_NaN();
float rssi;
float turbo_iters;
float mcs;
int n_samples;
int n_samples_pucch;
float pucch_rssi;
float pucch_ni;
float turbo_iters;
float mcs;
int n_samples;
int n_samples_pucch;
};
struct dl_metrics_t {
float mcs;
// Initialize this member with an invalid value as this field is optional.
int64_t pucch_tpc = 0;
int64_t pucch_tpc;
int n_samples;
};

@ -259,6 +259,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.ts1_reloc_overall_timeout", bpo::value<uint32_t>(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds.")
("expert.rlf_min_ul_snr_estim", bpo::value<int>(&args->stack.mac.rlf_min_ul_snr_estim)->default_value(-2), "SNR threshold in dB below which the eNB is notified with rlf ko.")
("expert.max_s1_setup_retries", bpo::value<int32_t>(&args->stack.s1ap.max_s1_setup_retries)->default_value(-1), "Max S1 setup retries")
("expert.rx_gain_offset", bpo::value<float>(&args->phy.rx_gain_offset)->default_value(62), "RX Gain offset to add to rx_gain to calibrate RSRP readings")
// eMBMS section
("embms.enable", bpo::value<bool>(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB")

@ -363,7 +363,10 @@ bool cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
// Save statistics only if data was provided
if (ul_grant.data != nullptr) {
// Save metrics stats
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx, 0, enb_ul.chest_res.snr_db, pusch_res.avg_iterations_block);
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx,
enb_ul.chest_res.rsrp_dBfs - phy->params.rx_gain_offset,
enb_ul.chest_res.snr_db,
pusch_res.avg_iterations_block);
}
return true;
}
@ -451,7 +454,9 @@ int cc_worker::decode_pucch()
}
// Save metrics
ue_db[rnti]->metrics_ul_pucch(pucch_res.snr_db);
if (pucch_res.detected) {
ue_db[rnti]->metrics_ul_pucch(pucch_res.rsrp_db - phy->params.rx_gain_offset, pucch_res.snr_db);
}
}
}
}
@ -666,15 +671,22 @@ void cc_worker::ue::metrics_dl(uint32_t mcs)
void cc_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo_iters)
{
if (isnan(rssi)) {
rssi = 0;
}
metrics.ul.mcs = SRSRAN_VEC_CMA((float)mcs, metrics.ul.mcs, metrics.ul.n_samples);
metrics.ul.pusch_sinr = SRSRAN_VEC_CMA((float)sinr, metrics.ul.pusch_sinr, metrics.ul.n_samples);
metrics.ul.rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.rssi, metrics.ul.n_samples);
metrics.ul.pusch_rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.pusch_rssi, metrics.ul.n_samples);
metrics.ul.turbo_iters = SRSRAN_VEC_CMA((float)turbo_iters, metrics.ul.turbo_iters, metrics.ul.n_samples);
metrics.ul.n_samples++;
}
void cc_worker::ue::metrics_ul_pucch(float sinr)
void cc_worker::ue::metrics_ul_pucch(float rssi, float sinr)
{
if (isnan(rssi)) {
rssi = 0;
}
metrics.ul.pucch_rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.pucch_rssi, metrics.ul.n_samples_pucch);
metrics.ul.pucch_sinr = SRSRAN_VEC_CMA((float)sinr, metrics.ul.pucch_sinr, metrics.ul.n_samples_pucch);
metrics.ul.n_samples_pucch++;
}

@ -268,15 +268,17 @@ uint32_t sf_worker::get_metrics(std::vector<phy_metrics_t>& metrics)
for (uint32_t r = 0; r < cnt; r++) {
phy_metrics_t* m = &metrics[r];
phy_metrics_t* m_ = &metrics_[r];
m->dl.mcs = SRSRAN_VEC_PMA(m->dl.mcs, m->dl.n_samples, m_->dl.mcs, m_->dl.n_samples);
m->dl.mcs = SRSRAN_VEC_SAFE_PMA(m->dl.mcs, m->dl.n_samples, m_->dl.mcs, m_->dl.n_samples);
m->dl.n_samples += m_->dl.n_samples;
m->ul.n = SRSRAN_VEC_PMA(m->ul.n, m->ul.n_samples, m_->ul.n, m_->ul.n_samples);
m->ul.pusch_sinr = SRSRAN_VEC_PMA(m->ul.pusch_sinr, m->ul.n_samples, m_->ul.pusch_sinr, m_->ul.n_samples);
m->ul.n = SRSRAN_VEC_SAFE_PMA(m->ul.n, m->ul.n_samples, m_->ul.n, m_->ul.n_samples);
m->ul.pusch_sinr = SRSRAN_VEC_SAFE_PMA(m->ul.pusch_sinr, m->ul.n_samples, m_->ul.pusch_sinr, m_->ul.n_samples);
m->ul.pucch_sinr =
SRSRAN_VEC_PMA(m->ul.pucch_sinr, m->ul.n_samples_pucch, m_->ul.pucch_sinr, m_->ul.n_samples_pucch);
m->ul.mcs = SRSRAN_VEC_PMA(m->ul.mcs, m->ul.n_samples, m_->ul.mcs, m_->ul.n_samples);
m->ul.rssi = SRSRAN_VEC_PMA(m->ul.rssi, m->ul.n_samples, m_->ul.rssi, m_->ul.n_samples);
m->ul.turbo_iters = SRSRAN_VEC_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples);
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_sinr, m->ul.n_samples_pucch, m_->ul.pucch_sinr, m_->ul.n_samples_pucch);
m->ul.mcs = SRSRAN_VEC_SAFE_PMA(m->ul.mcs, m->ul.n_samples, m_->ul.mcs, m_->ul.n_samples);
m->ul.pusch_rssi = SRSRAN_VEC_SAFE_PMA(m->ul.pusch_rssi, m->ul.n_samples, m_->ul.pusch_rssi, m_->ul.n_samples);
m->ul.pucch_rssi =
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_rssi, m->ul.n_samples_pucch, m_->ul.pucch_rssi, m_->ul.n_samples_pucch);
m->ul.turbo_iters = SRSRAN_VEC_SAFE_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples);
m->ul.n_samples += m_->ul.n_samples;
m->ul.n_samples_pucch += m_->ul.n_samples_pucch;
}

@ -252,20 +252,26 @@ void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
metrics[j].ul.n_samples_pucch += metrics_tmp[j].ul.n_samples_pucch;
metrics[j].ul.mcs += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.mcs;
metrics[j].ul.n += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.n;
metrics[j].ul.rssi += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.rssi;
metrics[j].ul.pusch_rssi += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_rssi;
metrics[j].ul.pusch_sinr += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_sinr;
metrics[j].ul.pucch_rssi += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_rssi;
metrics[j].ul.pucch_sinr += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_sinr;
metrics[j].ul.turbo_iters += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.turbo_iters;
}
}
for (uint32_t j = 0; j < metrics.size(); j++) {
metrics[j].dl.mcs /= metrics[j].dl.n_samples;
metrics[j].ul.mcs /= metrics[j].ul.n_samples;
metrics[j].ul.n /= metrics[j].ul.n_samples;
metrics[j].ul.rssi /= metrics[j].ul.n_samples;
metrics[j].ul.pusch_sinr /= metrics[j].ul.n_samples;
metrics[j].ul.pucch_sinr /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.turbo_iters /= metrics[j].ul.n_samples;
if (metrics[j].dl.n_samples > 0) {
metrics[j].dl.mcs /= metrics[j].dl.n_samples;
}
if (metrics[j].ul.n_samples > 0) {
metrics[j].ul.mcs /= metrics[j].ul.n_samples;
metrics[j].ul.n /= metrics[j].ul.n_samples;
metrics[j].ul.pusch_rssi /= metrics[j].ul.n_samples;
metrics[j].ul.pusch_sinr /= metrics[j].ul.n_samples;
metrics[j].ul.pucch_rssi /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.pucch_sinr /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.turbo_iters /= metrics[j].ul.n_samples;
}
}
}

Loading…
Cancel
Save