|
|
|
@ -128,10 +128,10 @@ void rlc_am::reset()
|
|
|
|
|
reordering_timeout.reset();
|
|
|
|
|
if(tx_sdu) {
|
|
|
|
|
pool->deallocate(tx_sdu);
|
|
|
|
|
tx_sdu = NULL;
|
|
|
|
|
}
|
|
|
|
|
if(rx_sdu)
|
|
|
|
|
rx_sdu->reset();
|
|
|
|
|
if(rx_sdu) {
|
|
|
|
|
pool->deallocate(rx_sdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vt_a = 0;
|
|
|
|
|
vt_ms = RLC_AM_WINDOW_SIZE;
|
|
|
|
@ -827,6 +827,12 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|
|
|
|
rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure, at least one SDU (segment) has been added until this point
|
|
|
|
|
if (pdu->N_bytes == 0) {
|
|
|
|
|
log->error("Generated empty RLC PDU.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(tx_sdu)
|
|
|
|
|
header.fi |= RLC_FI_FIELD_NOT_END_ALIGNED; // Last byte does not correspond to last byte of SDU
|
|
|
|
|
|
|
|
|
@ -848,7 +854,6 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|
|
|
|
// Set SN
|
|
|
|
|
header.sn = vt_s;
|
|
|
|
|
vt_s = (vt_s + 1)%MOD;
|
|
|
|
|
log->info("%s PDU scheduled for tx. SN: %d (%d B)\n", rrc->get_rb_name(lcid).c_str(), header.sn, pdu->N_bytes);
|
|
|
|
|
|
|
|
|
|
// Place PDU in tx_window, write header and TX
|
|
|
|
|
tx_window[header.sn].buf = pdu;
|
|
|
|
@ -859,6 +864,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|
|
|
|
uint8_t *ptr = payload;
|
|
|
|
|
rlc_am_write_data_pdu_header(&header, &ptr);
|
|
|
|
|
memcpy(ptr, pdu->msg, pdu->N_bytes);
|
|
|
|
|
log->info_hex(payload, pdu->N_bytes, "%s PDU scheduled for tx. SN: %d (%d B)\n", rrc->get_rb_name(lcid).c_str(), header.sn, pdu->N_bytes);
|
|
|
|
|
|
|
|
|
|
debug_state();
|
|
|
|
|
return (ptr-payload) + pdu->N_bytes;
|
|
|
|
@ -868,8 +874,8 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_t>::iterator it;
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d",
|
|
|
|
|
rrc->get_rb_name(lcid).c_str(), header.sn);
|
|
|
|
|
log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d (%d B), %s",
|
|
|
|
|
rrc->get_rb_name(lcid).c_str(), header.sn, nof_bytes, rlc_fi_field_text[header.fi]);
|
|
|
|
|
|
|
|
|
|
if(!inside_rx_window(header.sn)) {
|
|
|
|
|
if(header.p) {
|
|
|
|
@ -1157,20 +1163,23 @@ void rlc_am::reassemble_rx_sdus()
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Iterate through rx_window, assembling and delivering SDUs
|
|
|
|
|
while(rx_window.end() != rx_window.find(vr_r))
|
|
|
|
|
{
|
|
|
|
|
// Handle any SDU segments
|
|
|
|
|
for(uint32_t i=0; i<rx_window[vr_r].header.N_li; i++)
|
|
|
|
|
{
|
|
|
|
|
int len = rx_window[vr_r].header.li[i];
|
|
|
|
|
uint32_t len = rx_window[vr_r].header.li[i];
|
|
|
|
|
if (rx_sdu->get_tailroom() >= len) {
|
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_r].buf->msg, len);
|
|
|
|
|
rx_sdu->N_bytes += len;
|
|
|
|
|
rx_window[vr_r].buf->msg += len;
|
|
|
|
|
rx_window[vr_r].buf->N_bytes -= len;
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str());
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", rrc->get_rb_name(lcid).c_str(), rx_sdu->N_bytes);
|
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
|
pdcp->write_pdu(lcid, rx_sdu);
|
|
|
|
|
|
|
|
|
|
rx_sdu = pool_allocate;
|
|
|
|
|
if (!rx_sdu) {
|
|
|
|
|
#ifdef RLC_AM_BUFFER_DEBUG
|
|
|
|
@ -1181,14 +1190,28 @@ void rlc_am::reassemble_rx_sdus()
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log->error("Cannot fit RLC PDU in SDU buffer, dropping both.\n");
|
|
|
|
|
pool->deallocate(rx_sdu);
|
|
|
|
|
pool->deallocate(rx_window[vr_r].buf);
|
|
|
|
|
rx_window.erase(vr_r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle last segment
|
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_r].buf->msg, rx_window[vr_r].buf->N_bytes);
|
|
|
|
|
uint32_t len = rx_window[vr_r].buf->N_bytes;
|
|
|
|
|
if (rx_sdu->get_tailroom() >= len) {
|
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_r].buf->msg, len);
|
|
|
|
|
rx_sdu->N_bytes += rx_window[vr_r].buf->N_bytes;
|
|
|
|
|
if(rlc_am_end_aligned(rx_window[vr_r].header.fi))
|
|
|
|
|
{
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str());
|
|
|
|
|
} else {
|
|
|
|
|
log->error("Cannot fit RLC PDU in SDU buffer, dropping both.\n");
|
|
|
|
|
pool->deallocate(rx_sdu);
|
|
|
|
|
pool->deallocate(rx_window[vr_r].buf);
|
|
|
|
|
rx_window.erase(vr_r);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(rlc_am_end_aligned(rx_window[vr_r].header.fi)) {
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", rrc->get_rb_name(lcid).c_str(), rx_sdu->N_bytes);
|
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
|
pdcp->write_pdu(lcid, rx_sdu);
|
|
|
|
|
rx_sdu = pool_allocate;
|
|
|
|
@ -1250,7 +1273,7 @@ void rlc_am::print_rx_segments()
|
|
|
|
|
for(it=rx_segments.begin();it!=rx_segments.end();it++) {
|
|
|
|
|
std::list<rlc_amd_rx_pdu_t>::iterator segit;
|
|
|
|
|
for(segit = it->second.segments.begin(); segit != it->second.segments.end(); segit++) {
|
|
|
|
|
ss << " SN:" << segit->header.sn << " SO:" << segit->header.so << " N:" << segit->buf->N_bytes << std::endl;
|
|
|
|
|
ss << " SN:" << segit->header.sn << " SO:" << segit->header.so << " N:" << segit->buf->N_bytes << " N_li: " << segit->header.N_li << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log->debug("%s\n", ss.str().c_str());
|
|
|
|
|