mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Merge branch 'hol-delay' into 'develop'
Add per-LCID head-of-line delay to DL scheduling candidates See merge request oai/openairinterface5g!4152
This commit is contained in:
@@ -108,6 +108,7 @@ typedef struct {
|
|||||||
sdu_size_t head_sdu_remaining_size_to_send; /*!< \brief remaining size of sdu: could be the total size or the remaining size of
|
sdu_size_t head_sdu_remaining_size_to_send; /*!< \brief remaining size of sdu: could be the total size or the remaining size of
|
||||||
already segmented sdu */
|
already segmented sdu */
|
||||||
bool head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */
|
bool head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */
|
||||||
|
uint64_t oldest_sdu_arrival_ms; /*!< \brief Timestamp (ms, RLC time) of oldest SDU in tx/retx queue, 0 if empty */
|
||||||
} mac_rlc_status_resp_t;
|
} mac_rlc_status_resp_t;
|
||||||
|
|
||||||
#define SDU_CONFIRM_NO false
|
#define SDU_CONFIRM_NO false
|
||||||
|
|||||||
@@ -442,6 +442,7 @@ static int collect_dl_candidates(gNB_MAC_INST *mac,
|
|||||||
int n = 0;
|
int n = 0;
|
||||||
const frame_structure_t *fs = &mac->frame_structure;
|
const frame_structure_t *fs = &mac->frame_structure;
|
||||||
const float dl_slots_per_s = (float)get_dl_slots_per_period(fs) / fs->numb_slots_period * fs->numb_slots_frame * 100;
|
const float dl_slots_per_s = (float)get_dl_slots_per_period(fs) / fs->numb_slots_period * fs->numb_slots_frame * 100;
|
||||||
|
const uint64_t now_ms = get_nr_rlc_current_time();
|
||||||
|
|
||||||
UE_iterator (UE_list, UE) {
|
UE_iterator (UE_list, UE) {
|
||||||
if (n >= max_candidates)
|
if (n >= max_candidates)
|
||||||
@@ -527,6 +528,11 @@ static int collect_dl_candidates(gNB_MAC_INST *mac,
|
|||||||
.alloc_beam_idx = 0,
|
.alloc_beam_idx = 0,
|
||||||
.alloc_new_beam = false,
|
.alloc_new_beam = false,
|
||||||
};
|
};
|
||||||
|
nr_dl_candidate_t *c = &candidates[n - 1];
|
||||||
|
FOR_EACH_SEQ_ARR(const nr_lc_config_t *, lc, &sched_ctrl->lc_config) {
|
||||||
|
const uint64_t ts = sched_ctrl->rlc_status[lc->lcid].oldest_sdu_arrival_ms;
|
||||||
|
c->hol_delay_ms[lc->lcid] = (ts > 0 && ts <= now_ms) ? (now_ms - ts) : 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* new transmission candidate */
|
/* new transmission candidate */
|
||||||
if (sched_ctrl->available_dl_harq.head < 0)
|
if (sched_ctrl->available_dl_harq.head < 0)
|
||||||
@@ -572,8 +578,11 @@ static int collect_dl_candidates(gNB_MAC_INST *mac,
|
|||||||
.alloc_new_beam = false,
|
.alloc_new_beam = false,
|
||||||
};
|
};
|
||||||
nr_dl_candidate_t *c = &candidates[n - 1];
|
nr_dl_candidate_t *c = &candidates[n - 1];
|
||||||
for (int lcid = 0; lcid < NR_MAX_NUM_LCID; lcid++)
|
FOR_EACH_SEQ_ARR(const nr_lc_config_t *, lc, &sched_ctrl->lc_config) {
|
||||||
c->pending_bytes_per_lcid[lcid] = sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
c->pending_bytes_per_lcid[lc->lcid] = sched_ctrl->rlc_status[lc->lcid].bytes_in_buffer;
|
||||||
|
const uint64_t ts = sched_ctrl->rlc_status[lc->lcid].oldest_sdu_arrival_ms;
|
||||||
|
c->hol_delay_ms[lc->lcid] = (ts > 0 && ts <= now_ms) ? (now_ms - ts) : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -925,6 +925,7 @@ struct nr_dl_candidate {
|
|||||||
int retx_rbSize; ///< RBs needed for retx, 0 for new tx
|
int retx_rbSize; ///< RBs needed for retx, 0 for new tx
|
||||||
uint32_t pending_bytes; ///< total bytes waiting in RLC buffers
|
uint32_t pending_bytes; ///< total bytes waiting in RLC buffers
|
||||||
uint32_t pending_bytes_per_lcid[NR_MAX_NUM_LCID]; ///< per-LCID bytes waiting in RLC buffers
|
uint32_t pending_bytes_per_lcid[NR_MAX_NUM_LCID]; ///< per-LCID bytes waiting in RLC buffers
|
||||||
|
uint64_t hol_delay_ms[NR_MAX_NUM_LCID]; ///< per-LCID head-of-line delay in milliseconds (age of oldest SDU)
|
||||||
float avg_throughput; ///< EWMA goodput in bps (dl_thr_ue)
|
float avg_throughput; ///< EWMA goodput in bps (dl_thr_ue)
|
||||||
float bler; ///< current BLER estimate
|
float bler; ///< current BLER estimate
|
||||||
int current_mcs; ///< current MCS state (retx: from HARQ, new tx: from BLER tracker)
|
int current_mcs; ///< current MCS state (retx: from HARQ, new tx: from BLER tracker)
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ typedef struct {
|
|||||||
int status_size;
|
int status_size;
|
||||||
int tx_size;
|
int tx_size;
|
||||||
int retx_size;
|
int retx_size;
|
||||||
|
uint64_t oldest_sdu_arrival_ms; /* timestamp (ms, from sdu->arrival_ms) of oldest SDU in tx/retx queue, 0 if empty */
|
||||||
} nr_rlc_entity_buffer_status_t;
|
} nr_rlc_entity_buffer_status_t;
|
||||||
|
|
||||||
typedef struct nr_rlc_entity_s {
|
typedef struct nr_rlc_entity_s {
|
||||||
|
|||||||
@@ -1777,6 +1777,12 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
|
|||||||
ret.tx_size = entity->common.bstatus.tx_size;
|
ret.tx_size = entity->common.bstatus.tx_size;
|
||||||
ret.retx_size = entity->common.bstatus.retx_size;
|
ret.retx_size = entity->common.bstatus.retx_size;
|
||||||
|
|
||||||
|
ret.oldest_sdu_arrival_ms = 0;
|
||||||
|
if (entity->retransmit_list && entity->retransmit_list->sdu)
|
||||||
|
ret.oldest_sdu_arrival_ms = entity->retransmit_list->sdu->arrival_ms;
|
||||||
|
else if (entity->tx_list && entity->tx_list->sdu)
|
||||||
|
ret.oldest_sdu_arrival_ms = entity->tx_list->sdu->arrival_ms;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1851,6 +1857,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
|||||||
|
|
||||||
if (entity->common.avg_time_is_on)
|
if (entity->common.avg_time_is_on)
|
||||||
sdu->sdu->time_of_arrival = time_average_now();
|
sdu->sdu->time_of_arrival = time_average_now();
|
||||||
|
|
||||||
|
sdu->sdu->arrival_ms = entity->t_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(nr_rlc_entity_t *_e
|
|||||||
ret.tx_size = entity->common.bstatus.tx_size;
|
ret.tx_size = entity->common.bstatus.tx_size;
|
||||||
ret.retx_size = 0;
|
ret.retx_size = 0;
|
||||||
|
|
||||||
|
ret.oldest_sdu_arrival_ms = 0;
|
||||||
|
if (entity->tx_list && entity->tx_list->sdu)
|
||||||
|
ret.oldest_sdu_arrival_ms = entity->tx_list->sdu->arrival_ms;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +151,8 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
|
|||||||
|
|
||||||
if (entity->common.avg_time_is_on)
|
if (entity->common.avg_time_is_on)
|
||||||
sdu->sdu->time_of_arrival = time_average_now();
|
sdu->sdu->time_of_arrival = time_average_now();
|
||||||
|
|
||||||
|
sdu->sdu->arrival_ms = entity->t_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|||||||
@@ -534,6 +534,10 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(nr_rlc_entity_t *_e
|
|||||||
ret.tx_size = entity->common.bstatus.tx_size;
|
ret.tx_size = entity->common.bstatus.tx_size;
|
||||||
ret.retx_size = 0;
|
ret.retx_size = 0;
|
||||||
|
|
||||||
|
ret.oldest_sdu_arrival_ms = 0;
|
||||||
|
if (entity->tx_list && entity->tx_list->sdu)
|
||||||
|
ret.oldest_sdu_arrival_ms = entity->tx_list->sdu->arrival_ms;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,6 +598,8 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
|
|||||||
|
|
||||||
if (entity->common.avg_time_is_on)
|
if (entity->common.avg_time_is_on)
|
||||||
sdu->sdu->time_of_arrival = time_average_now();
|
sdu->sdu->time_of_arrival = time_average_now();
|
||||||
|
|
||||||
|
sdu->sdu->arrival_ms = entity->t_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void unlock_nr_rlc_current_time(void)
|
|||||||
AssertFatal(0, "error locking mutex");
|
AssertFatal(0, "error locking mutex");
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_nr_rlc_current_time(void)
|
uint64_t get_nr_rlc_current_time(void)
|
||||||
{
|
{
|
||||||
lock_nr_rlc_current_time();
|
lock_nr_rlc_current_time();
|
||||||
|
|
||||||
@@ -267,10 +267,12 @@ static mac_rlc_status_resp_t _nr_rlc_status_ind(nr_rlc_ue_t *ue, frame_t frame,
|
|||||||
// Fix me: temproary reduction meanwhile cpu cost of this computation is optimized
|
// Fix me: temproary reduction meanwhile cpu cost of this computation is optimized
|
||||||
buf_stat = rb->buffer_status(rb, 1000 * 1000);
|
buf_stat = rb->buffer_status(rb, 1000 * 1000);
|
||||||
ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size;
|
ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size;
|
||||||
|
ret.oldest_sdu_arrival_ms = buf_stat.oldest_sdu_arrival_ms;
|
||||||
} else {
|
} else {
|
||||||
if (!(frame % 128) || channel_idP == 0) //to suppress this warning message
|
if (!(frame % 128) || channel_idP == 0) //to suppress this warning message
|
||||||
LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue->ue_id);
|
LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue->ue_id);
|
||||||
ret.bytes_in_buffer = 0;
|
ret.bytes_in_buffer = 0;
|
||||||
|
ret.oldest_sdu_arrival_ms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.pdus_in_buffer = 0;
|
ret.pdus_in_buffer = 0;
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ int nr_rlc_tx_list_occupancy(int ue_id, logical_chan_id_t lcid);
|
|||||||
|
|
||||||
void nr_rlc_activate_avg_time_to_tx(const int ue_id, const logical_chan_id_t channel_id, const bool is_on);
|
void nr_rlc_activate_avg_time_to_tx(const int ue_id, const logical_chan_id_t channel_id, const bool is_on);
|
||||||
|
|
||||||
|
uint64_t get_nr_rlc_current_time(void);
|
||||||
|
|
||||||
void nr_rlc_srb_recv_sdu(const int ue_id, const logical_chan_id_t channel_id, unsigned char *buf, int size);
|
void nr_rlc_srb_recv_sdu(const int ue_id, const logical_chan_id_t channel_id, unsigned char *buf, int size);
|
||||||
|
|
||||||
bool nr_rlc_activate_srb0(int ue_id,
|
bool nr_rlc_activate_srb0(int ue_id,
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ typedef struct nr_rlc_sdu_t {
|
|||||||
* transmission is used for statistics
|
* transmission is used for statistics
|
||||||
*/
|
*/
|
||||||
uint64_t time_of_arrival; /* unit microsecond */
|
uint64_t time_of_arrival; /* unit microsecond */
|
||||||
|
|
||||||
|
/* RLC time when the SDU was first received .Used for the HOL-delay
|
||||||
|
* in MAC. TODO: unify with time_of_arrival (feed E2AP/KPM in us)
|
||||||
|
*/
|
||||||
|
uint64_t arrival_ms;
|
||||||
} nr_rlc_sdu_t;
|
} nr_rlc_sdu_t;
|
||||||
|
|
||||||
typedef struct nr_rlc_sdu_segment_t {
|
typedef struct nr_rlc_sdu_segment_t {
|
||||||
|
|||||||
Reference in New Issue
Block a user