Improved DL TCP performance by tweeking BSR reports and UL scheduler

master
Ismael Gomez 7 years ago
parent 616e18c570
commit 955170bd52

@ -94,7 +94,8 @@ public:
typedef struct {
int priority;
int bsd;
int pbr;
int pbr;
int group;
enum {IDLE = 0, UL, DL, BOTH} direction;
} ue_bearer_cfg_t;
@ -231,7 +232,7 @@ public:
/* UL information */
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true) = 0;
virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0;
virtual int ul_phr(uint16_t rnti, int phr) = 0;
virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0;

@ -33,7 +33,7 @@
// Table 6.1.3.1-1 Buffer size levels for BSR
static uint32_t btable[64] = {
0, 5, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
0, 1, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000};
@ -428,12 +428,16 @@ int sch_subh::get_bsr(uint32_t buff_size[4])
buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6;
buff_size[3] = (payload[2]&0x3F);
} else {
uint32_t nonzero_lcg = (payload[0]&0xc0) >> 6;
nonzero_lcg = (payload[0]&0xc0) >> 6;
buff_size[nonzero_lcg%4] = payload[0]&0x3f;
}
for (int i=0;i<4;i++) {
if (buff_size[i]) {
buff_size[i] = btable[buff_size[i]%64];
if (buff_size[i]<63) {
buff_size[i] = btable[1+buff_size[i]];
} else {
buff_size[i] = btable[63];
}
}
}
return nonzero_lcg;

@ -15,14 +15,14 @@ qci_config = (
};
dl_um = {
sn_field_length = 10;
t_reordering = 80;
t_reordering = 45;
};
};
logical_channel_config = {
priority = 11;
priority = 13;
prioritized_bit_rate = -1;
bucket_size_duration = 100;
log_chan_group = 3;
log_chan_group = 2;
};
},
{

@ -108,7 +108,7 @@ public:
int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc);
int ul_sr_info(uint32_t tti, uint16_t rnti);
int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr);
int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true);
int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len);
int ul_phr(uint16_t rnti, int phr);
int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code);

@ -104,7 +104,8 @@ public:
void set_alloc(ul_alloc_t alloc);
void same_alloc();
bool is_adaptive_retx();
void reset_pending_data();
bool has_pending_ack();
uint32_t get_pending_data();

@ -62,7 +62,7 @@ public:
void rem_bearer(uint32_t lc_id);
void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
void ul_buffer_state(uint8_t lc_id, uint32_t bsr);
void ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value = true);
void ul_phr(int phr);
void mac_buffer_state(uint32_t ce_code);
void ul_recv_len(uint32_t lcid, uint32_t len);
@ -114,8 +114,10 @@ public:
uint32_t get_max_retx();
bool get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32_t *L);
bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce);
bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce);
uint32_t get_pending_ul_old_data();
private:
typedef struct {
@ -126,8 +128,7 @@ private:
} ue_bearer_t;
bool is_sr_triggered();
uint32_t get_pending_ul_old_data();
int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb);
static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t *mcs);

@ -85,7 +85,9 @@ public:
uint32_t rl_failure();
void rl_failure_reset();
void set_lcg(uint32_t lcid, uint32_t lcg);
void metrics_read(srsenb::mac_metrics_t* metrics);
void metrics_rx(bool crc, uint32_t tbs);
void metrics_tx(bool crc, uint32_t tbs);
@ -100,7 +102,9 @@ private:
void allocate_ce(srslte::sch_pdu *pdu, uint32_t lcid);
void metrics_phr(float phr);
uint32_t phr_counter;
uint32_t phr_counter;
std::vector<uint32_t> lc_groups[4];
mac_metrics_t metrics;

@ -9,7 +9,7 @@ mac_cnfg =
ulsch_cnfg =
{
max_harq_tx = 4;
periodic_bsr_timer = 5; // in ms
periodic_bsr_timer = 40; // in ms
retx_bsr_timer = 320; // in ms
};

@ -33,6 +33,7 @@
#include <strings.h>
#include <pthread.h>
#include <unistd.h>
#include <srslte/interfaces/sched_interface.h>
#include "srslte/common/log.h"
#include "mac/mac.h"
@ -163,7 +164,9 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint
int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg)
{
if (ue_db.count(rnti)) {
if (ue_db.count(rnti)) {
// configure BSR group in UE
ue_db[rnti]->set_lcg(lc_id, (uint32_t) cfg->group);
return scheduler.bearer_ue_cfg(rnti, lc_id, cfg);
} else {
Error("User rnti=0x%x not found\n", rnti);

@ -302,12 +302,12 @@ int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch
return ret;
}
int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr)
int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value)
{
pthread_mutex_lock(&mutex);
int ret = 0;
if (ue_db.count(rnti)) {
ue_db[rnti].ul_buffer_state(lcid, bsr);
ue_db[rnti].ul_buffer_state(lcid, bsr, set_value);
} else {
Error("User rnti=0x%x not found\n", rnti);
ret = -1;
@ -792,13 +792,13 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
user->unset_sr();
}
log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d)\n",
log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d-%d)\n",
is_rar?"RAR":"UL",
is_newtx?"tx":"retx",
rnti, h->get_id(),
sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce,
alloc.RB_start, alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs,
user->get_pending_ul_new_data(current_tti),pending_data_before);
user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data());
nof_dci_elems++;
} else {
@ -812,8 +812,16 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
}
}
}
}
}
// Update pending data counters after this TTI
for(std::map<uint16_t, sched_ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
sched_ue *user = (sched_ue *) &iter->second;
uint16_t rnti = (uint16_t) iter->first;
user->get_ul_harq(current_tti)->reset_pending_data();
}
sched_result->nof_dci_elems = nof_dci_elems;
sched_result->nof_phich_elems = nof_phich_elems;

@ -98,7 +98,7 @@ bool harq_proc::get_ack()
void harq_proc::set_ack(bool ack_)
{
ack = ack_;
ack_received = true;
ack_received = true;
log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx);
if (n_rtx >= max_retx) {
Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx);
@ -229,13 +229,22 @@ bool ul_harq_proc::has_pending_ack()
active = false;
}
if (!active) {
pending_data = 0;
need_ack = false;
need_ack = false;
}
return ret;
}
uint32_t ul_harq_proc::get_pending_data()
void ul_harq_proc::reset_pending_data()
{
if (!active) {
pending_data = 0;
}
}
uint32_t ul_harq_proc::get_pending_data()
{
return pending_data;
}

@ -163,12 +163,18 @@ void sched_ue::phy_config_enabled(uint32_t tti, bool enabled)
phy_config_dedicated_enabled = enabled;
}
void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr)
void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value)
{
if (lc_id < sched_interface::MAX_LC) {
lch[lc_id].bsr = bsr;
if (set_value) {
lch[lc_id].bsr = bsr;
} else {
lch[lc_id].bsr += bsr;
}
Debug("SCHED: UL lcid=%d buffer_state=%d\n", lc_id, bsr);
}
}
Info("SCHED: bsr=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", bsr, lc_id,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
}
void sched_ue::ul_phr(int phr)
@ -297,6 +303,8 @@ void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len)
}
}
}
Info("SCHED: recv_len=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", len, lcid,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
}
void sched_ue::set_ul_crc(uint32_t tti, bool crc_res)
@ -554,6 +562,10 @@ uint32_t sched_ue::get_pending_ul_new_data(uint32_t tti)
} else {
pending_data = 0;
}
if (pending_data) {
Info("SCHED: pending_data=%d, pending_ul_data=%d, bsr={%d,%d,%d,%d}\n", pending_data,pending_ul_data,
lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr);
}
return pending_data;
}

@ -58,6 +58,10 @@ void ue::config(uint16_t rnti_, uint32_t nof_prb, sched_interface *sched_, rrc_i
for(int i=0;i<NOF_HARQ_PROCESSES;i++) {
pending_buffers[i] = NULL;
}
// Set LCID group for SRB0 and SRB1
set_lcg(0, 0);
set_lcg(1, 0);
}
@ -88,7 +92,16 @@ void ue::rl_failure_reset()
{
nof_failures = 0;
}
void ue::set_lcg(uint32_t lcid, uint32_t lcg)
{
// find and remove if already exists
for (int i=0;i<4;i++) {
lc_groups[lcg].erase(std::remove(lc_groups[lcg].begin(), lc_groups[lcg].end(), lcid), lc_groups[lcg].end());
}
lc_groups[lcg].push_back(lcid);
}
srslte_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t tti)
{
return &softbuffer_rx[tti%NOF_HARQ_PROCESSES];
@ -138,63 +151,83 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, uint32_t tstamp)
if (pcap) {
pcap->write_ul_crnti(pdu, nof_bytes, rnti, true, last_tti);
}
uint32_t lcid_most_data = 0;
int most_data = -99;
while(mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (mac_msg_ul.get()->is_sdu())
{
if (mac_msg_ul.get()->is_sdu()) {
// Route logical channel
log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(),
"PDU: rnti=0x%x, lcid=%d, %d bytes\n",
rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(),
"PDU: rnti=0x%x, lcid=%d, %d bytes\n",
rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
/* In some cases, an uplink transmission with only CQI has all zeros and gets routed to RRC
* Compute the checksum if lcid=0 and avoid routing in that case
*/
bool route_pdu = true;
bool route_pdu = true;
if (mac_msg_ul.get()->get_sdu_lcid() == 0) {
uint8_t *x = mac_msg_ul.get()->get_sdu_ptr();
uint32_t sum = 0;
for (uint32_t i=0;i<mac_msg_ul.get()->get_payload_size();i++) {
uint32_t sum = 0;
for (uint32_t i = 0; i < mac_msg_ul.get()->get_payload_size(); i++) {
sum += x[i];
}
if (sum == 0) {
route_pdu = false;
route_pdu = false;
Warning("Received all zero PDU\n");
}
}
if (route_pdu) {
rlc->write_pdu(rnti,
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size());
rlc->write_pdu(rnti,
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size());
}
// Indicate scheduler to update BSR counters
sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
if ((int) mac_msg_ul.get()->get_payload_size() > most_data) {
most_data = (int) mac_msg_ul.get()->get_payload_size();
lcid_most_data = mac_msg_ul.get()->get_sdu_lcid();
}
// Save contention resolution if lcid == 0
if (mac_msg_ul.get()->get_sdu_lcid() == 0 && route_pdu) {
uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN;
uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN;
if (mac_msg_ul.get()->get_payload_size() >= nbytes) {
uint8_t *ue_cri_ptr = (uint8_t*) &conres_id;
uint8_t *pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the
for (uint32_t i=0;i<nbytes;i++) {
ue_cri_ptr[nbytes-i-1] = pkt_ptr[i];
uint8_t *ue_cri_ptr = (uint8_t *) &conres_id;
uint8_t *pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the
for (uint32_t i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i];
}
} else {
Error("Received CCCH UL message of invalid size=%d bytes\n", mac_msg_ul.get()->get_payload_size());
}
}
} else {
// Process MAC Control Element
if (!process_ce(mac_msg_ul.get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n");
}
}
}
}
mac_msg_ul.reset();
/* Process CE after all SDUs because we need to update BSR after */
bool bsr_received = false;
while(mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (!mac_msg_ul.get()->is_sdu()) {
// Process MAC Control Element
bsr_received |= process_ce(mac_msg_ul.get());
}
}
// If BSR is not received means that new data has arrived and there is no space for BSR transmission
if (!bsr_received && lcid_most_data > 2) {
// Add BSR to the LCID for which most data was received
sched->ul_bsr(rnti, lcid_most_data, 256, false); // false adds BSR instead of setting
Info("BSR not received. Giving extra grant\n");
}
Debug("MAC PDU processed\n");
@ -222,9 +255,10 @@ void ue::push_pdu(uint32_t tti, uint32_t len)
bool ue::process_ce(srslte::sch_subh *subh) {
uint32_t buff_size[4] = {0, 0, 0, 0};
uint32_t idx = 0;
float phr = 0;
uint16_t old_rnti = 0;
float phr = 0;
int idx = 0;
uint16_t old_rnti = 0;
bool is_bsr = false;
switch(subh->ce_type()) {
case srslte::sch_subh::PHR_REPORT:
phr = subh->get_phr();
@ -243,23 +277,26 @@ bool ue::process_ce(srslte::sch_subh *subh) {
}
break;
case srslte::sch_subh::TRUNC_BSR:
case srslte::sch_subh::SHORT_BSR:
case srslte::sch_subh::LONG_BSR:
case srslte::sch_subh::SHORT_BSR:
idx = subh->get_bsr(buff_size);
if (idx > 0) {
// Indicate BSR to scheduler
sched->ul_bsr(rnti, idx, 2*buff_size[idx]);
Info("CE: Received BSR rnti=0x%x, lcid=%d, value=%d\n", rnti, idx, buff_size[idx]);
} else if (idx == 0) {
// TODO: map lcid group to lcid
for (int i=0;i<4;i++) {
sched->ul_bsr(rnti, i, 2*buff_size[i]);
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
// Indicate BSR to scheduler
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
Info("CE: Received %s BSR rnti=0x%x, lcg=%d, lcid=%d, value=%d\n",
subh->ce_type()==srslte::sch_subh::SHORT_BSR?"Short":"Trunc", rnti, idx, lc_groups[idx][i], buff_size[idx]);
}
is_bsr = true;
break;
case srslte::sch_subh::LONG_BSR:
subh->get_bsr(buff_size);
for (int idx=0;idx<4;idx++) {
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
}
Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti,
buff_size[0], buff_size[1], buff_size[2], buff_size[3]);
} else {
printf("Error!\n");
}
is_bsr = true;
Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti,
buff_size[0], buff_size[1], buff_size[2], buff_size[3]);
break;
case srslte::sch_subh::PADDING:
Debug("CE: Received padding for rnti=0x%x\n", rnti);
@ -268,7 +305,7 @@ bool ue::process_ce(srslte::sch_subh *subh) {
Error("CE: Invalid lcid=0x%x\n", subh->ce_type());
break;
}
return true;
return is_bsr;
}

@ -24,6 +24,8 @@
*
*/
#include <srslte/interfaces/sched_interface.h>
#include <srslte/asn1/liblte_rrc.h>
#include "srslte/asn1/liblte_mme.h"
#include "upper/rrc.h"
@ -1311,7 +1313,9 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu)
// Add SRB2 and DRB1 to the scheduler
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
bearer_cfg.group = 0;
parent->mac->bearer_ue_cfg(rnti, 2, &bearer_cfg);
bearer_cfg.group = conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].lc_cnfg.ul_specific_params.log_chan_group;
parent->mac->bearer_ue_cfg(rnti, 3, &bearer_cfg);
// Configure SRB2 in RLC and PDCP

@ -26,7 +26,7 @@ ul_freq = 2565000000
tx_gain = 80
rx_gain = 60
#nof_rx_ant = 1
nof_rx_ant = 2
#device_name = auto
#device_args = auto
#time_adv_nsamples = auto

Loading…
Cancel
Save