aboutsummaryrefslogtreecommitdiffstats
path: root/src/bts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bts.cpp')
-rw-r--r--src/bts.cpp286
1 files changed, 226 insertions, 60 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index d1d738c6..715fb515 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -52,11 +52,14 @@ static BTS s_bts;
static const struct rate_ctr_desc bts_ctr_description[] = {
{ "tbf.dl.alloc", "TBF DL Allocated "},
{ "tbf.dl.freed", "TBF DL Freed "},
+ { "tbf.dl.aborted", "TBF DL Aborted "},
{ "tbf.ul.alloc", "TBF UL Allocated "},
{ "tbf.ul.freed", "TBF UL Freed "},
+ { "tbf.ul.aborted", "TBF UL Aborted "},
{ "tbf.reused", "TBF Reused "},
{ "tbf.alloc.algo-a", "TBF Alloc Algo A "},
{ "tbf.alloc.algo-b", "TBF Alloc Algo B "},
+ { "tbf.failed.egprs-only", "TBF Failed EGPRS-only"},
{ "rlc.sent", "RLC Sent "},
{ "rlc.resent", "RLC Resent "},
{ "rlc.restarted", "RLC Restarted "},
@@ -127,8 +130,6 @@ BTS::BTS()
, m_ms_store(this)
{
memset(&m_bts, 0, sizeof(m_bts));
- INIT_LLIST_HEAD(&m_bts.ul_tbfs);
- INIT_LLIST_HEAD(&m_bts.dl_tbfs);
m_bts.bts = this;
/* initialize back pointers */
@@ -214,14 +215,14 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
{
uint8_t l, trx, ts, any_tbf = 0;
struct gprs_rlcmac_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
struct gprs_rlcmac_paging *pag;
uint8_t slot_mask[8];
int8_t first_ts; /* must be signed */
- llist_head *tbfs_lists[] = {
- &m_bts.ul_tbfs,
- &m_bts.dl_tbfs,
+ LListHead<gprs_rlcmac_tbf> *tbfs_lists[] = {
+ &m_ul_tbfs,
+ &m_dl_tbfs,
NULL
};
@@ -235,7 +236,8 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
* Don't mark, if TBF uses a different slot that is already marked. */
memset(slot_mask, 0, sizeof(slot_mask));
for (l = 0; tbfs_lists[l]; l++) {
- llist_pods_for_each_entry(tbf, tbfs_lists[l], list, lpods) {
+ llist_for_each(pos, tbfs_lists[l]) {
+ tbf = pos->entry();
first_ts = -1;
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
@@ -296,16 +298,17 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{
struct gprs_rlcmac_dl_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
/* only one TBF can poll on specific TS/FN, because scheduler can only
* schedule one downlink control block (with polling) at a FN per TS */
- llist_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) {
+ llist_for_each(pos, &m_dl_tbfs) {
+ tbf = as_dl_tbf(pos->entry());
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
- && tbf->control_ts == ts) {
- return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
+ && tbf->poll_ts == ts) {
+ return tbf;
}
}
return NULL;
@@ -313,16 +316,17 @@ gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{
struct gprs_rlcmac_ul_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
/* only one TBF can poll on specific TS/FN, because scheduler can only
* schedule one downlink control block (with polling) at a FN per TS */
- llist_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) {
+ llist_for_each(pos, &m_ul_tbfs) {
+ tbf = as_ul_tbf(pos->entry());
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
- && tbf->control_ts == ts) {
- return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ && tbf->poll_ts == ts) {
+ return tbf;
}
}
return NULL;
@@ -462,7 +466,10 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
uint8_t sb = 0;
uint32_t sb_fn = 0;
int rc;
- uint8_t plen;
+ int plen;
+ uint8_t usf = 7;
+ uint8_t tsc;
+ uint16_t ta;
rach_frame();
@@ -481,8 +488,11 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
qta = 0;
if (qta > 252)
qta = 252;
+
+ ta = qta >> 2;
+
if (sb) {
- rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, qta >> 2);
+ rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, ta);
if (rc < 0)
return rc;
LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d "
@@ -492,6 +502,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
sb_fn);
LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink "
"(AGCH)\n");
+ tsc = m_bts.trx[trx_no].pdch[ts_no].tsc;
} else {
// Create new TBF
#warning "Copy and pate with other routines.."
@@ -502,7 +513,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
/* FIXME: send reject */
return -EBUSY;
}
- tbf->set_ta(qta >> 2);
+ tbf->set_ta(ta);
tbf->set_state(GPRS_RLCMAC_FLOW);
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
tbf_timer_start(tbf, 3169, m_bts.t3169, 0);
@@ -514,21 +525,31 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
LOGP(DRLCMAC, LOGL_INFO, "%s TX: START Immediate "
"Assignment Uplink (AGCH)\n", tbf_name(tbf));
+ trx_no = tbf->trx->trx_no;
+ ts_no = tbf->first_ts;
+ usf = tbf->m_usf[ts_no];
+ tsc = tbf->tsc();
}
bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
bitvec_unhex(immediate_assignment,
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- if (sb)
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra,
- Fn, qta >> 2, m_bts.trx[trx_no].arfcn, ts_no,
- m_bts.trx[trx_no].pdch[ts_no].tsc, 0, 0, 0, 0, sb_fn, 1,
- m_bts.alpha, m_bts.gamma, -1);
- else
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra,
- Fn, tbf->ta(), tbf->trx->arfcn, tbf->first_ts, tbf->tsc(),
- tbf->tfi(), tbf->m_usf[tbf->first_ts], 0, 0, 0, 0,
- m_bts.alpha, m_bts.gamma, -1);
- pcu_l1if_tx_agch(immediate_assignment, plen);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ " - TRX=%d (%d) TS=%d TA=%d TSC=%d TFI=%d USF=%d\n",
+ trx_no, m_bts.trx[trx_no].arfcn, ts_no, ta, tsc,
+ tbf ? tbf->tfi() : -1, usf);
+
+ plen = Encoding::write_immediate_assignment(
+ tbf, immediate_assignment, 0, ra, Fn, ta,
+ m_bts.trx[trx_no].arfcn, ts_no, tsc, usf, 0, sb_fn,
+ m_bts.alpha, m_bts.gamma, -1);
+
+ if (plen >= 0) {
+ pcu_l1if_tx_agch(immediate_assignment, plen);
+ if (tbf)
+ tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
+ }
+
bitvec_free(immediate_assignment);
return 0;
@@ -552,7 +573,8 @@ void BTS::trigger_dl_ass(
/* change state */
dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
- dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
+ dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
/* start timer */
tbf_timer_start(dl_tbf, 0, Tassign_pacch);
} else {
@@ -570,17 +592,24 @@ void BTS::trigger_dl_ass(
void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi)
{
int plen;
+ unsigned int ts = tbf->first_ts;
LOGP(DRLCMAC, LOGL_INFO, "TX: START %s Immediate Assignment Downlink (PCH)\n", tbf_name(tbf));
bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
/* use request reference that has maximum distance to current time,
* so the assignment will not conflict with possible RACH requests. */
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 1, 125,
- (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta(),
- tbf->trx->arfcn, tbf->first_ts, tbf->tsc(), tbf->tfi(), 0, tbf->tlli(), poll,
- tbf->poll_fn, 0, m_bts.alpha, m_bts.gamma, -1);
- pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
+ LOGP(DRLCMAC, LOGL_DEBUG, " - TRX=%d (%d) TS=%d TA=%d pollFN=%d\n",
+ tbf->trx->trx_no, tbf->trx->arfcn,
+ ts, tbf->ta(), poll ? tbf->poll_fn : -1);
+ plen = Encoding::write_immediate_assignment(tbf, immediate_assignment, 1, 125,
+ (tbf->pdch[ts]->last_rts_fn + 21216) % 2715648, tbf->ta(),
+ tbf->trx->arfcn, ts, tbf->tsc(), 7, poll,
+ tbf->poll_fn, m_bts.alpha, m_bts.gamma, -1);
+ if (plen >= 0) {
+ pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
+ tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
+ }
bitvec_free(immediate_assignment);
}
@@ -775,9 +804,19 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+ tbf->direction == new_tbf->direction)
tbf_free(tbf);
+ if ((new_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
+ /* We now know that the PACCH really existed */
+ LOGP(DRLCMAC, LOGL_INFO,
+ "The TBF has been confirmed on the PACCH, "
+ "changed type from CCCH to PACCH for %s\n",
+ tbf_name(new_tbf));
+ new_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+ new_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ }
new_tbf->set_state(GPRS_RLCMAC_FLOW);
/* stop pending assignment timer */
new_tbf->stop_timer();
@@ -803,7 +842,8 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+ tbf->direction == new_tbf->direction)
tbf_free(tbf);
new_tbf->set_state(GPRS_RLCMAC_FLOW);
@@ -891,6 +931,11 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
struct pcu_l1_meas meas;
+ int num_blocks;
+ uint8_t bits_data[RLC_GPRS_WS/8];
+ bitvec bits;
+ int bsn_begin, bsn_end;
+ char show_bits[RLC_GPRS_WS + 1];
tfi = ack_nack->DOWNLINK_TFI;
tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
@@ -917,10 +962,24 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf));
tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ num_blocks = Decoding::decode_gprs_acknack_bits(
+ &ack_nack->Ack_Nack_Description, &bits,
+ &bsn_begin, &bsn_end, &tbf->m_window);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Got GPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+ "\"%s\"\n",
+ ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
+ bsn_begin, bsn_end, num_blocks,
+ (Decoding::extract_rbb(&bits, show_bits), show_bits));
+
rc = tbf->rcvd_dl_ack(
ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION,
- ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
- ack_nack->Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
+ bsn_begin, &bits);
if (rc == 1) {
tbf_free(tbf);
return;
@@ -945,6 +1004,112 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
}
}
+void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nack, uint32_t fn)
+{
+ int8_t tfi = 0; /* must be signed */
+ struct gprs_rlcmac_dl_tbf *tbf;
+ struct pcu_l1_meas meas;
+ int rc;
+ int num_blocks;
+ uint8_t bits_data[RLC_EGPRS_MAX_WS/8];
+ char show_bits[RLC_EGPRS_MAX_WS + 1];
+ bitvec bits;
+ int bsn_begin, bsn_end;
+
+ tfi = ack_nack->DOWNLINK_TFI;
+ tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+ "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
+ fn, tfi, trx_no(), ts_no);
+ return;
+ }
+ if (tbf->tfi() != tfi) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+ "wrong TFI=%d, ignoring!\n", tfi);
+ return;
+ }
+ tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
+ if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
+ tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+ LOGP(DRLCMAC, LOGL_NOTICE, "Recovered EGPRS downlink ack "
+ "for %s\n", tbf_name(tbf));
+ }
+ /* reset N3105 */
+ tbf->n3105 = 0;
+ tbf->stop_t3191();
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "RX: [PCU <- BTS] %s EGPRS Packet Downlink Ack/Nack\n",
+ tbf_name(tbf));
+ tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+ LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS ACK/NACK: "
+ "ut: %d, final: %d, bow: %d, eow: %d, ssn: %d, have_crbb: %d, "
+ "urbb_len:%d, %p, %p, %d, %d, win: %d-%d, urbb: %s\n",
+ (int)ack_nack->EGPRS_AckNack.UnionType,
+ (int)ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+ (int)ack_nack->EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW,
+ (int)ack_nack->EGPRS_AckNack.Desc.END_OF_WINDOW,
+ (int)ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+ (int)ack_nack->EGPRS_AckNack.Desc.Exist_CRBB,
+ (int)ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH,
+ (void *)&ack_nack->EGPRS_AckNack.UnionType,
+ (void *)&ack_nack->EGPRS_AckNack.Desc,
+ (int)offsetof(EGPRS_AckNack_t, Desc),
+ (int)offsetof(EGPRS_AckNack_w_len_t, Desc),
+ tbf->m_window.v_a(),
+ tbf->m_window.v_s(),
+ osmo_hexdump((const uint8_t *)&ack_nack->EGPRS_AckNack.Desc.URBB,
+ sizeof(ack_nack->EGPRS_AckNack.Desc.URBB)));
+
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ num_blocks = Decoding::decode_egprs_acknack_bits(
+ &ack_nack->EGPRS_AckNack.Desc, &bits,
+ &bsn_begin, &bsn_end, &tbf->m_window);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Got EGPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+ "\"%s\"\n",
+ ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+ bsn_begin, bsn_end, num_blocks,
+ (Decoding::extract_rbb(&bits, show_bits), show_bits)
+ );
+
+ rc = tbf->rcvd_dl_ack(
+ ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+ bsn_begin, &bits);
+ if (rc == 1) {
+ tbf_free(tbf);
+ return;
+ }
+
+ /* check for channel request */
+ if (ack_nack->Exist_ChannelRequestDescription) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we provide one:\n");
+
+ /* This call will register the new TBF with the MS on success */
+ tbf_alloc_ul(bts_data(), tbf->trx->trx_no,
+ tbf->ms_class(), tbf->ms()->egprs_ms_class(),
+ tbf->tlli(), tbf->ta(), tbf->ms());
+
+ /* schedule uplink assignment */
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ }
+
+ /* get measurements */
+ if (tbf->ms()) {
+ /* TODO: Implement Measurements parsing for EGPRS */
+ /*
+ get_meas(&meas, &ack_nack->Channel_Quality_Report);
+ tbf->ms()->update_l1_meas(&meas);
+ */
+ }
+}
+
void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn)
{
struct gprs_rlcmac_sba *sba;
@@ -968,28 +1133,24 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request,
ta = ms->ta();
}
+ /* We got a RACH so the MS was in packet idle mode and thus
+ * didn't have any active TBFs */
if (ul_tbf) {
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still "
"exists. Killing pending UL TBF\n",
tlli, tbf_name(ul_tbf));
- /* The MS will not use the old TBF again, so we can
- * safely throw it away immediately */
tbf_free(ul_tbf);
ul_tbf = NULL;
}
if (dl_tbf) {
- /* TODO: There a chance that releasing dl_tbf can be
- * avoided if this PDCH is the control TS of dl_tbf,
- * but this needs to be checked with the spec. If an MS
- * losed the DL TBF because of PDCH mismatches only,
- * this check would make sense. */
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still exists. "
"Release pending DL TBF\n", tlli,
tbf_name(dl_tbf));
- dl_tbf->release();
+ tbf_free(dl_tbf);
+ dl_tbf = NULL;
}
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
"in packet resource request of single "
@@ -1104,6 +1265,9 @@ int gprs_rlcmac_pdch::rcv_control_block(
case MT_PACKET_DOWNLINK_ACK_NACK:
rcv_control_dl_ack_nack(&ul_control_block->u.Packet_Downlink_Ack_Nack, fn);
break;
+ case MT_EGPRS_PACKET_DOWNLINK_ACK_NACK:
+ rcv_control_egprs_dl_ack_nack(&ul_control_block->u.Egprs_Packet_Downlink_Ack_Nack, fn);
+ break;
case MT_PACKET_RESOURCE_REQUEST:
rcv_resource_request(&ul_control_block->u.Packet_Resource_Request, fn);
break;
@@ -1137,7 +1301,7 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
}
LOGP(DRLCMACUL, LOGL_DEBUG, "Got RLC block, coding scheme: %s, "
- "length: %d (%d))\n", cs.name(), len, cs.maxBytesUL());
+ "length: %d (%d))\n", cs.name(), len, cs.usedSizeUL());
if (cs.isGprs())
return rcv_block_gprs(data, fn, meas, cs);
@@ -1155,9 +1319,9 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
struct pcu_l1_meas *meas, GprsCodingScheme cs)
{
int rc;
- struct gprs_rlc_ul_header_egprs rlc_dec;
+ struct gprs_rlc_data_info rlc_dec;
struct gprs_rlcmac_ul_tbf *tbf;
- unsigned len = cs.maxBytesUL();
+ unsigned len = cs.sizeUL();
/* These are always data blocks, since EGPRS still uses CS-1 for
* control blocks (see 44.060, section 10.3, 1st par.)
@@ -1180,6 +1344,8 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
}
}
+ LOGP(DRLCMACUL, LOGL_DEBUG, " UL data: %s\n", osmo_hexdump(data, len));
+
rc = Decoding::rlc_parse_ul_data_header(&rlc_dec, data, cs);
if (rc < 0) {
LOGP(DRLCMACUL, LOGL_ERROR,
@@ -1205,7 +1371,7 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
return 0;
}
- return tbf->rcv_data_block_acknowledged(&rlc_dec, data, len, meas);
+ return tbf->rcv_data_block_acknowledged(&rlc_dec, data, meas);
}
int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
@@ -1239,13 +1405,15 @@ int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
return rc;
}
-gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi,
+gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(
+ LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir)
{
gprs_rlcmac_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
- llist_pods_for_each_entry(tbf, tbf_list, list, lpods) {
+ llist_for_each(pos, tbf_list) {
+ tbf = pos->entry();
if (tbf->tfi() != tfi)
continue;
if (!tbf->pdch[ts_no])
@@ -1257,14 +1425,12 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l
gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi)
{
- return static_cast<gprs_rlcmac_ul_tbf *>(
- tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF));
+ return as_ul_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF));
}
gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi)
{
- return static_cast<gprs_rlcmac_dl_tbf *>(
- tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF));
+ return as_dl_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF));
}
/* lookup TBF Entity (by TFI) */
@@ -1300,7 +1466,7 @@ void gprs_rlcmac_pdch::attach_tbf(gprs_rlcmac_tbf *tbf)
m_num_tbfs[tbf->direction] += 1;
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ ul_tbf = as_ul_tbf(tbf);
m_assigned_usf |= 1 << ul_tbf->m_usf[ts_no];
}
m_assigned_tfi[tbf->direction] |= 1UL << tbf->tfi();
@@ -1320,7 +1486,7 @@ void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf)
m_num_tbfs[tbf->direction] -= 1;
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ ul_tbf = as_ul_tbf(tbf);
m_assigned_usf &= ~(1 << ul_tbf->m_usf[ts_no]);
}
m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi());