|
|
@ -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++) {
|
|
|
|
for(int i=0;i<NOF_HARQ_PROCESSES;i++) {
|
|
|
|
pending_buffers[i] = NULL;
|
|
|
|
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;
|
|
|
|
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)
|
|
|
|
srslte_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t tti)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return &softbuffer_rx[tti%NOF_HARQ_PROCESSES];
|
|
|
|
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) {
|
|
|
|
if (pcap) {
|
|
|
|
pcap->write_ul_crnti(pdu, nof_bytes, rnti, true, last_tti);
|
|
|
|
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()) {
|
|
|
|
while(mac_msg_ul.next()) {
|
|
|
|
assert(mac_msg_ul.get());
|
|
|
|
assert(mac_msg_ul.get());
|
|
|
|
if (mac_msg_ul.get()->is_sdu())
|
|
|
|
if (mac_msg_ul.get()->is_sdu()) {
|
|
|
|
{
|
|
|
|
|
|
|
|
// Route logical channel
|
|
|
|
// Route logical channel
|
|
|
|
log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), 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",
|
|
|
|
"PDU: rnti=0x%x, lcid=%d, %d bytes\n",
|
|
|
|
rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size());
|
|
|
|
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
|
|
|
|
/* 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
|
|
|
|
* 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) {
|
|
|
|
if (mac_msg_ul.get()->get_sdu_lcid() == 0) {
|
|
|
|
uint8_t *x = mac_msg_ul.get()->get_sdu_ptr();
|
|
|
|
uint8_t *x = mac_msg_ul.get()->get_sdu_ptr();
|
|
|
|
uint32_t sum = 0;
|
|
|
|
uint32_t sum = 0;
|
|
|
|
for (uint32_t i=0;i<mac_msg_ul.get()->get_payload_size();i++) {
|
|
|
|
for (uint32_t i = 0; i < mac_msg_ul.get()->get_payload_size(); i++) {
|
|
|
|
sum += x[i];
|
|
|
|
sum += x[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sum == 0) {
|
|
|
|
if (sum == 0) {
|
|
|
|
route_pdu = false;
|
|
|
|
route_pdu = false;
|
|
|
|
Warning("Received all zero PDU\n");
|
|
|
|
Warning("Received all zero PDU\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (route_pdu) {
|
|
|
|
if (route_pdu) {
|
|
|
|
rlc->write_pdu(rnti,
|
|
|
|
rlc->write_pdu(rnti,
|
|
|
|
mac_msg_ul.get()->get_sdu_lcid(),
|
|
|
|
mac_msg_ul.get()->get_sdu_lcid(),
|
|
|
|
mac_msg_ul.get()->get_sdu_ptr(),
|
|
|
|
mac_msg_ul.get()->get_sdu_ptr(),
|
|
|
|
mac_msg_ul.get()->get_payload_size());
|
|
|
|
mac_msg_ul.get()->get_payload_size());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Indicate scheduler to update BSR counters
|
|
|
|
// 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());
|
|
|
|
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
|
|
|
|
// Save contention resolution if lcid == 0
|
|
|
|
if (mac_msg_ul.get()->get_sdu_lcid() == 0 && route_pdu) {
|
|
|
|
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) {
|
|
|
|
if (mac_msg_ul.get()->get_payload_size() >= nbytes) {
|
|
|
|
uint8_t *ue_cri_ptr = (uint8_t*) &conres_id;
|
|
|
|
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
|
|
|
|
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++) {
|
|
|
|
for (uint32_t i = 0; i < nbytes; i++) {
|
|
|
|
ue_cri_ptr[nbytes-i-1] = pkt_ptr[i];
|
|
|
|
ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Error("Received CCCH UL message of invalid size=%d bytes\n", mac_msg_ul.get()->get_payload_size());
|
|
|
|
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");
|
|
|
|
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) {
|
|
|
|
bool ue::process_ce(srslte::sch_subh *subh) {
|
|
|
|
uint32_t buff_size[4] = {0, 0, 0, 0};
|
|
|
|
uint32_t buff_size[4] = {0, 0, 0, 0};
|
|
|
|
uint32_t idx = 0;
|
|
|
|
float phr = 0;
|
|
|
|
float phr = 0;
|
|
|
|
int idx = 0;
|
|
|
|
uint16_t old_rnti = 0;
|
|
|
|
uint16_t old_rnti = 0;
|
|
|
|
|
|
|
|
bool is_bsr = false;
|
|
|
|
switch(subh->ce_type()) {
|
|
|
|
switch(subh->ce_type()) {
|
|
|
|
case srslte::sch_subh::PHR_REPORT:
|
|
|
|
case srslte::sch_subh::PHR_REPORT:
|
|
|
|
phr = subh->get_phr();
|
|
|
|
phr = subh->get_phr();
|
|
|
@ -243,23 +277,26 @@ bool ue::process_ce(srslte::sch_subh *subh) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case srslte::sch_subh::TRUNC_BSR:
|
|
|
|
case srslte::sch_subh::TRUNC_BSR:
|
|
|
|
case srslte::sch_subh::SHORT_BSR:
|
|
|
|
case srslte::sch_subh::SHORT_BSR:
|
|
|
|
case srslte::sch_subh::LONG_BSR:
|
|
|
|
|
|
|
|
idx = subh->get_bsr(buff_size);
|
|
|
|
idx = subh->get_bsr(buff_size);
|
|
|
|
if (idx > 0) {
|
|
|
|
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
|
|
|
|
// Indicate BSR to scheduler
|
|
|
|
// Indicate BSR to scheduler
|
|
|
|
sched->ul_bsr(rnti, idx, 2*buff_size[idx]);
|
|
|
|
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
|
|
|
|
Info("CE: Received BSR rnti=0x%x, lcid=%d, value=%d\n", rnti, idx, buff_size[idx]);
|
|
|
|
Info("CE: Received %s BSR rnti=0x%x, lcg=%d, lcid=%d, value=%d\n",
|
|
|
|
} else if (idx == 0) {
|
|
|
|
subh->ce_type()==srslte::sch_subh::SHORT_BSR?"Short":"Trunc", rnti, idx, lc_groups[idx][i], buff_size[idx]);
|
|
|
|
// TODO: map lcid group to lcid
|
|
|
|
}
|
|
|
|
for (int i=0;i<4;i++) {
|
|
|
|
is_bsr = true;
|
|
|
|
sched->ul_bsr(rnti, i, 2*buff_size[i]);
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
case srslte::sch_subh::PADDING:
|
|
|
|
case srslte::sch_subh::PADDING:
|
|
|
|
Debug("CE: Received padding for rnti=0x%x\n", rnti);
|
|
|
|
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());
|
|
|
|
Error("CE: Invalid lcid=0x%x\n", subh->ce_type());
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return is_bsr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|