aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bitvector.cpp18
-rw-r--r--src/bitvector.h1
-rw-r--r--src/bts.cpp286
-rw-r--r--src/bts.h40
-rw-r--r--src/csn1.cpp1
-rw-r--r--src/decoding.cpp267
-rw-r--r--src/decoding.h21
-rw-r--r--src/encoding.cpp940
-rw-r--r--src/encoding.h54
-rw-r--r--src/gprs_bssgp_pcu.cpp134
-rw-r--r--src/gprs_coding_scheme.cpp204
-rw-r--r--src/gprs_coding_scheme.h129
-rw-r--r--src/gprs_ms.cpp255
-rw-r--r--src/gprs_ms.h22
-rw-r--r--src/gprs_rlcmac_sched.cpp52
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp41
-rw-r--r--src/gsm_rlcmac.cpp8
-rw-r--r--src/gsm_rlcmac.h3
-rw-r--r--src/pcu_main.cpp7
-rw-r--r--src/pcu_utils.h16
-rw-r--r--src/pcu_vty.c140
-rw-r--r--src/pcu_vty_functions.cpp73
-rw-r--r--src/pcu_vty_functions.h1
-rw-r--r--src/poll_controller.cpp9
-rw-r--r--src/rlc.cpp176
-rw-r--r--src/rlc.h186
-rw-r--r--src/tbf.cpp336
-rw-r--r--src/tbf.h120
-rw-r--r--src/tbf_dl.cpp640
-rw-r--r--src/tbf_ul.cpp51
-rw-r--r--tests/alloc/AllocTest.cpp12
-rw-r--r--tests/edge/EdgeTest.cpp617
-rw-r--r--tests/edge/EdgeTest.ok8
-rw-r--r--tests/ms/MsTest.cpp4
-rw-r--r--tests/tbf/TbfTest.cpp279
-rw-r--r--tests/tbf/TbfTest.err2935
-rw-r--r--tests/tbf/TbfTest.ok23
-rw-r--r--tests/types/TypesTest.cpp62
-rw-r--r--tests/types/TypesTest.ok3
39 files changed, 6737 insertions, 1437 deletions
diff --git a/src/bitvector.cpp b/src/bitvector.cpp
index 43feebc..1028407 100644
--- a/src/bitvector.cpp
+++ b/src/bitvector.cpp
@@ -117,3 +117,21 @@ int bitvec_write_field(struct bitvec *bv, unsigned& write_index, uint64_t val, u
write_index += len;
return 0;
}
+
+int bitvec_write_field_lh(struct bitvec *bv, unsigned& write_index,
+ uint64_t val, unsigned len)
+{
+ unsigned int i;
+ int rc;
+ bv->cur_bit = write_index;
+ for (i = 0; i < len; i++) {
+ bit_value bit = L;
+ if (val & ((uint64_t)1 << (len - i - 1)))
+ bit = H;
+ rc = bitvec_set_bit(bv, bit);
+ if (rc)
+ return rc;
+ }
+ write_index += len;
+ return 0;
+}
diff --git a/src/bitvector.h b/src/bitvector.h
index 36bdbab..b14d204 100644
--- a/src/bitvector.h
+++ b/src/bitvector.h
@@ -39,6 +39,7 @@ unsigned int bitvec_pack(struct bitvec *bv, uint8_t *buffer);
unsigned int bitvec_unpack(struct bitvec *bv, uint8_t *buffer);
uint64_t bitvec_read_field(struct bitvec *bv, unsigned& read_index, unsigned len);
int bitvec_write_field(struct bitvec *bv, unsigned& write_index, uint64_t val, unsigned len);
+int bitvec_write_field_lh(struct bitvec *bv, unsigned& write_index, uint64_t val, unsigned len);
/*! }@ */
diff --git a/src/bts.cpp b/src/bts.cpp
index d1d738c..715fb51 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());
diff --git a/src/bts.h b/src/bts.h
index 45432ea..119f6b2 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -107,9 +107,11 @@ private:
void rcv_control_ack(Packet_Control_Acknowledgement_t *, uint32_t fn);
void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn);
+ void rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *, uint32_t fn);
void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn);
void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn);
- gprs_rlcmac_tbf *tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi,
+ gprs_rlcmac_tbf *tbf_from_list_by_tfi(
+ LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir);
gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir);
@@ -154,7 +156,9 @@ struct gprs_rlcmac_bts {
uint8_t cs3;
uint8_t cs4;
uint8_t initial_cs_dl, initial_cs_ul;
+ uint8_t initial_mcs_dl, initial_mcs_ul;
uint8_t max_cs_dl, max_cs_ul;
+ uint8_t max_mcs_dl, max_mcs_ul;
uint8_t force_cs; /* 0=use from BTS 1=use from VTY */
uint16_t force_llc_lifetime; /* overrides lifetime from SGSN */
uint32_t llc_discard_csec;
@@ -184,12 +188,8 @@ struct gprs_rlcmac_bts {
uint8_t cs_adj_lower_limit;
struct {int16_t low; int16_t high;} cs_lqual_ranges[4];
uint16_t cs_downgrade_threshold; /* downgrade if less packets left (DL) */
-
- /* TBF handling, make private or move into TBFController */
- /* list of uplink TBFs */
- struct llist_head ul_tbfs;
- /* list of downlink TBFs */
- struct llist_head dl_tbfs;
+ uint16_t ws_base;
+ uint16_t ws_pdch; /* increase WS by this value per PDCH */
/* State for dynamic algorithm selection */
int multislot_disabled;
@@ -212,11 +212,14 @@ public:
enum {
CTR_TBF_DL_ALLOCATED,
CTR_TBF_DL_FREED,
+ CTR_TBF_DL_ABORTED,
CTR_TBF_UL_ALLOCATED,
CTR_TBF_UL_FREED,
+ CTR_TBF_UL_ABORTED,
CTR_TBF_REUSED,
CTR_TBF_ALLOC_ALGO_A,
CTR_TBF_ALLOC_ALGO_B,
+ CTR_TBF_FAILED_EGPRS_ONLY,
CTR_RLC_SENT,
CTR_RLC_RESENT,
CTR_RLC_RESTARTED,
@@ -285,11 +288,14 @@ public:
*/
void tbf_dl_created();
void tbf_dl_freed();
+ void tbf_dl_aborted();
void tbf_ul_created();
void tbf_ul_freed();
+ void tbf_ul_aborted();
void tbf_reused();
void tbf_alloc_algo_a();
void tbf_alloc_algo_b();
+ void tbf_failed_egprs_only();
void rlc_sent();
void rlc_resent();
void rlc_restarted();
@@ -319,6 +325,8 @@ public:
struct rate_ctr_group *rate_counters() const;
struct osmo_stat_item_group *stat_items() const;
+ LListHead<gprs_rlcmac_tbf>& ul_tbfs();
+ LListHead<gprs_rlcmac_tbf>& dl_tbfs();
private:
int m_cur_fn;
int m_cur_blk_fn;
@@ -330,6 +338,11 @@ private:
GprsMsStorage m_ms_store;
+ /* list of uplink TBFs */
+ LListHead<gprs_rlcmac_tbf> m_ul_tbfs;
+ /* list of downlink TBFs */
+ LListHead<gprs_rlcmac_tbf> m_dl_tbfs;
+
private:
/* disable copying to avoid slicing */
BTS(const BTS&);
@@ -361,6 +374,16 @@ inline GprsMs *BTS::ms_by_imsi(const char *imsi)
return ms_store().get_ms(0, 0, imsi);
}
+inline LListHead<gprs_rlcmac_tbf>& BTS::ul_tbfs()
+{
+ return m_ul_tbfs;
+}
+
+inline LListHead<gprs_rlcmac_tbf>& BTS::dl_tbfs()
+{
+ return m_dl_tbfs;
+}
+
inline BTS *gprs_rlcmac_pdch::bts() const
{
return trx->bts;
@@ -405,11 +428,14 @@ inline struct osmo_stat_item_group *BTS::stat_items() const
CREATE_COUNT_INLINE(tbf_dl_created, CTR_TBF_DL_ALLOCATED)
CREATE_COUNT_INLINE(tbf_dl_freed, CTR_TBF_DL_FREED)
+CREATE_COUNT_INLINE(tbf_dl_aborted, CTR_TBF_DL_ABORTED)
CREATE_COUNT_INLINE(tbf_ul_created, CTR_TBF_UL_ALLOCATED)
CREATE_COUNT_INLINE(tbf_ul_freed, CTR_TBF_UL_FREED)
+CREATE_COUNT_INLINE(tbf_ul_aborted, CTR_TBF_UL_ABORTED)
CREATE_COUNT_INLINE(tbf_reused, CTR_TBF_REUSED)
CREATE_COUNT_INLINE(tbf_alloc_algo_a, CTR_TBF_ALLOC_ALGO_A)
CREATE_COUNT_INLINE(tbf_alloc_algo_b, CTR_TBF_ALLOC_ALGO_B)
+CREATE_COUNT_INLINE(tbf_failed_egprs_only, CTR_TBF_FAILED_EGPRS_ONLY)
CREATE_COUNT_INLINE(rlc_sent, CTR_RLC_SENT)
CREATE_COUNT_INLINE(rlc_resent, CTR_RLC_RESENT)
CREATE_COUNT_INLINE(rlc_restarted, CTR_RLC_RESTARTED)
diff --git a/src/csn1.cpp b/src/csn1.cpp
index 377c50f..54cc411 100644
--- a/src/csn1.cpp
+++ b/src/csn1.cpp
@@ -549,6 +549,7 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig
csnStreamInit(&arT, bit_offset, length);
arT.direction = 1;
+ LOGPC(DCSN1, LOGL_NOTICE, "ptr = %p | offset = %d | ", (void *)data, (int)pDescr->offset);
Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
if (Status >= 0)
diff --git a/src/decoding.cpp b/src/decoding.cpp
index abaa97f..f2b548c 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -23,6 +23,7 @@
extern "C" {
#include <osmocom/core/utils.h>
+#include <osmocom/core/bitcomp.h>
}
#include <arpa/inet.h>
@@ -180,7 +181,7 @@ static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
}
int Decoding::rlc_data_from_ul_data(
- const struct gprs_rlc_ul_data_block_info *rdbi, GprsCodingScheme cs,
+ const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
uint32_t *tlli)
{
@@ -281,47 +282,6 @@ int Decoding::rlc_data_from_ul_data(
return num_chunks;
}
-int Decoding::tlli_from_ul_data(const uint8_t *data, uint8_t len,
- uint32_t *tlli)
-{
- struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
- struct rlc_li_field *li;
- uint8_t e;
- uint32_t _tlli;
-
- if (!rh->ti)
- return -EINVAL;
-
- data += 3;
- len -= 3;
- e = rh->e;
- /* if E is not set (LI follows) */
- while (!e) {
- if (!len) {
- LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
- "but no more data\n");
- return -EINVAL;
- }
- /* get new E */
- li = (struct rlc_li_field *)data;
- if (li->e == 0) /* if LI==0, E is interpreted as '1' */
- e = 1;
- else
- e = li->e;
- data++;
- len--;
- }
- if (len < 4) {
- LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of frame "
- "border\n");
- return -EINVAL;
- }
- memcpy(&_tlli, data, 4);
- *tlli = ntohl(_tlli);
-
- return 0;
-}
-
uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
{
int i;
@@ -369,23 +329,35 @@ void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
show_rbb[64] = '\0';
}
-int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_ul_header_egprs *rlc,
+void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
+{
+ unsigned int i;
+ for (i = 0; i < rbb->cur_bit; i++) {
+ uint8_t bit;
+ bit = bitvec_get_bit_pos(rbb, i);
+ show_rbb[i] = bit == 1 ? 'R' : 'I';
+ }
+
+ show_rbb[i] = '\0';
+}
+
+int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
const uint8_t *data, GprsCodingScheme cs)
{
const struct gprs_rlc_ul_header_egprs_3 *egprs3;
const struct rlc_ul_header *gprs;
unsigned int e_ti_header;
unsigned int cur_bit = 0;
- unsigned int data_len = 0;
-
- rlc->cs = cs;
-
- data_len = cs.maxDataBlockBytes();
+ int punct, punct2, with_padding, cps;
+ unsigned int offs;
switch(cs.headerTypeData()) {
case GprsCodingScheme::HEADER_GPRS_DATA:
gprs = static_cast<struct rlc_ul_header *>
((void *)data);
+
+ gprs_rlc_data_info_init_ul(rlc, cs, false);
+
rlc->r = gprs->r;
rlc->si = gprs->si;
rlc->tfi = gprs->tfi;
@@ -400,20 +372,23 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_ul_header_egprs *rlc,
rlc->block_info[0].ti = gprs->ti;
rlc->block_info[0].spb = 0;
- cur_bit += 3 * 8;
-
- rlc->data_offs_bits[0] = cur_bit;
- rlc->block_info[0].data_len = data_len;
- cur_bit += data_len * 8;
+ cur_bit += rlc->data_offs_bits[0];
+ /* skip data area */
+ cur_bit += cs.maxDataBlockBytes() * 8;
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
egprs3 = static_cast<struct gprs_rlc_ul_header_egprs_3 *>
((void *)data);
+
+ cps = (egprs3->cps_a << 0) | (egprs3->cps_b << 2);
+ gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
+ gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
+
rlc->r = egprs3->r;
rlc->si = egprs3->si;
rlc->tfi = (egprs3->tfi_a << 0) | (egprs3->tfi_b << 2);
- rlc->cps = (egprs3->cps_a << 0) | (egprs3->cps_b << 2);
+ rlc->cps = cps;
rlc->rsb = egprs3->rsb;
rlc->num_data_blocks = 1;
@@ -423,17 +398,18 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_ul_header_egprs *rlc,
rlc->block_info[0].bsn =
(egprs3->bsn1_a << 0) | (egprs3->bsn1_b << 5);
- cur_bit += 3 * 8 + 7;
+ cur_bit += rlc->data_offs_bits[0] - 2;
- e_ti_header = (data[3] + (data[4] << 8)) >> 7;
+ offs = rlc->data_offs_bits[0] / 8;
+ OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
+
+ e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
rlc->block_info[0].e = !!(e_ti_header & 0x01);
rlc->block_info[0].ti = !!(e_ti_header & 0x02);
cur_bit += 2;
- rlc->data_offs_bits[0] = cur_bit;
- rlc->block_info[0].data_len = data_len;
- cur_bit += data_len * 8;
-
+ /* skip data area */
+ cur_bit += cs.maxDataBlockBytes() * 8;
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
@@ -464,7 +440,7 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_ul_header_egprs *rlc,
* \returns the number of bytes copied
*/
unsigned int Decoding::rlc_copy_to_aligned_buffer(
- const struct gprs_rlc_ul_header_egprs *rlc,
+ const struct gprs_rlc_data_info *rlc,
unsigned int data_block_idx,
const uint8_t *src, uint8_t *buffer)
{
@@ -474,7 +450,7 @@ unsigned int Decoding::rlc_copy_to_aligned_buffer(
uint8_t c, last_c;
uint8_t *dst;
- const struct gprs_rlc_ul_data_block_info *rdbi;
+ const struct gprs_rlc_data_block_info *rdbi;
OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
rdbi = &rlc->block_info[data_block_idx];
@@ -514,7 +490,7 @@ unsigned int Decoding::rlc_copy_to_aligned_buffer(
* buffer otherwise.
*/
const uint8_t *Decoding::rlc_get_data_aligned(
- const struct gprs_rlc_ul_header_egprs *rlc,
+ const struct gprs_rlc_data_info *rlc,
unsigned int data_block_idx,
const uint8_t *src, uint8_t *buffer)
{
@@ -534,3 +510,168 @@ const uint8_t *Decoding::rlc_get_data_aligned(
Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
return buffer;
}
+
+static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
+ gprs_rlc_dl_window *window)
+{
+ int num_blocks, i;
+
+ num_blocks = window->mod_sns(window->v_s() - window->v_a());
+ for (i = 0; i < num_blocks; i++)
+ bitvec_set_bit(bits, ONE);
+
+ *bsn_begin = window->v_a();
+ *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
+ return num_blocks;
+}
+
+int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
+ bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
+{
+ int urbb_len = desc->URBB_LENGTH;
+ int crbb_len = 0;
+ int num_blocks = 0;
+ struct bitvec urbb;
+ int i;
+ bool have_bitmap;
+ int implicitly_acked_blocks;
+ int ssn = desc->STARTING_SEQUENCE_NUMBER;
+ int rc;
+
+ if (desc->FINAL_ACK_INDICATION)
+ return handle_final_ack(bits, bsn_begin, bsn_end, window);
+
+ if (desc->Exist_CRBB)
+ crbb_len = desc->CRBB_LENGTH;
+
+ have_bitmap = (urbb_len + crbb_len) > 0;
+
+ /*
+ * bow & bitmap present:
+ * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
+ * bow & not bitmap present:
+ * V(A)-> [ 11111...11111 ] . SSN .... V(S)
+ * not bow & bitmap present:
+ * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
+ * not bow & not bitmap present:
+ * V(A)-> ... [] . SSN .... V(S)
+ */
+
+ if (desc->BEGINNING_OF_WINDOW) {
+ implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
+
+ for (i = 0; i < implicitly_acked_blocks; i++)
+ bitvec_set_bit(bits, ONE);
+
+ num_blocks += implicitly_acked_blocks;
+ }
+
+ if (!have_bitmap)
+ goto aborted;
+
+ /* next bit refers to V(Q) and thus is always zero (and not
+ * transmitted) */
+ bitvec_set_bit(bits, ZERO);
+ num_blocks += 1;
+
+ if (crbb_len > 0) {
+ int old_len = bits->cur_bit;
+ struct bitvec crbb;
+
+ crbb.data = (uint8_t *)desc->CRBB;
+ crbb.data_len = sizeof(desc->CRBB);
+ crbb.cur_bit = desc->CRBB_LENGTH;
+
+ rc = osmo_t4_decode(&crbb, desc->CRBB_STARTING_COLOR_CODE,
+ bits);
+
+ if (rc < 0) {
+ LOGP(DRLCMACUL, LOGL_NOTICE,
+ "Failed to decode CRBB: "
+ "length %d, data '%s'\n",
+ desc->CRBB_LENGTH,
+ osmo_hexdump(crbb.data, crbb.data_len));
+ /* We don't know the SSN offset for the URBB,
+ * return what we have so far and assume the
+ * bitmap has stopped here */
+ goto aborted;
+ }
+
+ LOGP(DRLCMACDL, LOGL_DEBUG,
+ "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
+ desc->CRBB_LENGTH, bits->cur_bit - old_len,
+ desc->CRBB_STARTING_COLOR_CODE,
+ osmo_hexdump(
+ desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
+ );
+
+ num_blocks += (bits->cur_bit - old_len);
+ }
+
+ urbb.cur_bit = 0;
+ urbb.data = (uint8_t *)desc->URBB;
+ urbb.data_len = sizeof(desc->URBB);
+
+ for (i = urbb_len; i > 0; i--) {
+ /*
+ * Set bit at the appropriate position (see 3GPP TS
+ * 44.060 12.3.1)
+ */
+ int is_ack = bitvec_get_bit_pos(&urbb, i-1);
+ bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
+ }
+ num_blocks += urbb_len;
+
+aborted:
+ *bsn_begin = window->v_a();
+ *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
+
+ return num_blocks;
+}
+
+int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
+ bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
+{
+ int urbb_len = RLC_GPRS_WS;
+ int num_blocks;
+ struct bitvec urbb;
+
+ if (desc->FINAL_ACK_INDICATION)
+ return handle_final_ack(bits, bsn_begin, bsn_end, window);
+
+ *bsn_begin = window->v_a();
+ *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
+
+ num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
+
+ if (num_blocks < 0 || num_blocks > urbb_len) {
+ *bsn_end = *bsn_begin;
+ LOGP(DRLCMACUL, LOGL_NOTICE,
+ "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
+ *bsn_begin, *bsn_end, num_blocks);
+ return -EINVAL;
+ }
+
+ urbb.cur_bit = 0;
+ urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
+ urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
+
+ /*
+ * TS 44.060, 12.3:
+ * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
+ * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
+ *
+ * We are only interested in the range from V(A) to SSN-1 which is
+ * num_blocks large. The RBB is laid out as
+ * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
+ * so we want to start with [V(A)] and go backwards until we reach
+ * [SSN-1] to get the needed BSNs in an increasing order. Note that
+ * the bit numbers are counted from the end of the buffer.
+ */
+ for (int i = num_blocks; i > 0; i--) {
+ int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
+ bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
+ }
+
+ return num_blocks;
+}
diff --git a/src/decoding.h b/src/decoding.h
index 1cda7b4..58ecd18 100644
--- a/src/decoding.h
+++ b/src/decoding.h
@@ -24,6 +24,8 @@
#include <stdint.h>
+struct bitvec;
+
class Decoding {
public:
struct RlcData {
@@ -32,25 +34,32 @@ public:
bool is_complete;
};
- static int tlli_from_ul_data(const uint8_t *data, uint8_t len,
- uint32_t *tlli);
static int rlc_data_from_ul_data(
- const struct gprs_rlc_ul_data_block_info *rdbi,
+ const struct gprs_rlc_data_block_info *rdbi,
GprsCodingScheme cs, const uint8_t *data, RlcData *chunks,
unsigned int chunks_size, uint32_t *tlli);
static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
static uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
static void extract_rbb(const uint8_t *rbb, char *extracted_rbb);
+ static void extract_rbb(const struct bitvec *rbb, char *show_rbb);
- static int rlc_parse_ul_data_header(struct gprs_rlc_ul_header_egprs *rlc,
+ static int rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
const uint8_t *data, GprsCodingScheme cs);
static unsigned int rlc_copy_to_aligned_buffer(
- const struct gprs_rlc_ul_header_egprs *rlc,
+ const struct gprs_rlc_data_info *rlc,
unsigned int data_block_idx,
const uint8_t *src, uint8_t *buffer);
static const uint8_t *rlc_get_data_aligned(
- const struct gprs_rlc_ul_header_egprs *rlc,
+ const struct gprs_rlc_data_info *rlc,
unsigned int data_block_idx,
const uint8_t *src, uint8_t *buffer);
+ static int decode_egprs_acknack_bits(
+ const EGPRS_AckNack_Desc_t *desc,
+ struct bitvec *bits, int *bsn_begin, int *bsn_end,
+ struct gprs_rlc_dl_window *window);
+ static int decode_gprs_acknack_bits(
+ const Ack_Nack_Description_t *desc,
+ bitvec *bits, int *bsn_begin, int *bsn_end,
+ gprs_rlc_dl_window *window);
};
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 7f4bf79..6c50abe 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -25,17 +25,142 @@
#include <tbf.h>
#include <gprs_debug.h>
-// GSM 04.08 9.1.18 Immediate assignment
+#include <errno.h>
+#include <string.h>
+
+static int write_ia_rest_downlink(
+ gprs_rlcmac_dl_tbf *tbf,
+ bitvec * dest, unsigned& wp,
+ uint8_t polling, uint32_t fn,
+ uint8_t alpha, uint8_t gamma, int8_t ta_idx)
+{
+ if (!tbf) {
+ LOGP(DRLCMACDL, LOGL_ERROR,
+ "Cannot encode DL IMMEDIATE ASSIGNMENT without TBF\n");
+ return -EINVAL;
+ }
+ // GSM 04.08 10.5.2.16 IA Rest Octets
+ bitvec_write_field_lh(dest, wp, 3, 2); // "HH"
+ bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
+ bitvec_write_field(dest, wp,tbf->tlli(),32); // TLLI
+ bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
+ bitvec_write_field(dest, wp,tbf->tfi(),5); // TFI
+ bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA
+ } else {
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ }
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
+ bitvec_write_field(dest, wp,polling,1); // Polling Bit
+ bitvec_write_field(dest, wp,!polling,1); // TA_VALID ???
+ if (ta_idx < 0) {
+ bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
+ } else {
+ bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
+ bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
+ }
+ if (polling) {
+ bitvec_write_field(dest, wp,0x1,1); // TBF Starting TIME present
+ bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
+ bitvec_write_field(dest, wp,fn % 51,6); // T3
+ bitvec_write_field(dest, wp,fn % 26,5); // T2
+ } else {
+ bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
+ }
+ bitvec_write_field(dest, wp,0x0,1); // P0 not present
+ // bitvec_write_field(dest, wp,0x1,1); // P0 not present
+ // bitvec_write_field(dest, wp,0xb,4);
+ if (tbf->is_egprs_enabled()) {
+ /* see GMS 44.018, 10.5.2.16 */
+ unsigned int ws_enc = (tbf->m_window.ws() - 64) / 32;
+ bitvec_write_field_lh(dest, wp, 1, 1); // "H"
+ bitvec_write_field(dest, wp, ws_enc,5); // EGPRS Window Size
+ bitvec_write_field(dest, wp, 0x0,2); // LINK_QUALITY_MEASUREMENT_MODE
+ bitvec_write_field(dest, wp, 0,1); // BEP_PERIOD2 not present
+ }
+
+ return 0;
+}
+
+static int write_ia_rest_uplink(
+ gprs_rlcmac_ul_tbf *tbf,
+ bitvec * dest, unsigned& wp,
+ uint8_t usf, uint32_t fn,
+ uint8_t alpha, uint8_t gamma, int8_t ta_idx)
+{
+ OSMO_ASSERT(!tbf || !tbf->is_egprs_enabled());
+
+ // GMS 04.08 10.5.2.37b 10.5.2.16
+ bitvec_write_field_lh(dest, wp, 3, 2); // "HH"
+ bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
+ if (tbf == NULL) {
+ bitvec_write_field(dest, wp, 0, 1); // Block Allocation : Single Block Allocation
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA = present
+ } else
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
+ if (ta_idx < 0) {
+ bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
+ } else {
+ bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
+ bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
+ }
+ bitvec_write_field(dest, wp, 1, 1); // TBF_STARTING_TIME_FLAG
+ bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
+ bitvec_write_field(dest, wp,fn % 51,6); // T3
+ bitvec_write_field(dest, wp,fn % 26,5); // T2
+ } else {
+ bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
+ bitvec_write_field(dest, wp, tbf->tfi(), 5); // TFI_ASSIGNMENT Temporary Flow Identity
+ bitvec_write_field(dest, wp, 0, 1); // POLLING
+ bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
+ bitvec_write_field(dest, wp, usf, 3); // USF
+ bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY
+ bitvec_write_field(dest, wp, 0, 1); // "0" power control: Not Present
+ bitvec_write_field(dest, wp, tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND
+ bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA
+ } else
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
+ /* note: there is no choise for TAI and no starting time */
+ bitvec_write_field(dest, wp, 0, 1); // switch TIMING_ADVANCE_INDEX = off
+ bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
+ }
+ return 0;
+}
+
+static int write_ia_rest_egprs_uplink(
+ gprs_rlcmac_ul_tbf *tbf,
+ bitvec * dest, unsigned& wp,
+ uint8_t usf, uint32_t fn,
+ uint8_t alpha, uint8_t gamma, int8_t ta_idx)
+{
+ LOGP(DRLCMACUL, LOGL_ERROR,
+ "EGPRS Packet Uplink Assignment is not yet implemented\n");
+ return -EINVAL;
+}
+
+/*
+ * Immediate assignment, sent on the CCCH/AGCH
+ * see GSM 04.08, 9.1.18 and GSM 44.018, 9.1.18 + 10.5.2.16
+ */
int Encoding::write_immediate_assignment(
- struct gprs_rlcmac_bts *bts,
+ struct gprs_rlcmac_tbf *tbf,
bitvec * dest, uint8_t downlink, uint8_t ra,
uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
- uint8_t tfi, uint8_t usf, uint32_t tlli,
- uint8_t polling, uint32_t fn, uint8_t single_block, uint8_t alpha,
+ uint8_t usf, uint8_t polling, uint32_t fn, uint8_t alpha,
uint8_t gamma, int8_t ta_idx)
{
unsigned wp = 0;
- uint8_t plen;
+ int plen;
+ int rc;
bitvec_write_field(dest, wp,0x0,4); // Skip Indicator
bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator
@@ -78,84 +203,24 @@ int Encoding::write_immediate_assignment(
plen = wp / 8;
if (downlink)
- {
- // GSM 04.08 10.5.2.16 IA Rest Octets
- bitvec_write_field(dest, wp, 3, 2); // "HH"
- bitvec_write_field(dest, wp, 1, 2); // "01" Packet Downlink Assignment
- bitvec_write_field(dest, wp,tlli,32); // TLLI
- bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
- bitvec_write_field(dest, wp,tfi,5); // TFI
- bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
- if (alpha) {
- bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
- bitvec_write_field(dest, wp,alpha,4); // ALPHA
- } else {
- bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
- }
- bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
- bitvec_write_field(dest, wp,polling,1); // Polling Bit
- bitvec_write_field(dest, wp,!polling,1); // TA_VALID ???
- if (ta_idx < 0) {
- bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
- } else {
- bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
- bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
- }
- if (polling) {
- bitvec_write_field(dest, wp,0x1,1); // TBF Starting TIME present
- bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
- bitvec_write_field(dest, wp,fn % 51,6); // T3
- bitvec_write_field(dest, wp,fn % 26,5); // T2
- } else {
- bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present
- }
- bitvec_write_field(dest, wp,0x0,1); // P0 not present
-// bitvec_write_field(dest, wp,0x1,1); // P0 not present
-// bitvec_write_field(dest, wp,0xb,4);
- }
+ rc = write_ia_rest_downlink(as_dl_tbf(tbf), dest, wp,
+ polling, fn,
+ alpha, gamma, ta_idx);
+ else if (as_ul_tbf(tbf) && as_ul_tbf(tbf)->is_egprs_enabled())
+ rc = write_ia_rest_egprs_uplink(as_ul_tbf(tbf), dest, wp,
+ usf, fn,
+ alpha, gamma, ta_idx);
else
- {
- // GMS 04.08 10.5.2.37b 10.5.2.16
- bitvec_write_field(dest, wp, 3, 2); // "HH"
- bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
- if (single_block) {
- bitvec_write_field(dest, wp, 0, 1); // Block Allocation : Single Block Allocation
- if (alpha) {
- bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
- bitvec_write_field(dest, wp,alpha,4); // ALPHA = present
- } else
- bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
- bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
- if (ta_idx < 0) {
- bitvec_write_field(dest, wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
- } else {
- bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
- bitvec_write_field(dest, wp,ta_idx,4); // TIMING_ADVANCE_INDEX
- }
- bitvec_write_field(dest, wp, 1, 1); // TBF_STARTING_TIME_FLAG
- bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
- bitvec_write_field(dest, wp,fn % 51,6); // T3
- bitvec_write_field(dest, wp,fn % 26,5); // T2
- } else {
- bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation
- bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
- bitvec_write_field(dest, wp, 0, 1); // POLLING
- bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic
- bitvec_write_field(dest, wp, usf, 3); // USF
- bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY
- bitvec_write_field(dest, wp, 0, 1); // "0" power control: Not Present
- bitvec_write_field(dest, wp, bts->initial_cs_ul-1, 2); // CHANNEL_CODING_COMMAND
- bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
- if (alpha) {
- bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
- bitvec_write_field(dest, wp,alpha,4); // ALPHA
- } else
- bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
- bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
- /* note: there is no choise for TAI and no starting time */
- bitvec_write_field(dest, wp, 0, 1); // switch TIMING_ADVANCE_INDEX = off
- bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
- }
+ rc = write_ia_rest_uplink(as_ul_tbf(tbf), dest, wp,
+ usf, fn,
+ alpha, gamma, ta_idx);
+
+ if (rc < 0) {
+ LOGP(DRLCMAC, LOGL_ERROR,
+ "Failed to create IMMEDIATE ASSIGMENT (%s) for %s\n",
+ downlink ? "downlink" : "uplink",
+ tbf ? tbf->name() : "single block allocation");
+ return rc;
}
return plen;
@@ -166,7 +231,7 @@ void Encoding::write_packet_uplink_assignment(
struct gprs_rlcmac_bts *bts,
bitvec * dest, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t alpha,
+ struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t rrbp, uint8_t alpha,
uint8_t gamma, int8_t ta_idx, int8_t use_egprs)
{
// TODO We should use our implementation of encode RLC/MAC Control messages.
@@ -193,7 +258,7 @@ void Encoding::write_packet_uplink_assignment(
if (!use_egprs) {
bitvec_write_field(dest, wp,0x0,1); // Message escape
- bitvec_write_field(dest, wp,tbf->current_cs()-1, 2); // CHANNEL_CODING_COMMAND
+ bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND
bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
bitvec_write_field(dest, wp,tbf->ta(),6); // TIMING_ADVANCE_VALUE
@@ -205,13 +270,14 @@ void Encoding::write_packet_uplink_assignment(
}
} else { /* EPGRS */
+ unsigned int ws_enc = (tbf->m_window.ws() - 64) / 32;
bitvec_write_field(dest, wp,0x1,1); // Message escape
bitvec_write_field(dest, wp,0x0,2); // EGPRS message contents
bitvec_write_field(dest, wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI
bitvec_write_field(dest, wp,0x0,1); // No COMPACT reduced MA
- bitvec_write_field(dest, wp,tbf->current_cs()-1, 4); // EGPRS Modulation and Coding IE
+ bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE
bitvec_write_field(dest, wp,0x0,1); // No RESEGMENT
- bitvec_write_field(dest, wp,0x0,5); // EGPRS Window Size = 64
+ bitvec_write_field(dest, wp,ws_enc,5); // EGPRS Window Size
bitvec_write_field(dest, wp,0x0,1); // No Access Technologies Request
bitvec_write_field(dest, wp,0x0,1); // No ARAC RETRANSMISSION REQUEST
bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
@@ -269,16 +335,21 @@ void Encoding::write_packet_uplink_assignment(
/* generate downlink assignment */
-void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
- uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
- uint8_t alpha, uint8_t gamma, int8_t ta_idx, uint8_t ta_ts)
+void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block,
+ bool old_tfi_is_valid, uint8_t old_tfi, uint8_t old_downlink,
+ struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t rrbp,
+ uint8_t alpha, uint8_t gamma, int8_t ta_idx,
+ uint8_t ta_ts, bool use_egprs)
{
// Packet downlink assignment TS 44.060 11.2.7
+ PDA_AdditionsR99_t *pda_r99;
+
uint8_t tn;
+ unsigned int ws_enc;
block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
- block->RRBP = 0x0; // N+13
+ block->RRBP = rrbp; // 0: N+13
block->SP = poll; // RRBP field is valid
block->USF = 0x0; // Uplink state flag
@@ -287,9 +358,14 @@ void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_
block->u.Packet_Downlink_Assignment.Exist_PERSISTENCE_LEVEL = 0x0; // PERSISTENCE_LEVEL: off
- block->u.Packet_Downlink_Assignment.ID.UnionType = 0x0; // TFI = on
- block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.UnionType = old_downlink; // 0=UPLINK TFI, 1=DL TFI
- block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.u.UPLINK_TFI = old_tfi; // TFI
+ if (old_tfi_is_valid) {
+ block->u.Packet_Downlink_Assignment.ID.UnionType = 0x0; // TFI = on
+ block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.UnionType = old_downlink; // 0=UPLINK TFI, 1=DL TFI
+ block->u.Packet_Downlink_Assignment.ID.u.Global_TFI.u.UPLINK_TFI = old_tfi; // TFI
+ } else {
+ block->u.Packet_Downlink_Assignment.ID.UnionType = 0x1; // TLLI
+ block->u.Packet_Downlink_Assignment.ID.u.TLLI = tbf->tlli();
+ }
block->u.Packet_Downlink_Assignment.MAC_MODE = 0x0; // Dynamic Allocation
block->u.Packet_Downlink_Assignment.RLC_MODE = 0x0; // RLC acknowledged mode
@@ -338,7 +414,21 @@ void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_
block->u.Packet_Downlink_Assignment.Exist_TBF_Starting_Time = 0x0; // TBF Starting TIME = off
block->u.Packet_Downlink_Assignment.Exist_Measurement_Mapping = 0x0; // Measurement_Mapping = off
- block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
+ if (!use_egprs) {
+ block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
+ return;
+ }
+
+ ws_enc = (tbf->window()->ws() - 64) / 32;
+
+ block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x1; // AdditionsR99 = on
+ pda_r99 = &block->u.Packet_Downlink_Assignment.AdditionsR99;
+ pda_r99->Exist_EGPRS_Params = 1;
+ pda_r99->EGPRS_WindowSize = ws_enc; /* see TS 44.060, table 12.5.2.1 */
+ pda_r99->LINK_QUALITY_MEASUREMENT_MODE = 0x0; /* no meas, see TS 44.060, table 11.2.7.2 */
+ pda_r99->Exist_BEP_PERIOD2 = 0; /* No extra EGPRS BEP PERIOD */
+ pda_r99->Exist_Packet_Extended_Timing_Advance = 0;
+ pda_r99->Exist_COMPACT_ReducedMA = 0;
}
/* generate paging request */
@@ -399,50 +489,181 @@ void Encoding::encode_rbb(const char *show_rbb, uint8_t *rbb)
}
}
-/* generate uplink ack */
-void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts,
- RlcMacDownlink_t * block, struct gprs_rlcmac_ul_tbf *tbf,
- uint8_t final)
+static void write_packet_ack_nack_desc_gprs(
+ struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
+ gprs_rlc_ul_window *window, bool is_final)
{
- // Packet Uplink Ack/Nack TS 44.060 11.2.28
-
char rbb[65];
- tbf->m_window.update_rbb(rbb);
+ window->update_rbb(rbb);
- LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
- "(final=%d)\n", tbf_name(tbf), final);
+ rbb[64] = 0;
+ LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
+ "I=Invalid\n", rbb);
- block->PAYLOAD_TYPE = 0x1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
- block->RRBP = 0x0; // N+13
- block->SP = final; // RRBP field is valid, if it is final ack
- block->USF = 0x0; // Uplink state flag
+ bitvec_write_field(dest, wp, is_final, 1); // FINAL_ACK_INDICATION
+ bitvec_write_field(dest, wp, window->ssn(), 7); // STARTING_SEQUENCE_NUMBER
- block->u.Packet_Uplink_Ack_Nack.MESSAGE_TYPE = 0x9; // Packet Downlink Assignment
- block->u.Packet_Uplink_Ack_Nack.PAGE_MODE = 0x0; // Normal Paging
- block->u.Packet_Uplink_Ack_Nack.UPLINK_TFI = tbf->tfi(); // Uplink TFI
+ for (int i = 0; i < 64; i++) {
+ /* Set bit at the appropriate position (see 3GPP TS 04.60 9.1.8.1) */
+ bool is_ack = (rbb[i] == 'R');
+ bitvec_write_field(dest, wp, is_ack, 1);
+ }
+}
- block->u.Packet_Uplink_Ack_Nack.UnionType = 0x0; // PU_AckNack_GPRS = on
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.CHANNEL_CODING_COMMAND = tbf->current_cs() - 1; // CS1
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.FINAL_ACK_INDICATION = final; // FINAL ACK INDICATION
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->m_window.ssn(); // STARTING_SEQUENCE_NUMBER
+static void write_packet_uplink_ack_gprs(
+ struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
+ struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
+{
- encode_rbb(rbb, block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
+ bitvec_write_field(dest, wp, tbf->current_cs().to_num() - 1, 2); // CHANNEL_CODING_COMMAND
+ write_packet_ack_nack_desc_gprs(bts, dest, wp, &tbf->m_window, is_final);
+
+ bitvec_write_field(dest, wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
+ bitvec_write_field(dest, wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
+
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Timing Advance
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Power Control Parameters
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Extension Bits
+ bitvec_write_field(dest, wp, 0, 1); // fixed 0
+ bitvec_write_field(dest, wp, 1, 1); // 1: have Additions R99
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Extended Timing Advance
+ bitvec_write_field(dest, wp, 1, 1); // TBF_EST (enabled)
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have REL 5
+};
+
+static void write_packet_ack_nack_desc_egprs(
+ struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
+ gprs_rlc_ul_window *window, bool is_final)
+{
+ int urbb_len = 0;
+ int crbb_len = 0;
+ int len;
+ bool bow = true;
+ bool eow = true;
+ int ssn = window->mod_sns(window->v_q() + 1);
+ int num_blocks = window->mod_sns(window->v_r() - window->v_q());
+ int esn_crbb = window->mod_sns(ssn - 1);
+ int rest_bits = dest->data_len * 8 - wp;
+
+ if (num_blocks > 0)
+ /* V(Q) is NACK and omitted -> SSN = V(Q) + 1 */
+ num_blocks -= 1;
+
+ if (num_blocks > window->ws())
+ num_blocks = window->ws();
+
+ if (num_blocks > rest_bits) {
+ eow = false;
+ urbb_len = rest_bits;
+ /* TODO: use compression, start encoding bits and stop when the
+ * space is exhausted. Use the first combination that encodes
+ * all bits. If there is none, use the combination that encodes
+ * the largest number of bits (e.g. by setting num_blocks to the
+ * max and repeating the construction).
+ */
+ } else if (num_blocks > rest_bits - 9) {
+ /* union bit and length field take 9 bits */
+ eow = false;
+ urbb_len = rest_bits - 9;
+ /* TODO: use compression (see above) */
+ }
- /* rbb is not NULL terminated */
- rbb[64] = 0;
- LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
- "I=Invalid\n", rbb);
+ if (urbb_len + crbb_len == rest_bits)
+ len = -1;
+ else if (crbb_len == 0)
+ len = urbb_len + 15;
+ else
+ len = urbb_len + crbb_len + 23;
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.UnionType = 0x0; // Fixed Allocation Dummy = on
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.u.FixedAllocationDummy = 0x0; // Fixed Allocation Dummy
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off
+ /* EGPRS Ack/Nack Description IE */
+ if (len < 0) {
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have length
+ } else {
+ bitvec_write_field(dest, wp, 1, 1); // 1: have length
+ bitvec_write_field(dest, wp, len, 8); // length
+ }
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_CONTENTION_RESOLUTION_TLLI = 0x1;
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.CONTENTION_RESOLUTION_TLLI = tbf->tlli();
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Packet_Timing_Advance = 0x0;
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Extension_Bits = 0x0;
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Common_Uplink_Ack_Nack_Data.Exist_Power_Control_Parameters = 0x0;
+ bitvec_write_field(dest, wp, is_final, 1); // FINAL_ACK_INDICATION
+ bitvec_write_field(dest, wp, bow, 1); // BEGINNING_OF_WINDOW
+ bitvec_write_field(dest, wp, eow, 1); // END_OF_WINDOW
+ bitvec_write_field(dest, wp, ssn, 11); // STARTING_SEQUENCE_NUMBER
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have CRBB
+
+ /* TODO: Add CRBB support */
+
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ " - EGPRS URBB, len = %d, SSN = %d, ESN_CRBB = %d, "
+ "SNS = %d, WS = %d, V(Q) = %d, V(R) = %d%s%s\n",
+ urbb_len, ssn, esn_crbb,
+ window->sns(), window->ws(), window->v_q(), window->v_r(),
+ bow ? ", BOW" : "", eow ? ", EOW" : "");
+ for (int i = urbb_len; i > 0; i--) {
+ /* Set bit at the appropriate position (see 3GPP TS 04.60 12.3.1) */
+ bool is_ack = window->m_v_n.is_received(esn_crbb + i);
+ bitvec_write_field(dest, wp, is_ack, 1);
+ }
+}
+
+static void write_packet_uplink_ack_egprs(
+ struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
+ struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
+{
+ bitvec_write_field(dest, wp, 0, 2); // fixed 00
+ bitvec_write_field(dest, wp, 2, 4); // CHANNEL_CODING_COMMAND: MCS-3
+ // bitvec_write_field(dest, wp, tbf->current_cs() - 1, 4); // CHANNEL_CODING_COMMAND
+ bitvec_write_field(dest, wp, 0, 1); // 0: no RESEGMENT (nyi)
+ bitvec_write_field(dest, wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it?
+ bitvec_write_field(dest, wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify
+ bitvec_write_field(dest, wp, 0, 1); // 0: no ARAC_RETRANSMISSION_REQUEST, TODO: clarify
+ bitvec_write_field(dest, wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
+ bitvec_write_field(dest, wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
+ bitvec_write_field(dest, wp, 1, 1); // TBF_EST (enabled)
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Timing Advance
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Extended Timing Advance
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Power Control Parameters
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have Extension Bits
+
+ write_packet_ack_nack_desc_egprs(bts, dest, wp, &tbf->m_window, is_final);
+
+ bitvec_write_field(dest, wp, 0, 1); // fixed 0
+ bitvec_write_field(dest, wp, 0, 1); // 0: don't have REL 5
+};
+
+void Encoding::write_packet_uplink_ack(
+ struct gprs_rlcmac_bts *bts, bitvec * dest,
+ struct gprs_rlcmac_ul_tbf *tbf, bool is_final,
+ uint8_t rrbp)
+{
+ unsigned wp = 0;
+
+ LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
+ "(final=%d)\n", tbf_name(tbf), is_final);
+
+ bitvec_write_field(dest, wp, 0x1, 2); // Payload Type
+ bitvec_write_field(dest, wp, rrbp, 2); // Uplink block with TDMA framenumber
+ bitvec_write_field(dest, wp, is_final, 1); // Suppl/Polling Bit
+ bitvec_write_field(dest, wp, 0x0, 3); // Uplink state flag
+ bitvec_write_field(dest, wp, 0x9, 6); // MESSAGE TYPE Uplink Ack/Nack
+ bitvec_write_field(dest, wp, 0x0, 2); // Page Mode
+
+ bitvec_write_field(dest, wp, 0x0, 2); // fixed 00
+ bitvec_write_field(dest, wp, tbf->tfi(), 5); // Uplink TFI
+
+ if (tbf->is_egprs_enabled()) {
+ /* PU_AckNack_EGPRS = on */
+ bitvec_write_field(dest, wp, 1, 1); // 1: EGPRS
+ write_packet_uplink_ack_egprs(bts, dest, wp, tbf, is_final);
+ } else {
+ /* PU_AckNack_GPRS = on */
+ bitvec_write_field(dest, wp, 0, 1); // 0: GPRS
+ write_packet_uplink_ack_gprs(bts, dest, wp, tbf, is_final);
+ }
+
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "Uplink Ack/Nack bit count %d, max %d, message = %s\n",
+ wp, dest->data_len * 8,
+ osmo_hexdump(dest->data, dest->data_len));
}
unsigned Encoding::write_packet_paging_request(bitvec * dest)
@@ -487,3 +708,468 @@ unsigned Encoding::write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t
return wp;
}
+int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
+ uint8_t *data)
+{
+ struct gprs_rlc_dl_header_egprs_1 *egprs1;
+ struct gprs_rlc_dl_header_egprs_2 *egprs2;
+ struct gprs_rlc_dl_header_egprs_3 *egprs3;
+ struct rlc_dl_header *gprs;
+ unsigned int e_fbi_header;
+ GprsCodingScheme cs = rlc->cs;
+ unsigned int offs;
+ unsigned int bsn_delta;
+
+ switch(cs.headerTypeData()) {
+ case GprsCodingScheme::HEADER_GPRS_DATA:
+ gprs = static_cast<struct rlc_dl_header *>
+ ((void *)data);
+
+ gprs->usf = rlc->usf;
+ gprs->s_p = rlc->es_p != 0 ? 1 : 0;
+ gprs->rrbp = rlc->rrbp;
+ gprs->pt = 0;
+ gprs->tfi = rlc->tfi;
+ gprs->pr = rlc->pr;
+
+ gprs->fbi = rlc->block_info[0].cv == 0;
+ gprs->e = rlc->block_info[0].e;
+ gprs->bsn = rlc->block_info[0].bsn;
+ break;
+
+ case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
+ egprs1 = static_cast<struct gprs_rlc_dl_header_egprs_1 *>
+ ((void *)data);
+
+ egprs1->usf = rlc->usf;
+ egprs1->es_p = rlc->es_p;
+ egprs1->rrbp = rlc->rrbp;
+ egprs1->tfi_a = rlc->tfi >> 0; /* 1 bit LSB */
+ egprs1->tfi_b = rlc->tfi >> 1; /* 4 bits */
+ egprs1->pr = rlc->pr;
+ egprs1->cps = rlc->cps;
+
+ egprs1->bsn1_a = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
+ egprs1->bsn1_b = rlc->block_info[0].bsn >> 2; /* 8 bits */
+ egprs1->bsn1_c = rlc->block_info[0].bsn >> 10; /* 1 bit */
+
+ bsn_delta = (rlc->block_info[1].bsn - rlc->block_info[0].bsn) &
+ (RLC_EGPRS_SNS - 1);
+
+ egprs1->bsn2_a = bsn_delta >> 0; /* 7 bits LSB */
+ egprs1->bsn2_b = bsn_delta >> 7; /* 3 bits */
+
+ /* first FBI/E header */
+ e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
+ e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
+ offs = rlc->data_offs_bits[0] / 8;
+ OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 2);
+ e_fbi_header <<= 0;
+ data[offs] = (data[offs] & 0b11111100) | e_fbi_header;
+
+ /* second FBI/E header */
+ e_fbi_header = rlc->block_info[1].e ? 0x01 : 0;
+ e_fbi_header |= rlc->block_info[1].cv == 0 ? 0x02 : 0; /* FBI */
+ offs = rlc->data_offs_bits[1] / 8;
+ OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 4);
+ e_fbi_header <<= 2;
+ data[offs] = (data[offs] & 0b11110011) | e_fbi_header;
+ break;
+
+ case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2:
+ egprs2 = static_cast<struct gprs_rlc_dl_header_egprs_2 *>
+ ((void *)data);
+
+ egprs2->usf = rlc->usf;
+ egprs2->es_p = rlc->es_p;
+ egprs2->rrbp = rlc->rrbp;
+ egprs2->tfi_a = rlc->tfi >> 0; /* 1 bit LSB */
+ egprs2->tfi_b = rlc->tfi >> 1; /* 4 bits */
+ egprs2->pr = rlc->pr;
+ egprs2->cps = rlc->cps;
+
+ egprs2->bsn1_a = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
+ egprs2->bsn1_b = rlc->block_info[0].bsn >> 2; /* 8 bits */
+ egprs2->bsn1_c = rlc->block_info[0].bsn >> 10; /* 1 bit */
+
+ e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
+ e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
+ offs = rlc->data_offs_bits[0] / 8;
+ OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 6);
+ e_fbi_header <<= 4;
+ data[offs] = (data[offs] & 0b11001111) | e_fbi_header;
+ break;
+
+ case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
+ egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *>
+ ((void *)data);
+
+ egprs3->usf = rlc->usf;
+ egprs3->es_p = rlc->es_p;
+ egprs3->rrbp = rlc->rrbp;
+ egprs3->tfi_a = rlc->tfi >> 0; /* 1 bit LSB */
+ egprs3->tfi_b = rlc->tfi >> 1; /* 4 bits */
+ egprs3->pr = rlc->pr;
+ egprs3->cps = rlc->cps;
+
+ egprs3->bsn1_a = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */
+ egprs3->bsn1_b = rlc->block_info[0].bsn >> 2; /* 8 bits */
+ egprs3->bsn1_c = rlc->block_info[0].bsn >> 10; /* 1 bit */
+
+ egprs3->spb = rlc->block_info[0].spb;
+
+ e_fbi_header = rlc->block_info[0].e ? 0x01 : 0;
+ e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */
+ offs = rlc->data_offs_bits[0] / 8;
+ OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
+ e_fbi_header <<= 7;
+ data[offs-1] = (data[offs-1] & 0b01111111) | (e_fbi_header >> 0);
+ data[offs] = (data[offs] & 0b11111110) | (e_fbi_header >> 8);
+ break;
+
+ default:
+ LOGP(DRLCMACDL, LOGL_ERROR,
+ "Encoding of uplink %s data blocks not yet supported.\n",
+ cs.name());
+ return -ENOTSUP;
+ };
+
+ return 0;
+}
+
+/**
+ * \brief Copy LSB bitstream RLC data block from byte aligned buffer.
+ *
+ * Note that the bitstream is encoded in LSB first order, so the two octets
+ * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
+ * (LSB has bit position 1). This is a different order than the one used by
+ * CSN.1.
+ *
+ * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
+ * \param src A pointer to the start of the RLC block (incl. the header)
+ * \param buffer A data area of a least the size of the RLC block
+ * \returns the number of bytes copied
+ */
+unsigned int Encoding::rlc_copy_from_aligned_buffer(
+ const struct gprs_rlc_data_info *rlc,
+ unsigned int data_block_idx,
+ uint8_t *dst, const uint8_t *buffer)
+{
+ unsigned int hdr_bytes;
+ unsigned int extra_bits;
+ unsigned int i;
+
+ uint8_t c, last_c;
+ const uint8_t *src;
+ const struct gprs_rlc_data_block_info *rdbi;
+
+ OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
+ rdbi = &rlc->block_info[data_block_idx];
+
+ hdr_bytes = rlc->data_offs_bits[data_block_idx] / 8;
+ extra_bits = (rlc->data_offs_bits[data_block_idx] % 8);
+
+ if (extra_bits == 0) {
+ /* It is aligned already */
+ memmove(dst + hdr_bytes, buffer, rdbi->data_len);
+ return rdbi->data_len;
+ }
+
+ src = buffer;
+ dst = dst + hdr_bytes;
+ last_c = *dst << (8 - extra_bits);
+
+ for (i = 0; i < rdbi->data_len; i++) {
+ c = src[i];
+ *(dst++) = (last_c >> (8 - extra_bits)) | (c << extra_bits);
+ last_c = c;
+ }
+
+ /* overwrite the lower extra_bits */
+ *dst = (*dst & (0xff << extra_bits)) | (last_c >> (8 - extra_bits));
+
+ return rdbi->data_len;
+}
+
+static Encoding::AppendResult rlc_data_to_dl_append_gprs(
+ struct gprs_rlc_data_block_info *rdbi,
+ gprs_llc *llc, int *offset, int *num_chunks,
+ uint8_t *data_block,
+ bool is_final)
+{
+ int chunk;
+ int space;
+ struct rlc_li_field *li;
+ uint8_t *delimiter, *data, *e_pointer;
+
+ data = data_block + *offset;
+ delimiter = data_block + *num_chunks;
+ e_pointer = (*num_chunks ? delimiter - 1 : NULL);
+
+ chunk = llc->chunk_size();
+ space = rdbi->data_len - *offset;
+
+ /* if chunk will exceed block limit */
+ if (chunk > space) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "larger than space (%d) left in block: copy "
+ "only remaining space, and we are done\n",
+ chunk, space);
+ /* block is filled, so there is no extension */
+ if (e_pointer)
+ *e_pointer |= 0x01;
+ /* fill only space */
+ llc->consume(data, space);
+ /* return data block as message */
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ return Encoding::AR_NEED_MORE_BLOCKS;
+ }
+ /* if FINAL chunk would fit precisely in space left */
+ if (chunk == space && is_final)
+ {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "would exactly fit into space (%d): because "
+ "this is a final block, we don't add length "
+ "header, and we are done\n", chunk, space);
+ /* block is filled, so there is no extension */
+ if (e_pointer)
+ *e_pointer |= 0x01;
+ /* fill space */
+ llc->consume(data, space);
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ rdbi->cv = 0;
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+ }
+ /* if chunk would fit exactly in space left */
+ if (chunk == space) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "would exactly fit into space (%d): add length "
+ "header with LI=0, to make frame extend to "
+ "next block, and we are done\n", chunk, space);
+ /* make space for delimiter */
+ if (delimiter != data)
+ memmove(delimiter + 1, delimiter,
+ data - delimiter);
+ data++;
+ (*offset)++;
+ space--;
+ /* add LI with 0 length */
+ li = (struct rlc_li_field *)delimiter;
+ li->e = 1; /* not more extension */
+ li->m = 0; /* shall be set to 0, in case of li = 0 */
+ li->li = 0; /* chunk fills the complete space */
+ rdbi->e = 0; /* 0: extensions present */
+ // no need to set e_pointer nor increase delimiter
+ /* fill only space, which is 1 octet less than chunk */
+ llc->consume(data, space);
+ /* return data block as message */
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ return Encoding::AR_NEED_MORE_BLOCKS;
+ }
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
+ "than remaining space (%d): add length header to "
+ "to delimit LLC frame\n", chunk, space);
+ /* the LLC frame chunk ends in this block */
+ /* make space for delimiter */
+ if (delimiter != data)
+ memmove(delimiter + 1, delimiter, data - delimiter);
+ data++;
+ (*offset)++;
+ space--;
+ /* add LI to delimit frame */
+ li = (struct rlc_li_field *)delimiter;
+ li->e = 0; /* Extension bit, maybe set later */
+ li->m = 0; /* will be set later, if there is more LLC data */
+ li->li = chunk; /* length of chunk */
+ rdbi->e = 0; /* 0: extensions present */
+ (*num_chunks)++;
+ /* copy (rest of) LLC frame to space and reset later */
+ llc->consume(data, chunk);
+ data += chunk;
+ space -= chunk;
+ (*offset) += chunk;
+ /* if we have more data and we have space left */
+ if (space > 0 && !is_final) {
+ li->m = 1; /* we indicate more frames to follow */
+ return Encoding::AR_COMPLETED_SPACE_LEFT;
+ }
+ /* if we don't have more LLC frames */
+ if (is_final) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
+ "done.\n");
+ li->e = 1; /* we cannot extend */
+ rdbi->cv = 0;
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+ }
+ /* we have no space left */
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
+ "done.\n");
+ li->e = 1; /* we cannot extend */
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+}
+
+static Encoding::AppendResult rlc_data_to_dl_append_egprs(
+ struct gprs_rlc_data_block_info *rdbi,
+ gprs_llc *llc, int *offset, int *num_chunks,
+ uint8_t *data_block,
+ bool is_final)
+{
+ int chunk;
+ int space;
+ struct rlc_li_field_egprs *li;
+ struct rlc_li_field_egprs *prev_li;
+ uint8_t *delimiter, *data;
+
+ data = data_block + *offset;
+ delimiter = data_block + *num_chunks;
+ prev_li = (struct rlc_li_field_egprs *)
+ (*num_chunks ? delimiter - 1 : NULL);
+
+ chunk = llc->chunk_size();
+ space = rdbi->data_len - *offset;
+
+ /* if chunk will exceed block limit */
+ if (chunk > space) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "larger than space (%d) left in block: copy "
+ "only remaining space, and we are done\n",
+ chunk, space);
+ /* fill only space */
+ llc->consume(data, space);
+ /* return data block as message */
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ return Encoding::AR_NEED_MORE_BLOCKS;
+ }
+ /* if FINAL chunk would fit precisely in space left */
+ if (chunk == space && is_final)
+ {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "would exactly fit into space (%d): because "
+ "this is a final block, we don't add length "
+ "header, and we are done\n", chunk, space);
+ /* fill space */
+ llc->consume(data, space);
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ rdbi->cv = 0;
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+ }
+ /* if chunk would fit exactly in space left */
+ if (chunk == space) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
+ "would exactly fit into space (%d): just copy "
+ "it, and we are done. The next block will have "
+ "to start with an empty chunk\n",
+ chunk, space);
+ /* fill space */
+ llc->consume(data, space);
+ *offset = rdbi->data_len;
+ (*num_chunks)++;
+ return Encoding::AR_NEED_MORE_BLOCKS;
+ }
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
+ "than remaining space (%d): add length header to "
+ "to delimit LLC frame\n", chunk, space);
+ /* the LLC frame chunk ends in this block */
+ /* make space for delimiter */
+
+ if (delimiter != data)
+ memmove(delimiter + 1, delimiter, data - delimiter);
+
+ data += 1;
+ (*offset) += 1;
+ space -= 1;
+ /* add LI to delimit frame */
+ li = (struct rlc_li_field_egprs *)delimiter;
+ li->e = 1; /* Extension bit, maybe set later */
+ li->li = chunk; /* length of chunk */
+ /* tell previous extension header about the new one */
+ if (prev_li)
+ prev_li->e = 0;
+ rdbi->e = 0; /* 0: extensions present */
+ delimiter++;
+ prev_li = li;
+ (*num_chunks)++;
+ /* copy (rest of) LLC frame to space and reset later */
+ llc->consume(data, chunk);
+ data += chunk;
+ space -= chunk;
+ (*offset) += chunk;
+ /* if we have more data and we have space left */
+ if (space > 0) {
+ if (!is_final)
+ return Encoding::AR_COMPLETED_SPACE_LEFT;
+
+ /* we don't have more LLC frames */
+ /* We will have to add another chunk with filling octets */
+ LOGP(DRLCMACDL, LOGL_DEBUG,
+ "-- There is remaining space (%d): add filling byte chunk\n",
+ space);
+
+ if (delimiter != data)
+ memmove(delimiter + 1, delimiter, data - delimiter);
+
+ data += 1;
+ (*offset) += 1;
+ space -= 1;
+
+ /* set filling bytes extension */
+ li = (struct rlc_li_field_egprs *)delimiter;
+ li->e = 1;
+ li->li = 127;
+
+ /* tell previous extension header about the new one */
+ if (prev_li)
+ prev_li->e = 0;
+
+ delimiter++;
+ (*num_chunks)++;
+
+ rdbi->cv = 0;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
+ "are done.\n");
+
+ *offset = rdbi->data_len;
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+ }
+
+ if (is_final) {
+ /* we don't have more LLC frames */
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
+ "are done.\n");
+ rdbi->cv = 0;
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+ }
+
+ /* we have no space left */
+ LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
+ "done.\n");
+ return Encoding::AR_COMPLETED_BLOCK_FILLED;
+}
+
+Encoding::AppendResult Encoding::rlc_data_to_dl_append(
+ struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+ gprs_llc *llc, int *offset, int *num_chunks,
+ uint8_t *data_block,
+ bool is_final)
+{
+ if (cs.isGprs())
+ return rlc_data_to_dl_append_gprs(rdbi,
+ llc, offset, num_chunks, data_block, is_final);
+
+ if (cs.isEgprs())
+ return rlc_data_to_dl_append_egprs(rdbi,
+ llc, offset, num_chunks, data_block, is_final);
+
+ LOGP(DRLCMACDL, LOGL_ERROR, "%s data block encoding not implemented\n",
+ cs.name());
+
+ return AR_NEED_MORE_BLOCKS;
+}
diff --git a/src/encoding.h b/src/encoding.h
index ac66838..94e9a02 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -22,10 +22,13 @@
#include <stdint.h>
#include <gsm_rlcmac.h>
+#include <gprs_coding_scheme.h>
struct gprs_rlcmac_bts;
struct gprs_rlcmac_tbf;
struct bitvec;
+struct gprs_llc;
+struct gprs_rlc_data_block_info;
/**
* I help with encoding data into CSN1 messages.
@@ -36,28 +39,33 @@ struct bitvec;
class Encoding {
public:
static int write_immediate_assignment(
- struct gprs_rlcmac_bts *bts,
- bitvec * dest, uint8_t downlink, uint8_t ra,
- uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc,
- uint8_t tfi, uint8_t usf, uint32_t tlli, uint8_t polling,
- uint32_t fn, uint8_t single_block, uint8_t alpha, uint8_t gamma,
+ struct gprs_rlcmac_tbf *tbf,
+ bitvec * dest, uint8_t downlink, uint8_t ra,
+ uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts,
+ uint8_t tsc, uint8_t usf, uint8_t polling,
+ uint32_t fn, uint8_t alpha, uint8_t gamma,
int8_t ta_idx);
static void write_packet_uplink_assignment(
struct gprs_rlcmac_bts *bts,
bitvec * dest, uint8_t old_tfi,
- uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t alpha,
- uint8_t gamma, int8_t ta_idx, int8_t use_egprs);
+ uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
+ struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t rrbp,
+ uint8_t alpha, uint8_t gamma, int8_t ta_idx,
+ int8_t use_egprs);
- static void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
- uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
- uint8_t alpha, uint8_t gamma, int8_t ta_idx, uint8_t ta_ts);
+ static void write_packet_downlink_assignment(RlcMacDownlink_t * block,
+ bool old_tfi_is_valid, uint8_t old_tfi, uint8_t old_downlink,
+ struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t rrbp,
+ uint8_t alpha, uint8_t gamma,
+ int8_t ta_idx, uint8_t ta_ts, bool use_egprs);
static void encode_rbb(const char *show_rbb, uint8_t *rbb);
- static void write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, RlcMacDownlink_t * block, struct gprs_rlcmac_ul_tbf *tbf,
- uint8_t final);
+ static void write_packet_uplink_ack(
+ struct gprs_rlcmac_bts *bts, bitvec * dest,
+ struct gprs_rlcmac_ul_tbf *tbf, bool is_final,
+ uint8_t rrbp);
static int write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi_len);
@@ -65,4 +73,24 @@ public:
uint8_t *identity, uint8_t chan_needed);
static unsigned write_packet_paging_request(bitvec * dest);
+
+ static int rlc_write_dl_data_header(
+ const struct gprs_rlc_data_info *rlc,
+ uint8_t *data);
+ static unsigned int rlc_copy_from_aligned_buffer(
+ const struct gprs_rlc_data_info *rlc,
+ unsigned int data_block_idx,
+ uint8_t *dst, const uint8_t *buffer);
+
+ enum AppendResult {
+ AR_NEED_MORE_BLOCKS,
+ AR_COMPLETED_SPACE_LEFT,
+ AR_COMPLETED_BLOCK_FILLED,
+ };
+
+ static AppendResult rlc_data_to_dl_append(
+ struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+ gprs_llc *llc, int *offset, int *num_chunks,
+ uint8_t *data,
+ bool is_final);
};
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 838c667..da1d26c 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -23,6 +23,7 @@
#include <pcu_l1_if.h>
#include <bts.h>
#include <tbf.h>
+#include <decoding.h>
#define BSSGP_TIMER_T1 30 /* Guards the (un)blocking procedures */
#define BSSGP_TIMER_T2 30 /* Guards the reset procedure */
@@ -73,44 +74,30 @@ static int parse_imsi(struct tlv_parsed *tp, char *imsi)
return 0;
}
-static int parse_ra_cap_ms_class(struct tlv_parsed *tp)
+static int parse_ra_cap(struct tlv_parsed *tp, MS_Radio_Access_capability_t *rac)
{
bitvec *block;
- unsigned rp = 0;
- uint8_t ms_class = 0;
uint8_t cap_len;
uint8_t *cap;
+ memset(rac, 0, sizeof(*rac));
+
if (!TLVP_PRESENT(tp, BSSGP_IE_MS_RADIO_ACCESS_CAP))
- return ms_class;
+ return -EINVAL;
cap_len = TLVP_LEN(tp, BSSGP_IE_MS_RADIO_ACCESS_CAP);
cap = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_MS_RADIO_ACCESS_CAP);
+ LOGP(DBSSGP, LOGL_DEBUG, "Got BSSGP RA Capability of size %d\n", cap_len);
+
block = bitvec_alloc(cap_len);
bitvec_unpack(block, cap);
- bitvec_read_field(block, rp, 4); // Access Technology Type
- bitvec_read_field(block, rp, 7); // Length of Access Capabilities
- bitvec_read_field(block, rp, 3); // RF Power Capability
- if (bitvec_read_field(block, rp, 1)) // A5 Bits Present
- bitvec_read_field(block, rp, 7); // A5 Bits
- bitvec_read_field(block, rp, 1); // ES IND
- bitvec_read_field(block, rp, 1); // PS
- bitvec_read_field(block, rp, 1); // VGCS
- bitvec_read_field(block, rp, 1); // VBS
- if (bitvec_read_field(block, rp, 1)) { // Multislot Cap Present
- if (bitvec_read_field(block, rp, 1)) // HSCSD Present
- bitvec_read_field(block, rp, 5); // Class
- if (bitvec_read_field(block, rp, 1)) { // GPRS Present
- ms_class = bitvec_read_field(block, rp, 5); // Class
- bitvec_read_field(block, rp, 1); // Ext.
- }
- if (bitvec_read_field(block, rp, 1)) // SMS Present
- bitvec_read_field(block, rp, 4); // SMS Value
- }
+
+ /* TS 24.008, 10.5.5.12a */
+ decode_gsm_ra_cap(block, rac);
bitvec_free(block);
- return ms_class;
+ return 0;
}
static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
@@ -122,6 +109,11 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
uint8_t *data;
uint16_t len;
char imsi[16] = "000";
+ uint8_t ms_class = 0;
+ uint8_t egprs_ms_class = 0;
+#if 0
+ MS_Radio_Access_capability_t rac;
+#endif
budh = (struct bssgp_ud_hdr *)msgb_bssgph(msg);
tlli = ntohl(budh->tlli);
@@ -146,10 +138,17 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
* will listen to all paging blocks. */
parse_imsi(tp, imsi);
+#if 0 /* Do not rely on this IE. TODO: make this configurable */
/* parse ms radio access capability */
- uint8_t ms_class = parse_ra_cap_ms_class(tp);
- /* TODO: Get the EGPRS class from the CSN.1 RA capability */
- uint8_t egprs_ms_class = 0;
+ if (parse_ra_cap(tp, &rac) >= 0) {
+ /* Get the EGPRS class from the RA capability */
+ ms_class = Decoding::get_ms_class_by_capability(&rac);
+ egprs_ms_class =
+ Decoding::get_egprs_ms_class_by_capability(&rac);
+ LOGP(DBSSGP, LOGL_DEBUG, "Got downlink MS class %d/%d\n",
+ ms_class, egprs_ms_class);
+ }
+#endif
/* get lifetime */
uint16_t delay_csec = 0xffff;
@@ -534,19 +533,12 @@ static unsigned count_pdch(const struct gprs_rlcmac_bts *bts)
return num_pdch;
}
-static uint32_t gprs_bssgp_max_leak_rate(unsigned cs, int num_pdch)
+static uint32_t gprs_bssgp_max_leak_rate(GprsCodingScheme cs, int num_pdch)
{
- static const uint32_t max_lr_per_ts[4] = {
- 20 * (1000 / 20), /* CS-1: 20 byte payload per 20ms */
- 30 * (1000 / 20), /* CS-2: 30 byte payload per 20ms */
- 36 * (1000 / 20), /* CS-3: 36 byte payload per 20ms */
- 50 * (1000 / 20), /* CS-4: 50 byte payload per 20ms */
- };
-
- if (cs > ARRAY_SIZE(max_lr_per_ts))
- cs = 1;
+ int bytes_per_rlc_block = cs.maxDataBlockBytes() * cs.numDataBlocks();
- return max_lr_per_ts[cs-1] * num_pdch;
+ /* n byte payload per 20ms */
+ return bytes_per_rlc_block * (1000 / 20) * num_pdch;
}
static uint32_t compute_bucket_size(struct gprs_rlcmac_bts *bts,
@@ -619,6 +611,45 @@ static int get_and_reset_measured_leak_rate(int *usage_by_1000, unsigned num_pdc
return rate;
}
+static GprsCodingScheme max_coding_scheme_dl(struct gprs_rlcmac_bts *bts)
+{
+ int num;
+
+ if (bts->egprs_enabled) {
+ if (!bts->cs_adj_enabled) {
+ if (bts->initial_mcs_dl)
+ num = bts->initial_mcs_dl;
+ else
+ num = 1;
+ } else if (bts->max_mcs_dl) {
+ num = bts->max_mcs_dl;
+ } else {
+ num = 9;
+ }
+
+ return GprsCodingScheme::getEgprsByNum(num);
+ }
+
+ if (!bts->cs_adj_enabled) {
+ if (bts->initial_cs_dl)
+ num = bts->initial_cs_dl;
+ else if (bts->cs4)
+ num = 4;
+ else if (bts->cs3)
+ num = 3;
+ else if (bts->cs2)
+ num = 2;
+ else
+ num = 1;
+ } else if (bts->max_cs_dl) {
+ num = bts->max_cs_dl;
+ } else {
+ num = 4;
+ }
+
+ return GprsCodingScheme::getGprsByNum(num);
+}
+
int gprs_bssgp_tx_fc_bvc(void)
{
struct gprs_rlcmac_bts *bts;
@@ -628,7 +659,7 @@ int gprs_bssgp_tx_fc_bvc(void)
uint32_t ms_leak_rate; /* oct/s */
uint32_t avg_delay_ms;
int num_pdch = -1;
- int max_cs_dl;
+ GprsCodingScheme max_cs_dl;
if (!the_pcu.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
@@ -636,21 +667,7 @@ int gprs_bssgp_tx_fc_bvc(void)
}
bts = bts_main_data();
- if (bts->cs_adj_enabled) {
- max_cs_dl = bts->max_cs_dl;
- if (!max_cs_dl) {
- if (bts->cs4)
- max_cs_dl = 4;
- else if (bts->cs3)
- max_cs_dl = 3;
- else if (bts->cs2)
- max_cs_dl = 2;
- else
- max_cs_dl = 1;
- }
- } else {
- max_cs_dl = bts->initial_cs_dl;
- }
+ max_cs_dl = max_coding_scheme_dl(bts);
bucket_size = bts->fc_bvc_bucket_size;
leak_rate = bts->fc_bvc_leak_rate;
@@ -684,8 +701,8 @@ int gprs_bssgp_tx_fc_bvc(void)
leak_rate = gprs_bssgp_max_leak_rate(max_cs_dl, num_pdch);
LOGP(DBSSGP, LOGL_DEBUG,
- "Computed BVC leak rate = %d, num_pdch = %d, cs = %d\n",
- leak_rate, num_pdch, max_cs_dl);
+ "Computed BVC leak rate = %d, num_pdch = %d, cs = %s\n",
+ leak_rate, num_pdch, max_cs_dl.name());
};
if (ms_leak_rate == 0) {
@@ -707,8 +724,9 @@ int gprs_bssgp_tx_fc_bvc(void)
* should be derived from the max number of PDCH TS per TRX.
*/
LOGP(DBSSGP, LOGL_DEBUG,
- "Computed MS default leak rate = %d, ms_num_pdch = %d, cs = %d\n",
- ms_leak_rate, ms_num_pdch, max_cs_dl);
+ "Computed MS default leak rate = %d, ms_num_pdch = %d, "
+ "cs = %s\n",
+ ms_leak_rate, ms_num_pdch, max_cs_dl.name());
};
/* TODO: Force leak_rate to 0 on buffer bloat */
diff --git a/src/gprs_coding_scheme.cpp b/src/gprs_coding_scheme.cpp
index 04eb3b6..8601d4f 100644
--- a/src/gprs_coding_scheme.cpp
+++ b/src/gprs_coding_scheme.cpp
@@ -25,30 +25,61 @@ static struct {
struct {
unsigned int bytes;
unsigned int ext_bits;
+ unsigned int data_header_bits;
} uplink, downlink;
unsigned int data_bytes;
- unsigned int num_blocks;
+ unsigned int optional_padding_bits;
const char *name;
GprsCodingScheme::HeaderType data_hdr;
+ GprsCodingScheme::Family family;
} mcs_info[GprsCodingScheme::NUM_SCHEMES] = {
- {{0, 0}, {0, 0}, 0, 0, "UNKNOWN", GprsCodingScheme::HEADER_INVALID},
- {{23, 0}, {23, 0}, 20, 1, "CS-1", GprsCodingScheme::HEADER_GPRS_DATA},
- {{33, 7}, {33, 7}, 30, 1, "CS-2", GprsCodingScheme::HEADER_GPRS_DATA},
- {{39, 3}, {39, 3}, 36, 1, "CS-3", GprsCodingScheme::HEADER_GPRS_DATA},
- {{53, 7}, {53, 7}, 50, 1, "CS-4", GprsCodingScheme::HEADER_GPRS_DATA},
-
- {{26, 1}, {26, 1}, 22, 1, "MCS-1", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
- {{32, 1}, {32, 1}, 28, 1, "MCS-2", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
- {{41, 1}, {41, 1}, 37, 1, "MCS-3", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
- {{48, 1}, {48, 1}, 44, 1, "MCS-4", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3},
-
- {{60, 7}, {59, 6}, 56, 1, "MCS-5", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
- {{78, 7}, {77, 6}, 74, 1, "MCS-6", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2},
- {{118, 2}, {117, 4}, 56, 2, "MCS-7", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
- {{142, 2}, {141, 4}, 68, 2, "MCS-8", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
- {{154, 2}, {153, 4}, 74, 2, "MCS-9", GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1},
+ {{0, 0}, {0, 0}, 0, 0, "UNKNOWN",
+ GprsCodingScheme::HEADER_INVALID, GprsCodingScheme::FAMILY_INVALID},
+ {{23, 0}, {23, 0}, 20, 0, "CS-1",
+ GprsCodingScheme::HEADER_GPRS_DATA, GprsCodingScheme::FAMILY_INVALID},
+ {{33, 7}, {33, 7}, 30, 0, "CS-2",
+ GprsCodingScheme::HEADER_GPRS_DATA, GprsCodingScheme::FAMILY_INVALID},
+ {{39, 3}, {39, 3}, 36, 0, "CS-3",
+ GprsCodingScheme::HEADER_GPRS_DATA, GprsCodingScheme::FAMILY_INVALID},
+ {{53, 7}, {53, 7}, 50, 0, "CS-4",
+ GprsCodingScheme::HEADER_GPRS_DATA, GprsCodingScheme::FAMILY_INVALID},
+
+ {{26, 1}, {26, 1}, 22, 0, "MCS-1",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, GprsCodingScheme::FAMILY_C},
+ {{32, 1}, {32, 1}, 28, 0, "MCS-2",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, GprsCodingScheme::FAMILY_B},
+ {{41, 1}, {41, 1}, 37, 48, "MCS-3",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, GprsCodingScheme::FAMILY_A},
+ {{48, 1}, {48, 1}, 44, 0, "MCS-4",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, GprsCodingScheme::FAMILY_C},
+
+ {{60, 7}, {59, 6}, 56, 0, "MCS-5",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2, GprsCodingScheme::FAMILY_B},
+ {{78, 7}, {77, 6}, 74, 48, "MCS-6",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2, GprsCodingScheme::FAMILY_A},
+ {{118, 2}, {117, 4}, 56, 0, "MCS-7",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, GprsCodingScheme::FAMILY_B},
+ {{142, 2}, {141, 4}, 68, 0, "MCS-8",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, GprsCodingScheme::FAMILY_A},
+ {{154, 2}, {153, 4}, 74, 0, "MCS-9",
+ GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, GprsCodingScheme::FAMILY_A},
};
+static struct {
+ struct {
+ int data_header_bits;
+ } uplink, downlink;
+ unsigned int data_block_header_bits;
+ unsigned int num_blocks;
+ const char *name;
+} hdr_type_info[GprsCodingScheme::NUM_HEADER_TYPES] = {
+ {{0}, {0}, 0, 0, "INVALID"},
+ {{1*8 + 0}, {1*8 + 0}, 0, 0, "CONTROL"},
+ {{3*8 + 0}, {3*8 + 0}, 0, 1, "GPRS_DATA"},
+ {{5*8 + 6}, {5*8 + 0}, 2, 2, "EGPRS_DATA_TYPE1"},
+ {{4*8 + 5}, {3*8 + 4}, 2, 1, "EGPRS_DATA_TYPE2"},
+ {{3*8 + 7}, {3*8 + 7}, 2, 1, "EGPRS_DATA_TYPE3"},
+};
GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
{
@@ -73,7 +104,15 @@ GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
unsigned int GprsCodingScheme::sizeUL() const
{
- return maxBytesUL() + (spareBitsUL() ? 1 : 0);
+ return mcs_info[m_scheme].uplink.bytes + (spareBitsUL() ? 1 : 0);
+}
+
+unsigned int GprsCodingScheme::usedSizeUL() const
+{
+ if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
+ return mcs_info[m_scheme].uplink.bytes;
+ else
+ return sizeUL();
}
unsigned int GprsCodingScheme::maxBytesUL() const
@@ -88,7 +127,15 @@ unsigned int GprsCodingScheme::spareBitsUL() const
unsigned int GprsCodingScheme::sizeDL() const
{
- return maxBytesDL() + (spareBitsDL() ? 1 : 0);
+ return mcs_info[m_scheme].downlink.bytes + (spareBitsDL() ? 1 : 0);
+}
+
+unsigned int GprsCodingScheme::usedSizeDL() const
+{
+ if (mcs_info[m_scheme].data_hdr == HEADER_GPRS_DATA)
+ return mcs_info[m_scheme].downlink.bytes;
+ else
+ return sizeDL();
}
unsigned int GprsCodingScheme::maxBytesDL() const
@@ -106,9 +153,29 @@ unsigned int GprsCodingScheme::maxDataBlockBytes() const
return mcs_info[m_scheme].data_bytes;
}
+unsigned int GprsCodingScheme::optionalPaddingBits() const
+{
+ return mcs_info[m_scheme].optional_padding_bits;
+}
+
unsigned int GprsCodingScheme::numDataBlocks() const
{
- return mcs_info[m_scheme].num_blocks;
+ return hdr_type_info[headerTypeData()].num_blocks;
+}
+
+unsigned int GprsCodingScheme::numDataHeaderBitsUL() const
+{
+ return hdr_type_info[headerTypeData()].uplink.data_header_bits;
+}
+
+unsigned int GprsCodingScheme::numDataHeaderBitsDL() const
+{
+ return hdr_type_info[headerTypeData()].downlink.data_header_bits;
+}
+
+unsigned int GprsCodingScheme::numDataBlockHeaderBits() const
+{
+ return hdr_type_info[headerTypeData()].data_block_header_bits;
}
const char *GprsCodingScheme::name() const
@@ -120,3 +187,100 @@ GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeData() const
{
return mcs_info[m_scheme].data_hdr;
}
+
+GprsCodingScheme::Family GprsCodingScheme::family() const
+{
+ return mcs_info[m_scheme].family;
+}
+
+void GprsCodingScheme::inc(Mode mode)
+{
+ if (!isCompatible(mode))
+ /* This should not happen. TODO: Use assert? */
+ return;
+
+ Scheme new_cs(Scheme(m_scheme + 1));
+ if (!GprsCodingScheme(new_cs).isCompatible(mode))
+ /* Clipping, do not change the value */
+ return;
+
+ m_scheme = new_cs;
+}
+
+void GprsCodingScheme::dec(Mode mode)
+{
+ if (!isCompatible(mode))
+ /* This should not happen. TODO: Use assert? */
+ return;
+
+ Scheme new_cs(Scheme(m_scheme - 1));
+ if (!GprsCodingScheme(new_cs).isCompatible(mode))
+ /* Clipping, do not change the value */
+ return;
+
+ m_scheme = new_cs;
+}
+
+void GprsCodingScheme::inc()
+{
+ if (isGprs() && m_scheme == CS4)
+ return;
+
+ if (isEgprs() && m_scheme == MCS9)
+ return;
+
+ if (!isValid())
+ return;
+
+ m_scheme = Scheme(m_scheme + 1);
+}
+
+void GprsCodingScheme::dec()
+{
+ if (isGprs() && m_scheme == CS1)
+ return;
+
+ if (isEgprs() && m_scheme == MCS1)
+ return;
+
+ if (!isValid())
+ return;
+
+ m_scheme = Scheme(m_scheme - 1);
+}
+
+const char *GprsCodingScheme::modeName(Mode mode)
+{
+ switch (mode) {
+ case GPRS: return "GPRS";
+ case EGPRS_GMSK: return "EGPRS_GMSK-only";
+ case EGPRS: return "EGPRS";
+ default: return "???";
+ }
+}
+
+bool GprsCodingScheme::isFamilyCompatible(GprsCodingScheme o) const
+{
+ if (*this == o)
+ return true;
+
+ if (family() == FAMILY_INVALID)
+ return false;
+
+ return family() == o.family();
+}
+
+bool GprsCodingScheme::isCombinable(GprsCodingScheme o) const
+{
+ return numDataBlocks() == o.numDataBlocks();
+}
+
+void GprsCodingScheme::decToSingleBlock(bool *needStuffing)
+{
+ switch (m_scheme) {
+ case MCS7: *needStuffing = false; m_scheme = MCS5; break;
+ case MCS8: *needStuffing = true; m_scheme = MCS6; break;
+ case MCS9: *needStuffing = false; m_scheme = MCS6; break;
+ default: *needStuffing = false; break;
+ }
+}
diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h
index a91d1bd..aec3762 100644
--- a/src/gprs_coding_scheme.h
+++ b/src/gprs_coding_scheme.h
@@ -47,41 +47,81 @@ public:
HEADER_EGPRS_DATA_TYPE_1,
HEADER_EGPRS_DATA_TYPE_2,
HEADER_EGPRS_DATA_TYPE_3,
+ NUM_HEADER_TYPES
+ };
+
+ enum Family {
+ FAMILY_INVALID,
+ FAMILY_A,
+ FAMILY_B,
+ FAMILY_C,
};
GprsCodingScheme(Scheme s = UNKNOWN);
operator bool() const {return m_scheme != UNKNOWN;}
- operator int() const {return (int)m_scheme;}
- void operator =(Scheme s);
- void operator =(GprsCodingScheme o);
+ operator Scheme() const {return m_scheme;}
+ unsigned int to_num() const;
+
+ GprsCodingScheme& operator =(Scheme s);
+ GprsCodingScheme& operator =(GprsCodingScheme o);
+
bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
bool isGprs() const {return CS1 <= m_scheme && m_scheme <= CS4;}
bool isEgprs() const {return m_scheme >= MCS1;}
bool isEgprsGmsk() const {return isEgprs() && m_scheme <= MCS4;}
bool isCompatible(Mode mode) const;
+ bool isCompatible(GprsCodingScheme o) const;
+ bool isFamilyCompatible(GprsCodingScheme o) const;
+ bool isCombinable(GprsCodingScheme o) const;
void inc(Mode mode);
void dec(Mode mode);
+ void inc();
+ void dec();
+ void decToSingleBlock(bool *needStuffing);
unsigned int sizeUL() const;
unsigned int sizeDL() const;
+ unsigned int usedSizeUL() const;
+ unsigned int usedSizeDL() const;
unsigned int maxBytesUL() const;
unsigned int maxBytesDL() const;
unsigned int spareBitsUL() const;
unsigned int spareBitsDL() const;
unsigned int maxDataBlockBytes() const;
unsigned int numDataBlocks() const;
+ unsigned int numDataHeaderBitsUL() const;
+ unsigned int numDataHeaderBitsDL() const;
+ unsigned int numDataBlockHeaderBits() const;
+ unsigned int optionalPaddingBits() const;
const char *name() const;
HeaderType headerTypeData() const;
HeaderType headerTypeControl() const;
+ Family family() const;
static GprsCodingScheme getBySizeUL(unsigned size);
+ static GprsCodingScheme getGprsByNum(unsigned num);
+ static GprsCodingScheme getEgprsByNum(unsigned num);
+ static const char *modeName(Mode mode);
private:
+ GprsCodingScheme(int s); /* fail on use */
+ GprsCodingScheme& operator =(int s); /* fail on use */
enum Scheme m_scheme;
};
+inline unsigned int GprsCodingScheme::to_num() const
+{
+ if (isGprs())
+ return (m_scheme - CS1) + 1;
+
+ if (isEgprs())
+ return (m_scheme - MCS1) + 1;
+
+ return 0;
+}
+
inline bool GprsCodingScheme::isCompatible(Mode mode) const
{
switch (mode) {
@@ -93,32 +133,9 @@ inline bool GprsCodingScheme::isCompatible(Mode mode) const
return false;
}
-inline void GprsCodingScheme::inc(Mode mode)
-{
- if (!isCompatible(mode))
- /* This should not happen. TODO: Use assert? */
- return;
-
- Scheme new_cs(Scheme(m_scheme + 1));
- if (!GprsCodingScheme(new_cs).isCompatible(mode))
- /* Clipping, do not change the value */
- return;
-
- m_scheme = new_cs;
-}
-
-inline void GprsCodingScheme::dec(Mode mode)
+inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
{
- if (!isCompatible(mode))
- /* This should not happen. TODO: Use assert? */
- return;
-
- Scheme new_cs(Scheme(m_scheme - 1));
- if (!GprsCodingScheme(new_cs).isCompatible(mode))
- /* Clipping, do not change the value */
- return;
-
- m_scheme = new_cs;
+ return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
}
inline GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeControl() const
@@ -133,15 +150,67 @@ inline GprsCodingScheme::GprsCodingScheme(Scheme s)
m_scheme = UNKNOWN;
}
-inline void GprsCodingScheme::operator =(Scheme s)
+inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
{
m_scheme = s;
if (!isValid())
m_scheme = UNKNOWN;
+
+ return *this;
}
-inline void GprsCodingScheme::operator =(GprsCodingScheme o)
+inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
{
m_scheme = o.m_scheme;
+ return *this;
+}
+
+inline GprsCodingScheme GprsCodingScheme::getGprsByNum(unsigned num)
+{
+ if (num < 1 || num > 4)
+ return GprsCodingScheme();
+
+ return GprsCodingScheme(Scheme(CS1 + (num - 1)));
+}
+
+inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
+{
+ if (num < 1 || num > 9)
+ return GprsCodingScheme();
+
+ return GprsCodingScheme(Scheme(MCS1 + (num - 1)));
+}
+
+/* The coding schemes form a partial ordering */
+inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
+}
+
+inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return !(a == b);
+}
+
+inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return a.isCompatible(b) &&
+ GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
+}
+
+inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return b < a;
}
+
+inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return a == b || a < b;
+}
+
+inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
+{
+ return a == b || a > b;
+}
+
diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp
index 76fe47c..78f03f8 100644
--- a/src/gprs_ms.cpp
+++ b/src/gprs_ms.cpp
@@ -25,6 +25,7 @@
#include "tbf.h"
#include "gprs_debug.h"
#include "gprs_codel.h"
+#include "pcu_utils.h"
#include <time.h>
@@ -97,8 +98,6 @@ GprsMs::GprsMs(BTS *bts, uint32_t tlli) :
m_ta(0),
m_ms_class(0),
m_egprs_ms_class(0),
- m_current_cs_ul(1),
- m_current_cs_dl(1),
m_is_idle(true),
m_ref(0),
m_list(this),
@@ -107,7 +106,8 @@ GprsMs::GprsMs(BTS *bts, uint32_t tlli) :
m_reserved_dl_slots(0),
m_reserved_ul_slots(0),
m_current_trx(NULL),
- m_codel_state(NULL)
+ m_codel_state(NULL),
+ m_mode(GprsCodingScheme::GPRS)
{
int codel_interval = LLC_CODEL_USE_DEFAULT;
@@ -117,17 +117,11 @@ GprsMs::GprsMs(BTS *bts, uint32_t tlli) :
memset(&m_timer, 0, sizeof(m_timer));
m_timer.cb = GprsMs::timeout;
m_llc_queue.init();
- if (m_bts) {
- m_current_cs_ul = m_bts->bts_data()->initial_cs_ul;
- if (m_current_cs_ul < 1)
- m_current_cs_ul = 1;
- m_current_cs_dl = m_bts->bts_data()->initial_cs_dl;
- if (m_current_cs_dl < 1)
- m_current_cs_dl = 1;
+ set_mode(m_mode);
+ if (m_bts)
codel_interval = m_bts->bts_data()->llc_codel_interval_msec;
- }
if (codel_interval) {
if (codel_interval == LLC_CODEL_USE_DEFAULT)
@@ -215,12 +209,53 @@ void GprsMs::stop_timer()
unref();
}
+void GprsMs::set_mode(GprsCodingScheme::Mode mode)
+{
+ m_mode = mode;
+
+ if (!m_bts)
+ return;
+
+ switch (m_mode) {
+ case GprsCodingScheme::GPRS:
+ if (!m_current_cs_ul.isGprs()) {
+ m_current_cs_ul = GprsCodingScheme::getGprsByNum(
+ m_bts->bts_data()->initial_cs_ul);
+ if (!m_current_cs_ul.isValid())
+ m_current_cs_ul = GprsCodingScheme::CS1;
+ }
+ if (!m_current_cs_dl.isGprs()) {
+ m_current_cs_dl = GprsCodingScheme::getGprsByNum(
+ m_bts->bts_data()->initial_cs_dl);
+ if (!m_current_cs_dl.isValid())
+ m_current_cs_dl = GprsCodingScheme::CS1;
+ }
+ break;
+
+ case GprsCodingScheme::EGPRS_GMSK:
+ case GprsCodingScheme::EGPRS:
+ if (!m_current_cs_ul.isEgprs()) {
+ m_current_cs_ul = GprsCodingScheme::getEgprsByNum(
+ m_bts->bts_data()->initial_mcs_ul);
+ if (!m_current_cs_dl.isValid())
+ m_current_cs_ul = GprsCodingScheme::MCS1;
+ }
+ if (!m_current_cs_dl.isEgprs()) {
+ m_current_cs_dl = GprsCodingScheme::getEgprsByNum(
+ m_bts->bts_data()->initial_mcs_dl);
+ if (!m_current_cs_dl.isValid())
+ m_current_cs_dl = GprsCodingScheme::MCS1;
+ }
+ break;
+ }
+}
+
void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf)
{
if (tbf->direction == GPRS_RLCMAC_DL_TBF)
- attach_dl_tbf(static_cast<gprs_rlcmac_dl_tbf *>(tbf));
+ attach_dl_tbf(as_dl_tbf(tbf));
else
- attach_ul_tbf(static_cast<gprs_rlcmac_ul_tbf *>(tbf));
+ attach_ul_tbf(as_ul_tbf(tbf));
}
void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf)
@@ -464,9 +499,9 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
{
struct gprs_rlcmac_bts *bts_data;
int64_t now;
- uint8_t max_cs_dl = 4;
+ GprsCodingScheme max_cs_dl = this->max_cs_dl();
- OSMO_ASSERT(m_bts != NULL);
+ OSMO_ASSERT(max_cs_dl);
bts_data = m_bts->bts_data();
if (error_rate < 0)
@@ -474,32 +509,30 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
now = now_msec();
- if (bts_data->max_cs_dl)
- max_cs_dl = bts_data->max_cs_dl;
-
/* TODO: Check for TBF direction */
/* TODO: Support different CS values for UL and DL */
m_nack_rate_dl = error_rate;
if (error_rate > bts_data->cs_adj_upper_limit) {
- if (m_current_cs_dl > 1) {
- m_current_cs_dl -= 1;
+ if (m_current_cs_dl.to_num() > 1) {
+ m_current_cs_dl.dec(mode());
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): High error rate %d%%, "
- "reducing CS level to %d\n",
- imsi(), error_rate, m_current_cs_dl);
+ "reducing CS level to %s\n",
+ imsi(), error_rate, m_current_cs_dl.name());
m_last_cs_not_low = now;
}
} else if (error_rate < bts_data->cs_adj_lower_limit) {
if (m_current_cs_dl < max_cs_dl) {
if (now - m_last_cs_not_low > 1000) {
- m_current_cs_dl += 1;
+ m_current_cs_dl.inc(mode());
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): Low error rate %d%%, "
- "increasing DL CS level to %d\n",
- imsi(), error_rate, m_current_cs_dl);
+ "increasing DL CS level to %s\n",
+ imsi(), error_rate,
+ m_current_cs_dl.name());
m_last_cs_not_low = now;
} else {
LOGP(DRLCMACDL, LOGL_DEBUG,
@@ -516,46 +549,125 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
}
}
-void GprsMs::update_l1_meas(const pcu_l1_meas *meas)
+GprsCodingScheme GprsMs::max_cs_ul() const
{
struct gprs_rlcmac_bts *bts_data;
- uint8_t max_cs_ul = 4;
- unsigned i;
OSMO_ASSERT(m_bts != NULL);
bts_data = m_bts->bts_data();
- if (bts_data->max_cs_ul)
- max_cs_ul = bts_data->max_cs_ul;
+ if (m_current_cs_ul.isGprs()) {
+ if (!bts_data->max_cs_ul)
+ return GprsCodingScheme(GprsCodingScheme::CS4);
- if (meas->have_link_qual) {
- int old_link_qual = meas->link_qual;
- int low = bts_data->cs_lqual_ranges[current_cs_ul()-1].low;
- int high = bts_data->cs_lqual_ranges[current_cs_ul()-1].high;
- uint8_t new_cs_ul = m_current_cs_ul;
+ return GprsCodingScheme::getGprsByNum(bts_data->max_cs_ul);
+ }
- if (m_l1_meas.have_link_qual)
- old_link_qual = m_l1_meas.link_qual;
+ if (!m_current_cs_ul.isEgprs())
+ return GprsCodingScheme(); /* UNKNOWN */
- if (meas->link_qual < low && old_link_qual < low)
- new_cs_ul = m_current_cs_ul - 1;
- else if (meas->link_qual > high && old_link_qual > high &&
- m_current_cs_ul < max_cs_ul)
- new_cs_ul = m_current_cs_ul + 1;
+ if (bts_data->max_mcs_ul)
+ return GprsCodingScheme::getEgprsByNum(bts_data->max_mcs_ul);
+ else if (bts_data->max_cs_ul)
+ return GprsCodingScheme::getEgprsByNum(bts_data->max_cs_ul);
- if (m_current_cs_ul != new_cs_ul) {
- LOGP(DRLCMACDL, LOGL_INFO,
- "MS (IMSI %s): "
- "Link quality %ddB (%ddB) left window [%d, %d], "
- "modifying uplink CS level: %d -> %d\n",
- imsi(), meas->link_qual, old_link_qual,
- low, high,
- m_current_cs_ul, new_cs_ul);
-
- m_current_cs_ul = new_cs_ul;
- }
+ return GprsCodingScheme(GprsCodingScheme::MCS4);
+}
+
+GprsCodingScheme GprsMs::max_cs_dl() const
+{
+ struct gprs_rlcmac_bts *bts_data;
+
+ OSMO_ASSERT(m_bts != NULL);
+ bts_data = m_bts->bts_data();
+
+ if (m_current_cs_dl.isGprs()) {
+ if (!bts_data->max_cs_dl)
+ return GprsCodingScheme(GprsCodingScheme::CS4);
+
+ return GprsCodingScheme::getGprsByNum(bts_data->max_cs_dl);
}
+ if (!m_current_cs_dl.isEgprs())
+ return GprsCodingScheme(); /* UNKNOWN */
+
+ if (bts_data->max_mcs_dl)
+ return GprsCodingScheme::getEgprsByNum(bts_data->max_mcs_dl);
+ else if (bts_data->max_cs_dl)
+ return GprsCodingScheme::getEgprsByNum(bts_data->max_cs_dl);
+
+ return GprsCodingScheme(GprsCodingScheme::MCS4);
+}
+
+void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
+{
+ struct gprs_rlcmac_bts *bts_data;
+ GprsCodingScheme max_cs_ul = this->max_cs_ul();
+
+ int old_link_qual;
+ int low;
+ int high;
+ GprsCodingScheme new_cs_ul = m_current_cs_ul;
+ unsigned current_cs_num = m_current_cs_ul.to_num();
+
+ bts_data = m_bts->bts_data();
+
+ if (!max_cs_ul) {
+ LOGP(DRLCMACDL, LOGL_ERROR,
+ "max_cs_ul cannot be derived (current UL CS: %s)\n",
+ m_current_cs_ul.name());
+ return;
+ }
+
+ if (!m_current_cs_ul)
+ return;
+
+ if (!meas->have_link_qual)
+ return;
+
+ old_link_qual = meas->link_qual;
+
+ if (m_current_cs_ul.isGprs()) {
+ low = bts_data->cs_lqual_ranges[current_cs_num-1].low;
+ high = bts_data->cs_lqual_ranges[current_cs_num-1].high;
+ } else if (m_current_cs_ul.isEgprs()) {
+ /* TODO, use separate table */
+ if (current_cs_num > 4)
+ current_cs_num = 4;
+ low = bts_data->cs_lqual_ranges[current_cs_num-1].low;
+ high = bts_data->cs_lqual_ranges[current_cs_num-1].high;
+ } else {
+ return;
+ }
+
+ if (m_l1_meas.have_link_qual)
+ old_link_qual = m_l1_meas.link_qual;
+
+ if (meas->link_qual < low && old_link_qual < low)
+ new_cs_ul.dec(mode());
+ else if (meas->link_qual > high && old_link_qual > high &&
+ m_current_cs_ul < max_cs_ul)
+ new_cs_ul.inc(mode());
+
+ if (m_current_cs_ul != new_cs_ul) {
+ LOGP(DRLCMACDL, LOGL_INFO,
+ "MS (IMSI %s): "
+ "Link quality %ddB (%ddB) left window [%d, %d], "
+ "modifying uplink CS level: %s -> %s\n",
+ imsi(), meas->link_qual, old_link_qual,
+ low, high,
+ m_current_cs_ul.name(), new_cs_ul.name());
+
+ m_current_cs_ul = new_cs_ul;
+ }
+}
+
+void GprsMs::update_l1_meas(const pcu_l1_meas *meas)
+{
+ unsigned i;
+
+ update_cs_ul(meas);
+
if (meas->have_rssi)
m_l1_meas.set_rssi(meas->rssi);
if (meas->have_bto)
@@ -582,9 +694,9 @@ void GprsMs::update_l1_meas(const pcu_l1_meas *meas)
}
}
-uint8_t GprsMs::current_cs_dl() const
+GprsCodingScheme GprsMs::current_cs_dl() const
{
- uint8_t cs = m_current_cs_dl;
+ GprsCodingScheme cs = m_current_cs_dl;
size_t unencoded_octets;
if (!m_bts)
@@ -594,7 +706,7 @@ uint8_t GprsMs::current_cs_dl() const
/* If the DL TBF is active, add number of unencoded chunk octets */
if (m_dl_tbf)
- unencoded_octets = m_dl_tbf->m_llc.chunk_size();
+ unencoded_octets += m_dl_tbf->m_llc.chunk_size();
/* There are many unencoded octets, don't reduce */
if (unencoded_octets >= m_bts->bts_data()->cs_downgrade_threshold)
@@ -605,11 +717,11 @@ uint8_t GprsMs::current_cs_dl() const
return cs;
/* The throughput would probably be better if the CS level was reduced */
- cs -= 1;
+ cs.dec(mode());
/* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */
- if (cs == 2)
- cs -= 1;
+ if (cs == GprsCodingScheme(GprsCodingScheme::CS2))
+ cs.dec(mode());
return cs;
}
@@ -651,6 +763,31 @@ uint8_t GprsMs::ul_slots() const
return slots;
}
+uint8_t GprsMs::current_pacch_slots() const
+{
+ uint8_t slots = 0;
+
+ bool is_dl_active = m_dl_tbf && m_dl_tbf->is_tfi_assigned();
+ bool is_ul_active = m_ul_tbf && m_ul_tbf->is_tfi_assigned();
+
+ if (!is_dl_active && !is_ul_active)
+ return 0;
+
+ /* see TS 44.060, 8.1.1.2.2 */
+ if (is_dl_active && !is_ul_active)
+ slots = m_dl_tbf->dl_slots();
+ else if (!is_dl_active && is_ul_active)
+ slots = m_ul_tbf->ul_slots();
+ else
+ slots = m_ul_tbf->ul_slots() & m_dl_tbf->dl_slots();
+
+ /* Assume a multislot class 1 device */
+ /* TODO: For class 2 devices, this could be removed */
+ slots = pcu_lsb(slots);
+
+ return slots;
+}
+
void GprsMs::set_reserved_slots(gprs_rlcmac_trx *trx,
uint8_t ul_slots, uint8_t dl_slots)
{
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index f9b63f2..b07f175 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -74,6 +74,8 @@ public:
bool check_tlli(uint32_t tlli);
void reset();
+ GprsCodingScheme::Mode mode() const;
+ void set_mode(GprsCodingScheme::Mode mode);
const char *imsi() const;
void set_imsi(const char *imsi);
@@ -85,14 +87,17 @@ public:
void set_ms_class(uint8_t ms_class);
void set_egprs_ms_class(uint8_t ms_class);
- uint8_t current_cs_ul() const;
- uint8_t current_cs_dl() const;
+ GprsCodingScheme current_cs_ul() const;
+ GprsCodingScheme current_cs_dl() const;
+ GprsCodingScheme max_cs_ul() const;
+ GprsCodingScheme max_cs_dl() const;
int first_common_ts() const;
uint8_t dl_slots() const;
uint8_t ul_slots() const;
uint8_t reserved_dl_slots() const;
uint8_t reserved_ul_slots() const;
+ uint8_t current_pacch_slots() const;
gprs_rlcmac_trx *current_trx() const;
void set_reserved_slots(gprs_rlcmac_trx *trx,
uint8_t ul_slots, uint8_t dl_slots);
@@ -134,6 +139,7 @@ protected:
void unref();
void start_timer();
void stop_timer();
+ void update_cs_ul(const pcu_l1_meas*);
private:
BTS *m_bts;
@@ -152,8 +158,8 @@ private:
uint8_t m_ms_class;
uint8_t m_egprs_ms_class;
/* current coding scheme */
- uint8_t m_current_cs_ul;
- uint8_t m_current_cs_dl;
+ GprsCodingScheme m_current_cs_ul;
+ GprsCodingScheme m_current_cs_dl;
gprs_llc_queue m_llc_queue;
@@ -172,6 +178,7 @@ private:
gprs_rlcmac_trx *m_current_trx;
struct gprs_codel *m_codel_state;
+ GprsCodingScheme::Mode m_mode;
};
inline bool GprsMs::is_idle() const
@@ -220,11 +227,16 @@ inline uint8_t GprsMs::egprs_ms_class() const
return m_egprs_ms_class;
}
-inline uint8_t GprsMs::current_cs_ul() const
+inline GprsCodingScheme GprsMs::current_cs_ul() const
{
return m_current_cs_ul;
}
+inline GprsCodingScheme::Mode GprsMs::mode() const
+{
+ return m_mode;
+}
+
inline void GprsMs::set_timeout(unsigned secs)
{
m_delay = secs;
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index b4db88c..313e23f 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -25,7 +25,7 @@
#include "pcu_utils.h"
-static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
+static uint32_t sched_poll(BTS *bts,
uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr,
struct gprs_rlcmac_tbf **poll_tbf,
struct gprs_rlcmac_tbf **ul_ass_tbf,
@@ -34,7 +34,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
{
struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_dl_tbf *dl_tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
uint32_t poll_fn;
/* check special TBF for events */
@@ -42,9 +42,11 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
if ((block_nr % 3) == 2)
poll_fn ++;
poll_fn = poll_fn % 2715648;
- llist_pods_for_each_entry(ul_tbf, &bts->ul_tbfs, list, lpods) {
+ llist_for_each(pos, &bts->ul_tbfs()) {
+ ul_tbf = as_ul_tbf(pos->entry());
+ OSMO_ASSERT(ul_tbf);
/* this trx, this ts */
- if (ul_tbf->trx->trx_no != trx || ul_tbf->control_ts != ts)
+ if (ul_tbf->trx->trx_no != trx || !ul_tbf->is_control_ts(ts))
continue;
/* polling for next uplink block */
if (ul_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
@@ -58,9 +60,11 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
*ul_ass_tbf = ul_tbf;
#warning "Is this supposed to be fair? The last TBF for each wins? Maybe use llist_add_tail and skip once we have all states?"
}
- llist_pods_for_each_entry(dl_tbf, &bts->dl_tbfs, list, lpods) {
+ llist_for_each(pos, &bts->dl_tbfs()) {
+ dl_tbf = as_dl_tbf(pos->entry());
+ OSMO_ASSERT(dl_tbf);
/* this trx, this ts */
- if (dl_tbf->trx->trx_no != trx || dl_tbf->control_ts != ts)
+ if (dl_tbf->trx->trx_no != trx || !dl_tbf->is_control_ts(ts))
continue;
/* polling for next uplink block */
if (dl_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
@@ -126,14 +130,18 @@ static struct msgb *sched_select_ctrl_msg(
if (!tbf)
continue;
- if (tbf == ul_ass_tbf)
- msg = ul_ass_tbf->create_ul_ass(fn);
- else if (tbf == dl_ass_tbf)
- msg = dl_ass_tbf->create_dl_ass(fn);
+ /*
+ * Assignments for the same direction have lower precedence,
+ * because they may kill the TBF when the CONTOL ACK is
+ * received, thus preventing the others from being processed.
+ */
+
+ if (tbf == ul_ass_tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
+ msg = ul_ass_tbf->create_ul_ass(fn, ts);
+ else if (tbf == dl_ass_tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
+ msg = dl_ass_tbf->create_dl_ass(fn, ts);
else if (tbf == ul_ack_tbf)
- msg = ul_ack_tbf->create_ul_ack(fn);
- else
- abort();
+ msg = ul_ack_tbf->create_ul_ack(fn, ts);
if (!msg) {
tbf = NULL;
@@ -145,6 +153,21 @@ static struct msgb *sched_select_ctrl_msg(
break;
}
+ if (!msg) {
+ /*
+ * If one of these is left, the response (CONTROL ACK) from the
+ * MS will kill the current TBF, only one of them can be
+ * non-NULL
+ */
+ if (dl_ass_tbf) {
+ tbf = dl_ass_tbf;
+ msg = dl_ass_tbf->create_dl_ass(fn, ts);
+ } else if (ul_ass_tbf) {
+ tbf = ul_ass_tbf;
+ msg = ul_ass_tbf->create_ul_ass(fn, ts);
+ }
+ }
+
/* any message */
if (msg) {
tbf->rotate_in_list();
@@ -292,7 +315,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
/* store last frame number of RTS */
pdch->last_rts_fn = fn;
- poll_fn = sched_poll(bts, trx, ts, fn, block_nr, &poll_tbf, &ul_ass_tbf,
+ poll_fn = sched_poll(bts->bts, trx, ts, fn, block_nr, &poll_tbf, &ul_ass_tbf,
&dl_ass_tbf, &ul_ack_tbf);
/* check uplink resource for polling */
if (poll_tbf)
@@ -330,6 +353,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
/* msg is now available */
/* set USF */
+ OSMO_ASSERT(msgb_length(msg) > 0);
msg->data[0] = (msg->data[0] & 0xf8) | usf;
/* Used to measure the leak rate, count all blocks */
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp
index 0daeaf5..57197b2 100644
--- a/src/gprs_rlcmac_ts_alloc.cpp
+++ b/src/gprs_rlcmac_ts_alloc.cpp
@@ -24,6 +24,7 @@
#include <bts.h>
#include <tbf.h>
#include <gprs_ms.h>
+#include <pcu_utils.h>
#include <errno.h>
#include <values.h>
@@ -80,20 +81,6 @@ static const struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = {
/* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA },
};
-static unsigned lsb(unsigned x)
-{
- return x & -x;
-}
-
-static unsigned bitcount(unsigned x)
-{
- unsigned count = 0;
- for (count = 0; x; count += 1)
- x &= x - 1;
-
- return count;
-}
-
static char *set_flag_chars(char *buf, uint8_t val, char set_char, char unset_char = 0)
{
int i;
@@ -480,14 +467,12 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
/* The allocation will be successful, so the system state and tbf_/ms_
* may be modified from now on. */
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- struct gprs_rlcmac_ul_tbf *ul_tbf =
- static_cast<gprs_rlcmac_ul_tbf *>(tbf_);
+ struct gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(tbf_);
LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink TS=%d TFI=%d USF=%d\n",
ts, tfi, usf);
assign_uplink_tbf_usf(pdch, ul_tbf, tfi, usf);
} else {
- struct gprs_rlcmac_dl_tbf *dl_tbf =
- static_cast<gprs_rlcmac_dl_tbf *>(tbf_);
+ struct gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(tbf_);
LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d TFI=%d\n",
ts, tfi);
assign_dlink_tbf(pdch, dl_tbf, tfi);
@@ -642,7 +627,7 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
if ((tx_window & (1 << ((ul_ts+num_tx-1) % 8))) == 0)
continue;
- tx_slot_count = bitcount(tx_window);
+ tx_slot_count = pcu_bitcount(tx_window);
max_rx = OSMO_MIN(ms_class->rx, ms_class->sum - num_tx);
rx_valid_win = (1 << max_rx) - 1;
@@ -671,7 +656,7 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
* testing */
rx_window = rx_good & rx_valid_win;
- rx_slot_count = bitcount(rx_window);
+ rx_slot_count = pcu_bitcount(rx_window);
#if 0
LOGP(DRLCMAC, LOGL_DEBUG, "n_tx=%d, n_rx=%d, mask_sel=%d, "
@@ -736,7 +721,7 @@ static int find_multi_slots(struct gprs_rlcmac_bts *bts,
continue;
/* Check number of common slots according to TS 54.002, 6.4.2.2 */
- common_slot_count = bitcount(tx_window & rx_window);
+ common_slot_count = pcu_bitcount(tx_window & rx_window);
req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count);
if (ms_class->type == 1)
req_common_slots = OSMO_MIN(req_common_slots, 2);
@@ -893,7 +878,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
dl_slots & ul_slots, compute_usage_by_num_tbfs,
NULL, NULL);
if (ts < 0)
- ul_slots = dl_slots = lsb(dl_slots & ul_slots);
+ ul_slots = dl_slots = pcu_lsb(dl_slots & ul_slots);
else
ul_slots = dl_slots = (dl_slots & ul_slots) & (1<<ts);
}
@@ -922,9 +907,9 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
"available\n");
return -EINVAL;
}
- slotcount = bitcount(dl_slots);
+ slotcount = pcu_bitcount(dl_slots);
first_ts = ffs(dl_slots) - 1;
- avail_count = bitcount(reserved_dl_slots);
+ avail_count = pcu_bitcount(reserved_dl_slots);
} else {
int free_usf = -1;
@@ -960,7 +945,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
/* We will stick to that single UL slot, unreserve the others */
reserved_ul_slots = ul_slots;
- avail_count = bitcount(reserved_ul_slots);
+ avail_count = pcu_bitcount(reserved_ul_slots);
}
first_common_ts = ffs(dl_slots & ul_slots) - 1;
@@ -1010,8 +995,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
tbf_->first_ts = first_ts;
if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
- struct gprs_rlcmac_dl_tbf *dl_tbf =
- static_cast<gprs_rlcmac_dl_tbf *>(tbf_);
+ struct gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(tbf_);
for (ts = 0; ts < 8; ts++) {
if (!(dl_slots & (1 << ts)))
continue;
@@ -1021,8 +1005,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
assign_dlink_tbf(&trx->pdch[ts], dl_tbf, tfi);
}
} else {
- struct gprs_rlcmac_ul_tbf *ul_tbf =
- static_cast<gprs_rlcmac_ul_tbf *>(tbf_);
+ struct gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(tbf_);
for (ts = 0; ts < 8; ts++) {
if (!(ul_slots & (1 << ts)))
diff --git a/src/gsm_rlcmac.cpp b/src/gsm_rlcmac.cpp
index 44bc5e1..6b43aa6 100644
--- a/src/gsm_rlcmac.cpp
+++ b/src/gsm_rlcmac.cpp
@@ -5509,3 +5509,11 @@ void encode_gsm_rlcmac_downlink_data(bitvec * vector, RlcMacDownlinkDataBlock_t
LOGPC(DRLCMACDATA, LOGL_NOTICE, "\n");
}
}
+
+void decode_gsm_ra_cap(bitvec * vector, MS_Radio_Access_capability_t *data)
+{
+ csnStream_t ar;
+ unsigned readIndex = 0;
+ csnStreamInit(&ar, 0, 8 * vector->data_len);
+ /*ret =*/ csnStreamDecoder(&ar, CSNDESCR(MS_Radio_Access_capability_t), vector, readIndex, data);
+}
diff --git a/src/gsm_rlcmac.h b/src/gsm_rlcmac.h
index 017b311..8f4039c 100644
--- a/src/gsm_rlcmac.h
+++ b/src/gsm_rlcmac.h
@@ -476,7 +476,7 @@ typedef struct
typedef struct
{
- guint8 LENGTH;
+ /* guint8 LENGTH; */
EGPRS_AckNack_Desc_t Desc;
} EGPRS_AckNack_w_len_t;
@@ -5136,4 +5136,5 @@ typedef struct
void encode_gsm_rlcmac_uplink(bitvec * vector, RlcMacUplink_t * data);
void decode_gsm_rlcmac_uplink_data(bitvec * vector, RlcMacUplinkDataBlock_t * data);
void encode_gsm_rlcmac_downlink_data(bitvec * vector, RlcMacDownlinkDataBlock_t * data);
+ void decode_gsm_ra_cap(bitvec * vector, MS_Radio_Access_capability_t * data);
#endif /* __PACKET_GSM_RLCMAC_H__ */
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 96dc6d7..8eb7441 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -164,6 +164,7 @@ int main(int argc, char *argv[])
bts = bts_main_data();
bts->fc_interval = 1;
bts->initial_cs_dl = bts->initial_cs_ul = 1;
+ bts->initial_mcs_dl = bts->initial_mcs_ul = 1;
bts->cs1 = 1;
bts->t3142 = 20;
bts->t3169 = 5;
@@ -180,6 +181,8 @@ int main(int argc, char *argv[])
bts->cs_adj_lower_limit = 10; /* Increase CS if the error rate is below */
bts->max_cs_ul = 4;
bts->max_cs_dl = 4;
+ bts->max_mcs_ul = 4;
+ bts->max_mcs_dl = 4;
/* CS-1 to CS-4 */
bts->cs_lqual_ranges[0].low = -256;
bts->cs_lqual_ranges[0].high = 6;
@@ -191,6 +194,10 @@ int main(int argc, char *argv[])
bts->cs_lqual_ranges[3].high = 256;
bts->cs_downgrade_threshold = 200;
+ /* TODO: increase them when CRBB decoding is implemented */
+ bts->ws_base = 64;
+ bts->ws_pdch = 0;
+
bts->llc_codel_interval_msec = LLC_CODEL_USE_DEFAULT;
bts->dl_tbf_idle_msec = 2000;
bts->llc_idle_ack_csec = 10;
diff --git a/src/pcu_utils.h b/src/pcu_utils.h
index 5ca234a..d664446 100644
--- a/src/pcu_utils.h
+++ b/src/pcu_utils.h
@@ -24,3 +24,19 @@ inline void csecs_to_timeval(unsigned csecs, struct timeval *tv) {
tv->tv_sec = csecs / 100;
tv->tv_usec = (csecs % 100) * 10000;
}
+
+template <typename T>
+inline unsigned int pcu_bitcount(T x)
+{
+ unsigned int count = 0;
+ for (count = 0; x; count += 1)
+ x &= x - 1;
+
+ return count;
+}
+
+template <typename T>
+inline T pcu_lsb(T x)
+{
+ return x & -x;
+}
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index aa29b4c..58fea99 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -55,9 +55,7 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, "pcu%s", VTY_NEWLINE);
if (bts->egprs_enabled)
- vty_out(vty, " egprs%s", VTY_NEWLINE);
- else
- vty_out(vty, " no egprs%s", VTY_NEWLINE);
+ vty_out(vty, " egprs only%s", VTY_NEWLINE);
vty_out(vty, " flow-control-interval %d%s", bts->fc_interval,
VTY_NEWLINE);
@@ -111,6 +109,26 @@ static int config_write_pcu(struct vty *vty)
bts->cs_lqual_ranges[3].low,
VTY_NEWLINE);
+ if (bts->initial_mcs_dl != 1 && bts->initial_mcs_ul != 1) {
+ if (bts->initial_mcs_ul == bts->initial_mcs_dl)
+ vty_out(vty, " mcs %d%s", bts->initial_mcs_dl,
+ VTY_NEWLINE);
+ else
+ vty_out(vty, " mcs %d %d%s", bts->initial_mcs_dl,
+ bts->initial_mcs_ul, VTY_NEWLINE);
+ }
+ if (bts->max_mcs_dl && bts->max_mcs_ul) {
+ if (bts->max_mcs_ul == bts->max_mcs_dl)
+ vty_out(vty, " mcs max %d%s", bts->max_mcs_dl,
+ VTY_NEWLINE);
+ else
+ vty_out(vty, " mcs max %d %d%s", bts->max_mcs_dl,
+ bts->max_mcs_ul, VTY_NEWLINE);
+ }
+
+ vty_out(vty, " window-size %d %d%s", bts->ws_base, bts->ws_pdch,
+ VTY_NEWLINE);
+
if (bts->force_llc_lifetime == 0xffff)
vty_out(vty, " queue lifetime infinite%s", VTY_NEWLINE);
else if (bts->force_llc_lifetime)
@@ -162,8 +180,8 @@ DEFUN(cfg_pcu,
DEFUN(cfg_pcu_egprs,
cfg_pcu_egprs_cmd,
- "egprs",
- EGPRS_STR)
+ "egprs only",
+ EGPRS_STR "Use EGPRS and disable plain GPRS\n")
{
struct gprs_rlcmac_bts *bts = bts_main_data();
@@ -361,11 +379,12 @@ DEFUN(cfg_pcu_no_cs,
return CMD_SUCCESS;
}
+#define CS_MAX_STR "Set maximum values for adaptive CS selection (overrides BTS config)\n"
DEFUN(cfg_pcu_cs_max,
cfg_pcu_cs_max_cmd,
"cs max <1-4> [<1-4>]",
CS_STR
- "Set maximum values for adaptive CS selection (overrides BTS config)\n"
+ CS_MAX_STR
"Maximum CS value to be used\n"
"Use a different maximum CS value for the uplink")
{
@@ -384,8 +403,7 @@ DEFUN(cfg_pcu_cs_max,
DEFUN(cfg_pcu_no_cs_max,
cfg_pcu_no_cs_max_cmd,
"no cs max",
- NO_STR CS_STR
- "Set maximum values for adaptive CS selection (overrides BTS config)\n")
+ NO_STR CS_STR CS_MAX_STR)
{
struct gprs_rlcmac_bts *bts = bts_main_data();
@@ -395,6 +413,93 @@ DEFUN(cfg_pcu_no_cs_max,
return CMD_SUCCESS;
}
+#define MCS_STR "Modulation and Coding Scheme configuration (EGPRS)\n"
+
+DEFUN(cfg_pcu_mcs,
+ cfg_pcu_mcs_cmd,
+ "mcs <1-9> [<1-9>]",
+ MCS_STR
+ "Initial MCS value to be used (default 1)\n"
+ "Use a different initial MCS value for the uplink")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+ uint8_t cs = atoi(argv[0]);
+
+ bts->initial_mcs_dl = cs;
+ if (argc > 1)
+ bts->initial_mcs_ul = atoi(argv[1]);
+ else
+ bts->initial_mcs_ul = cs;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_mcs,
+ cfg_pcu_no_mcs_cmd,
+ "no mcs",
+ NO_STR MCS_STR)
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->initial_mcs_dl = 1;
+ bts->initial_mcs_ul = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_mcs_max,
+ cfg_pcu_mcs_max_cmd,
+ "mcs max <1-9> [<1-9>]",
+ MCS_STR
+ CS_MAX_STR
+ "Maximum MCS value to be used\n"
+ "Use a different maximum MCS value for the uplink")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+ uint8_t mcs = atoi(argv[0]);
+
+ bts->max_mcs_dl = mcs;
+ if (argc > 1)
+ bts->max_mcs_ul = atoi(argv[1]);
+ else
+ bts->max_mcs_ul = mcs;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_mcs_max,
+ cfg_pcu_no_mcs_max_cmd,
+ "no mcs max",
+ NO_STR MCS_STR CS_MAX_STR)
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->max_mcs_dl = 0;
+ bts->max_mcs_ul = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_window_size,
+ cfg_pcu_window_size_cmd,
+ "window-size <0-1024> [<0-256>]",
+ "Window size configuration (b + N_PDCH * f)\n"
+ "Base value (b)\n"
+ "Factor for number of PDCH (f)")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+ uint16_t b = atoi(argv[0]);
+
+ bts->ws_base = b;
+ if (argc > 1) {
+ uint16_t f = atoi(argv[1]);
+ bts->ws_pdch = f;
+ }
+
+ return CMD_SUCCESS;
+}
+
+
#define QUEUE_STR "Packet queue options\n"
#define LIFETIME_STR "Set lifetime limit of LLC frame in centi-seconds " \
"(overrides the value given by SGSN)\n"
@@ -775,19 +880,7 @@ DEFUN(show_tbf,
SHOW_STR "information about TBFs\n" "All TBFs\n")
{
struct gprs_rlcmac_bts *bts = bts_main_data();
- struct llist_head *tbf;
-
- vty_out(vty, "UL TBFs%s", VTY_NEWLINE);
- llist_for_each(tbf, &bts->ul_tbfs) {
- tbf_print_vty_info(vty, tbf);
- }
-
- vty_out(vty, "%sDL TBFs%s", VTY_NEWLINE, VTY_NEWLINE);
- llist_for_each(tbf, &bts->dl_tbfs) {
- tbf_print_vty_info(vty, tbf);
- }
-
- return CMD_SUCCESS;
+ return pcu_vty_show_tbf_all(vty, bts);
}
DEFUN(show_ms_all,
@@ -860,6 +953,11 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_cs_downgrade_thrsh_cmd);
install_element(PCU_NODE, &cfg_pcu_no_cs_downgrade_thrsh_cmd);
install_element(PCU_NODE, &cfg_pcu_cs_lqual_ranges_cmd);
+ install_element(PCU_NODE, &cfg_pcu_mcs_cmd);
+ install_element(PCU_NODE, &cfg_pcu_no_mcs_cmd);
+ install_element(PCU_NODE, &cfg_pcu_mcs_max_cmd);
+ install_element(PCU_NODE, &cfg_pcu_no_mcs_max_cmd);
+ install_element(PCU_NODE, &cfg_pcu_window_size_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_inf_cmd);
install_element(PCU_NODE, &cfg_pcu_no_queue_lifetime_cmd);
diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp
index ce2a006..166b15e 100644
--- a/src/pcu_vty_functions.cpp
+++ b/src/pcu_vty_functions.cpp
@@ -39,6 +39,61 @@ int pcu_vty_config_write_pcu_ext(struct vty *vty)
return CMD_SUCCESS;
}
+static void tbf_print_vty_info(struct vty *vty, gprs_rlcmac_tbf *tbf)
+{
+ gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(tbf);
+ gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(tbf);
+
+ vty_out(vty, "TBF: TFI=%d TLLI=0x%08x (%s) DIR=%s IMSI=%s%s", tbf->tfi(),
+ tbf->tlli(), tbf->is_tlli_valid() ? "valid" : "invalid",
+ tbf->direction == GPRS_RLCMAC_UL_TBF ? "UL" : "DL",
+ tbf->imsi(), VTY_NEWLINE);
+ vty_out(vty, " created=%lu state=%08x 1st_TS=%d 1st_cTS=%d ctrl_TS=%d "
+ "MS_CLASS=%d/%d%s",
+ tbf->created_ts(), tbf->state_flags, tbf->first_ts,
+ tbf->first_common_ts, tbf->control_ts,
+ tbf->ms_class(),
+ tbf->ms() ? tbf->ms()->egprs_ms_class() : -1,
+ VTY_NEWLINE);
+ vty_out(vty, " TS_alloc=");
+ for (int i = 0; i < 8; i++) {
+ bool is_ctrl = tbf->is_control_ts(i);
+ if (tbf->pdch[i])
+ vty_out(vty, "%d%s ", i, is_ctrl ? "!" : "");
+ }
+ vty_out(vty, " CS=%s WS=%d",
+ tbf->current_cs().name(), tbf->window()->ws());
+
+ if (ul_tbf) {
+ gprs_rlc_ul_window *win = &ul_tbf->m_window;
+ vty_out(vty, " V(Q)=%d V(R)=%d",
+ win->v_q(), win->v_r());
+ }
+ if (dl_tbf) {
+ gprs_rlc_dl_window *win = &dl_tbf->m_window;
+ vty_out(vty, " V(A)=%d V(S)=%d nBSN=%d%s",
+ win->v_a(), win->v_s(), win->resend_needed(),
+ win->window_stalled() ? " STALLED" : "");
+ }
+ vty_out(vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
+}
+
+int pcu_vty_show_tbf_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data)
+{
+ BTS *bts = bts_data->bts;
+ LListHead<gprs_rlcmac_tbf> *ms_iter;
+
+ vty_out(vty, "UL TBFs%s", VTY_NEWLINE);
+ llist_for_each(ms_iter, &bts->ul_tbfs())
+ tbf_print_vty_info(vty, ms_iter->entry());
+
+ vty_out(vty, "%sDL TBFs%s", VTY_NEWLINE, VTY_NEWLINE);
+ llist_for_each(ms_iter, &bts->dl_tbfs())
+ tbf_print_vty_info(vty, ms_iter->entry());
+
+ return CMD_SUCCESS;
+}
+
int pcu_vty_show_ms_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data)
{
BTS *bts = bts_data->bts;
@@ -47,10 +102,11 @@ int pcu_vty_show_ms_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data)
llist_for_each(ms_iter, &bts->ms_store().ms_list()) {
GprsMs *ms = ms_iter->entry();
- vty_out(vty, "MS TLLI=%08x, TA=%d, CS-UL=%d, CS-DL=%d, LLC=%d, "
+ vty_out(vty, "MS TLLI=%08x, TA=%d, CS-UL=%s, CS-DL=%s, LLC=%d, "
"IMSI=%s%s",
ms->tlli(),
- ms->ta(), ms->current_cs_ul(), ms->current_cs_dl(),
+ ms->ta(), ms->current_cs_ul().name(),
+ ms->current_cs_dl().name(),
ms->llc_queue()->size(),
ms->imsi(),
VTY_NEWLINE);
@@ -62,15 +118,24 @@ static int show_ms(struct vty *vty, GprsMs *ms)
{
unsigned i;
LListHead<gprs_rlcmac_tbf> *i_tbf;
+ uint8_t slots;
vty_out(vty, "MS TLLI=%08x, IMSI=%s%s", ms->tlli(), ms->imsi(), VTY_NEWLINE);
vty_out(vty, " Timing advance (TA): %d%s", ms->ta(), VTY_NEWLINE);
- vty_out(vty, " Coding scheme uplink: CS-%d%s", ms->current_cs_ul(),
+ vty_out(vty, " Coding scheme uplink: %s%s", ms->current_cs_ul().name(),
VTY_NEWLINE);
- vty_out(vty, " Coding scheme downlink: CS-%d%s", ms->current_cs_dl(),
+ vty_out(vty, " Coding scheme downlink: %s%s", ms->current_cs_dl().name(),
VTY_NEWLINE);
+ vty_out(vty, " Mode: %s%s",
+ GprsCodingScheme::modeName(ms->mode()), VTY_NEWLINE);
vty_out(vty, " MS class: %d%s", ms->ms_class(), VTY_NEWLINE);
vty_out(vty, " EGPRS MS class: %d%s", ms->egprs_ms_class(), VTY_NEWLINE);
+ vty_out(vty, " PACCH: ");
+ slots = ms->current_pacch_slots();
+ for (int i = 0; i < 8; i++)
+ if (slots & (1 << i))
+ vty_out(vty, "%d ", i);
+ vty_out(vty, "%s", VTY_NEWLINE);
vty_out(vty, " LLC queue length: %d%s", ms->llc_queue()->size(),
VTY_NEWLINE);
vty_out(vty, " LLC queue octets: %d%s", ms->llc_queue()->octets(),
diff --git a/src/pcu_vty_functions.h b/src/pcu_vty_functions.h
index 1f4ad91..35acf64 100644
--- a/src/pcu_vty_functions.h
+++ b/src/pcu_vty_functions.h
@@ -28,6 +28,7 @@ struct vty;
struct gprs_rlcmac_bts;
int pcu_vty_config_write_pcu_ext(struct vty *vty);
+int pcu_vty_show_tbf_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data);
int pcu_vty_show_ms_all(struct vty *vty, struct gprs_rlcmac_bts *bts_data);
int pcu_vty_show_ms_by_tlli(struct vty *vty, struct gprs_rlcmac_bts *bts_data,
uint32_t tlli);
diff --git a/src/poll_controller.cpp b/src/poll_controller.cpp
index 8108f74..54e3bc7 100644
--- a/src/poll_controller.cpp
+++ b/src/poll_controller.cpp
@@ -30,14 +30,14 @@ PollController::PollController(BTS& bts)
void PollController::expireTimedout(int frame_number, unsigned max_delay)
{
- struct gprs_rlcmac_bts *bts = m_bts.bts_data();
struct gprs_rlcmac_dl_tbf *dl_tbf;
struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_sba *sba, *sba2;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
uint32_t elapsed;
- llist_pods_for_each_entry(ul_tbf, &bts->ul_tbfs, list, lpods) {
+ llist_for_each(pos, &m_bts.ul_tbfs()) {
+ ul_tbf = as_ul_tbf(pos->entry());
if (ul_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
elapsed = (frame_number + 2715648 - ul_tbf->poll_fn)
% 2715648;
@@ -45,7 +45,8 @@ void PollController::expireTimedout(int frame_number, unsigned max_delay)
ul_tbf->poll_timeout();
}
}
- llist_pods_for_each_entry(dl_tbf, &bts->dl_tbfs, list, lpods) {
+ llist_for_each(pos, &m_bts.dl_tbfs()) {
+ dl_tbf = as_dl_tbf(pos->entry());
if (dl_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
elapsed = (frame_number + 2715648 - dl_tbf->poll_fn)
% 2715648;
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 227fa36..79d8f48 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -57,7 +57,7 @@ void gprs_rlc_dl_window::reset()
int gprs_rlc_dl_window::resend_needed()
{
- for (uint16_t bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) {
+ for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
if (m_v_b.is_nacked(bsn) || m_v_b.is_resend(bsn))
return bsn;
}
@@ -69,7 +69,7 @@ int gprs_rlc_dl_window::mark_for_resend()
{
int resend = 0;
- for (uint16_t bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) {
+ for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
if (m_v_b.is_unacked(bsn)) {
/* mark to be re-send */
m_v_b.mark_resend(bsn);
@@ -85,7 +85,7 @@ int gprs_rlc_dl_window::count_unacked()
uint16_t unacked = 0;
uint16_t bsn;
- for (bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) {
+ for (bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
if (!m_v_b.is_acked(bsn))
unacked += 1;
}
@@ -93,19 +93,50 @@ int gprs_rlc_dl_window::count_unacked()
return unacked;
}
-static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns)
+static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn)
{
- return (ssn - 1 - bitnum) & mod_sns;
+ return (ssn - 1 - bitnum);
}
-void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint8_t ssn,
+void gprs_rlc_dl_window::update(BTS *bts, const struct bitvec *rbb,
+ uint16_t first_bsn, uint16_t *lost,
+ uint16_t *received)
+{
+ unsigned num_blocks = rbb->cur_bit;
+ unsigned bsn;
+
+ /* first_bsn is in range V(A)..V(S) */
+
+ for (unsigned int bitpos = 0; bitpos < num_blocks; bitpos++) {
+ bool is_ack;
+ bsn = mod_sns(first_bsn + bitpos);
+ if (bsn == mod_sns(v_a() - 1))
+ break;
+
+ is_ack = bitvec_get_bit_pos(rbb, bitpos) == 1;
+
+ if (is_ack) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
+ if (!m_v_b.is_acked(bsn))
+ *received += 1;
+ m_v_b.mark_acked(bsn);
+ } else {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn);
+ m_v_b.mark_nacked(bsn);
+ bts->rlc_nacked();
+ *lost += 1;
+ }
+ }
+}
+
+void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint16_t ssn,
uint16_t *lost, uint16_t *received)
{
/* SSN - 1 is in range V(A)..V(S)-1 */
for (int bitpos = 0; bitpos < ws(); bitpos++) {
- uint16_t bsn = bitnum_to_bsn(bitpos, ssn, mod_sns());
+ uint16_t bsn = mod_sns(bitnum_to_bsn(bitpos, ssn));
- if (bsn == ((v_a() - 1) & mod_sns()))
+ if (bsn == mod_sns(v_a() - 1))
break;
if (show_rbb[ws() - 1 - bitpos] == 'R') {
@@ -128,7 +159,7 @@ int gprs_rlc_dl_window::move_window()
uint16_t bsn;
int moved = 0;
- for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = (bsn + 1) & mod_sns()) {
+ for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) {
if (m_v_b.is_acked(bsn)) {
m_v_b.mark_invalid(bsn);
moved += 1;
@@ -144,7 +175,7 @@ void gprs_rlc_dl_window::show_state(char *show_v_b)
int i;
uint16_t bsn;
- for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = (bsn + 1) & mod_sns()) {
+ for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) {
uint16_t index = bsn & mod_sns_half();
switch(m_v_b.get_state(index)) {
case GPRS_RLC_DL_BSN_INVALID:
@@ -172,6 +203,22 @@ void gprs_rlc_v_n::reset()
m_v_n[i] = GPRS_RLC_UL_BSN_INVALID;
}
+void gprs_rlc_window::set_sns(uint16_t sns)
+{
+ OSMO_ASSERT(sns >= RLC_GPRS_SNS);
+ OSMO_ASSERT(sns <= RLC_MAX_SNS);
+ /* check for 2^n */
+ OSMO_ASSERT((sns & (-sns)) == sns);
+ m_sns = sns;
+}
+
+void gprs_rlc_window::set_ws(uint16_t ws)
+{
+ OSMO_ASSERT(ws >= RLC_GPRS_SNS/2);
+ OSMO_ASSERT(ws <= RLC_MAX_SNS/2);
+ m_ws = ws;
+}
+
/* Update the receive block bitmap */
void gprs_rlc_ul_window::update_rbb(char *rbb)
{
@@ -188,7 +235,7 @@ void gprs_rlc_ul_window::update_rbb(char *rbb)
void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn)
{
uint16_t offset_v_r;
- offset_v_r = (bsn + 1 - v_r()) & mod_sns();
+ offset_v_r = mod_sns(bsn + 1 - v_r());
/* Positive offset, so raise. */
if (offset_v_r < (sns() >> 1)) {
while (offset_v_r--) {
@@ -212,7 +259,7 @@ uint16_t gprs_rlc_ul_window::raise_v_q()
if (!m_v_n.is_received(v_q()))
break;
LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
- "V(Q) to %d\n", v_q(), (v_q() + 1) & mod_sns());
+ "V(Q) to %d\n", v_q(), mod_sns(v_q() + 1));
raise_v_q(1);
count += 1;
}
@@ -233,3 +280,108 @@ bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn)
return was_valid;
}
+
+static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
+ GprsCodingScheme cs, bool with_padding, unsigned int header_bits)
+{
+ unsigned int i;
+ unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0;
+
+ memset(rlc, 0, sizeof(*rlc));
+
+ rlc->cs = cs;
+ rlc->with_padding = with_padding;
+ rlc->num_data_blocks = cs.numDataBlocks();
+
+ OSMO_ASSERT(rlc->num_data_blocks <= ARRAY_SIZE(rlc->block_info));
+
+ for (i = 0; i < rlc->num_data_blocks; i++) {
+ gprs_rlc_data_block_info_init(&rlc->block_info[i], cs,
+ with_padding);
+
+ rlc->data_offs_bits[i] =
+ header_bits + padding_bits +
+ (i+1) * cs.numDataBlockHeaderBits() +
+ i * 8 * rlc->block_info[0].data_len;
+ }
+}
+
+void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
+ GprsCodingScheme cs, bool with_padding)
+{
+ return gprs_rlc_data_header_init(rlc, cs, with_padding,
+ cs.numDataHeaderBitsDL());
+}
+
+void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
+ GprsCodingScheme cs, bool with_padding)
+{
+ return gprs_rlc_data_header_init(rlc, cs, with_padding,
+ cs.numDataHeaderBitsUL());
+}
+
+void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
+ GprsCodingScheme cs, bool with_padding)
+{
+ unsigned int data_len = cs.maxDataBlockBytes();
+ if (with_padding)
+ data_len -= cs.optionalPaddingBits() / 8;
+
+ rdbi->data_len = data_len;
+ rdbi->bsn = 0;
+ rdbi->ti = 0;
+ rdbi->e = 1;
+ rdbi->cv = 15;
+ rdbi->pi = 0;
+ rdbi->spb = 0;
+}
+
+unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2,
+ int with_padding)
+{
+ switch (GprsCodingScheme::Scheme(cs)) {
+ case GprsCodingScheme::MCS1: return 0b1011 + punct % 2;
+ case GprsCodingScheme::MCS2: return 0b1001 + punct % 2;
+ case GprsCodingScheme::MCS3: return (with_padding ? 0b0110 : 0b0011) +
+ punct % 3;
+ case GprsCodingScheme::MCS4: return 0b0000 + punct % 3;
+ case GprsCodingScheme::MCS5: return 0b100 + punct % 2;
+ case GprsCodingScheme::MCS6: return (with_padding ? 0b010 : 0b000) +
+ punct % 2;
+ case GprsCodingScheme::MCS7: return 0b10100 + 3 * (punct % 3) + punct2 % 3;
+ case GprsCodingScheme::MCS8: return 0b01011 + 3 * (punct % 3) + punct2 % 3;
+ case GprsCodingScheme::MCS9: return 0b00000 + 4 * (punct % 3) + punct2 % 3;
+ default: ;
+ }
+
+ return -1;
+}
+
+void gprs_rlc_mcs_cps_decode(unsigned int cps,
+ GprsCodingScheme cs, int *punct, int *punct2, int *with_padding)
+{
+ *punct2 = -1;
+ *with_padding = 0;
+
+ switch (GprsCodingScheme::Scheme(cs)) {
+ case GprsCodingScheme::MCS1:
+ cps -= 0b1011; *punct = cps % 2; break;
+ case GprsCodingScheme::MCS2:
+ cps -= 0b1001; *punct = cps % 2; break;
+ case GprsCodingScheme::MCS3:
+ cps -= 0b0011; *punct = cps % 3; *with_padding = cps >= 3; break;
+ case GprsCodingScheme::MCS4:
+ cps -= 0b0000; *punct = cps % 3; break;
+ case GprsCodingScheme::MCS5:
+ cps -= 0b100; *punct = cps % 2; break;
+ case GprsCodingScheme::MCS6:
+ cps -= 0b000; *punct = cps % 2; *with_padding = cps >= 2; break;
+ case GprsCodingScheme::MCS7:
+ cps -= 0b10100; *punct = cps / 3; *punct2 = cps % 3; break;
+ case GprsCodingScheme::MCS8:
+ cps -= 0b01011; *punct = cps / 3; *punct2 = cps % 3; break;
+ case GprsCodingScheme::MCS9:
+ cps -= 0b00000; *punct = cps / 4; *punct2 = cps % 3; break;
+ default: ;
+ }
+}
diff --git a/src/rlc.h b/src/rlc.h
index f2acb98..54f28df 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -25,9 +25,16 @@
#include <stdint.h>
-#define RLC_MAX_SNS 128 /* GPRS, must be power of 2 */
-#define RLC_MAX_WS 64 /* max window size */
-#define RLC_MAX_LEN 54 /* CS-4 including spare bits */
+#define RLC_GPRS_SNS 128 /* GPRS, must be power of 2 */
+#define RLC_GPRS_WS 64 /* max window size */
+#define RLC_EGPRS_SNS 2048 /* EGPRS, must be power of 2 */
+#define RLC_EGPRS_MIN_WS 64 /* min window size */
+#define RLC_EGPRS_MAX_WS 1024 /* min window size */
+#define RLC_EGPRS_SNS 2048 /* EGPRS, must be power of 2 */
+#define RLC_EGPRS_MAX_BSN_DELTA 512
+#define RLC_MAX_SNS RLC_EGPRS_SNS
+#define RLC_MAX_WS RLC_EGPRS_MAX_WS
+#define RLC_MAX_LEN 74 /* MCS-9 data unit */
struct BTS;
struct gprs_rlc_v_n;
@@ -55,26 +62,31 @@ static inline uint16_t mod_sns_half()
return (RLC_MAX_SNS / 2) - 1;
}
-struct gprs_rlc_ul_data_block_info {
+struct gprs_rlc_data_block_info {
unsigned int data_len; /* EGPRS: N2, GPRS: N2-2, N-2 */
unsigned int bsn;
unsigned int ti;
unsigned int e;
- unsigned int cv;
+ unsigned int cv; /* FBI == 1 <=> CV == 0 */
unsigned int pi;
unsigned int spb;
};
-struct gprs_rlc_ul_header_egprs {
+struct gprs_rlc_data_info {
GprsCodingScheme cs;
unsigned int r;
unsigned int si;
unsigned int tfi;
unsigned int cps;
unsigned int rsb;
+ unsigned int usf;
+ unsigned int es_p;
+ unsigned int rrbp;
+ unsigned int pr;
unsigned int num_data_blocks;
+ unsigned int with_padding;
unsigned int data_offs_bits[2];
- struct gprs_rlc_ul_data_block_info block_info[2];
+ struct gprs_rlc_data_block_info block_info[2];
};
struct gprs_rlc_data {
@@ -86,10 +98,21 @@ struct gprs_rlc_data {
/* block len of history */
uint8_t len;
- struct gprs_rlc_ul_data_block_info block_info;
+ struct gprs_rlc_data_block_info block_info;
GprsCodingScheme cs;
};
+void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
+ GprsCodingScheme cs, bool with_padding);
+void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
+ GprsCodingScheme cs, bool with_padding);
+void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
+ GprsCodingScheme cs, bool with_padding);
+unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2,
+ int with_padding);
+void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs,
+ int *punct, int *punct2, int *with_padding);
+
/*
* I hold the currently transferred blocks and will provide
* the routines to manipulate these arrays.
@@ -131,18 +154,28 @@ private:
/**
- * TODO: The UL/DL code could/should share a baseclass but
- * we are using llist_for_each_entry for the TBF which
- * requires everything which creates a requirement for a POD
- * type and in < C++11 something that is using even if the
- * most simple form of inheritance is not a POD anymore.
+ * TODO: The UL/DL code could/should share a base class.
*/
-struct gprs_rlc_dl_window {
- void reset();
+class gprs_rlc_window {
+public:
+ gprs_rlc_window();
+
const uint16_t mod_sns() const;
+ const uint16_t mod_sns(uint16_t bsn) const;
const uint16_t sns() const;
const uint16_t ws() const;
+ void set_sns(uint16_t sns);
+ void set_ws(uint16_t ws);
+
+protected:
+ uint16_t m_sns;
+ uint16_t m_ws;
+};
+
+struct gprs_rlc_dl_window: public gprs_rlc_window {
+ void reset();
+
bool window_stalled() const;
bool window_empty() const;
@@ -157,8 +190,11 @@ struct gprs_rlc_dl_window {
/* Methods to manage reception */
int resend_needed();
int mark_for_resend();
- void update(BTS *bts, char *show_rbb, uint8_t ssn,
+ void update(BTS *bts, char *show_rbb, uint16_t ssn,
uint16_t *lost, uint16_t *received);
+ void update(BTS *bts, const struct bitvec *rbb,
+ uint16_t first_bsn, uint16_t *lost,
+ uint16_t *received);
int move_window();
void show_state(char *show_rbb);
int count_unacked();
@@ -167,6 +203,8 @@ struct gprs_rlc_dl_window {
uint16_t m_v_a; /* ack state */
gprs_rlc_v_b m_v_b;
+
+ gprs_rlc_dl_window();
};
struct gprs_rlc_v_n {
@@ -184,18 +222,14 @@ private:
gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */
};
-struct gprs_rlc_ul_window {
- const uint16_t mod_sns() const;
- const uint16_t sns() const;
- const uint16_t ws() const;
-
+struct gprs_rlc_ul_window: public gprs_rlc_window {
const uint16_t v_r() const;
const uint16_t v_q() const;
const uint16_t ssn() const;
- bool is_in_window(uint8_t bsn) const;
- bool is_received(uint8_t bsn) const;
+ bool is_in_window(uint16_t bsn) const;
+ bool is_received(uint16_t bsn) const;
void update_rbb(char *rbb);
void raise_v_r_to(int moves);
@@ -211,6 +245,8 @@ struct gprs_rlc_ul_window {
uint16_t m_v_q; /* receive window state */
gprs_rlc_v_n m_v_n;
+
+ gprs_rlc_ul_window();
};
extern "C" {
@@ -268,6 +304,50 @@ struct gprs_rlc_ul_header_egprs_3 {
spare:1,
dummy:1;
} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_1 {
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_a:1;
+ uint8_t tfi_b:4,
+ pr:2,
+ bsn1_a:2;
+ uint8_t bsn1_b:8;
+ uint8_t bsn1_c:1,
+ bsn2_a:7;
+ uint8_t bsn2_b:3,
+ cps:5;
+} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_2 {
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_a:1;
+ uint8_t tfi_b:4,
+ pr:2,
+ bsn1_a:2;
+ uint8_t bsn1_b:8;
+ uint8_t bsn1_c:1,
+ cps:3,
+ dummy:4;
+} __attribute__ ((packed));
+
+struct gprs_rlc_dl_header_egprs_3 {
+ uint8_t usf:3,
+ es_p:2,
+ rrbp:2,
+ tfi_a:1;
+ uint8_t tfi_b:4,
+ pr:2,
+ bsn1_a:2;
+ uint8_t bsn1_b:8;
+ uint8_t bsn1_c:1,
+ cps:4,
+ spb:2,
+ dummy:1;
+} __attribute__ ((packed));
#else
# error "Only little endian headers are supported yet. TODO: add missing structs"
#endif
@@ -338,21 +418,38 @@ inline void gprs_rlc_v_b::mark_invalid(int bsn)
return mark(bsn, GPRS_RLC_DL_BSN_INVALID);
}
-inline const uint16_t gprs_rlc_dl_window::sns() const
+inline gprs_rlc_window::gprs_rlc_window()
+ : m_sns(RLC_GPRS_SNS)
+ , m_ws(RLC_GPRS_WS)
{
- return RLC_MAX_SNS;
}
-inline const uint16_t gprs_rlc_dl_window::ws() const
+inline const uint16_t gprs_rlc_window::sns() const
{
- return RLC_MAX_WS;
+ return m_sns;
}
-inline const uint16_t gprs_rlc_dl_window::mod_sns() const
+inline const uint16_t gprs_rlc_window::ws() const
+{
+ return m_ws;
+}
+
+inline const uint16_t gprs_rlc_window::mod_sns() const
{
return sns() - 1;
}
+inline const uint16_t gprs_rlc_window::mod_sns(uint16_t bsn) const
+{
+ return bsn & mod_sns();
+}
+
+inline gprs_rlc_dl_window::gprs_rlc_dl_window()
+ : m_v_s(0)
+ , m_v_a(0)
+{
+}
+
inline const uint16_t gprs_rlc_dl_window::v_s() const
{
return m_v_s;
@@ -360,7 +457,7 @@ inline const uint16_t gprs_rlc_dl_window::v_s() const
inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const
{
- return (m_v_s + offset) & mod_sns();
+ return mod_sns(m_v_s + offset);
}
inline const uint16_t gprs_rlc_dl_window::v_a() const
@@ -370,7 +467,7 @@ inline const uint16_t gprs_rlc_dl_window::v_a() const
inline bool gprs_rlc_dl_window::window_stalled() const
{
- return ((m_v_s - m_v_a) & mod_sns()) == ws();
+ return (mod_sns(m_v_s - m_v_a)) == ws();
}
inline bool gprs_rlc_dl_window::window_empty() const
@@ -393,7 +490,13 @@ inline const int16_t gprs_rlc_dl_window::distance() const
return (m_v_s - m_v_a) & mod_sns();
}
-inline bool gprs_rlc_ul_window::is_in_window(uint8_t bsn) const
+inline gprs_rlc_ul_window::gprs_rlc_ul_window()
+ : m_v_r(0)
+ , m_v_q(0)
+{
+}
+
+inline bool gprs_rlc_ul_window::is_in_window(uint16_t bsn) const
{
uint16_t offset_v_q;
@@ -404,7 +507,7 @@ inline bool gprs_rlc_ul_window::is_in_window(uint8_t bsn) const
return offset_v_q < ws();
}
-inline bool gprs_rlc_ul_window::is_received(uint8_t bsn) const
+inline bool gprs_rlc_ul_window::is_received(uint16_t bsn) const
{
uint16_t offset_v_r;
@@ -413,21 +516,6 @@ inline bool gprs_rlc_ul_window::is_received(uint8_t bsn) const
return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws();
}
-inline const uint16_t gprs_rlc_ul_window::sns() const
-{
- return RLC_MAX_SNS;
-}
-
-inline const uint16_t gprs_rlc_ul_window::ws() const
-{
- return RLC_MAX_WS;
-}
-
-inline const uint16_t gprs_rlc_ul_window::mod_sns() const
-{
- return sns() - 1;
-}
-
inline const uint16_t gprs_rlc_ul_window::v_r() const
{
return m_v_r;
@@ -445,12 +533,12 @@ inline const uint16_t gprs_rlc_ul_window::ssn() const
inline void gprs_rlc_ul_window::raise_v_r_to(int moves)
{
- m_v_r = (m_v_r + moves) & mod_sns();
+ m_v_r = mod_sns(m_v_r + moves);
}
inline void gprs_rlc_ul_window::raise_v_q(int incr)
{
- m_v_q = (m_v_q + incr) & mod_sns();
+ m_v_q = mod_sns(m_v_q + incr);
}
inline void gprs_rlc_v_n::mark_received(int bsn)
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 556f6e8..69b9e3a 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -28,6 +28,7 @@
#include <gprs_bssgp_pcu.h>
#include <gprs_ms.h>
#include <decoding.h>
+#include <pcu_utils.h>
extern "C" {
#include <osmocom/core/msgb.h>
@@ -60,6 +61,7 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir) :
ul_ack_state(GPRS_RLCMAC_UL_ACK_NONE),
poll_state(GPRS_RLCMAC_POLL_NONE),
poll_fn(0),
+ poll_ts(0),
n3105(0),
T(0),
num_T_exp(0),
@@ -74,12 +76,12 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir) :
m_ms(NULL),
m_ta(0),
m_ms_class(0),
+ m_list(this),
m_ms_list(this),
m_egprs_enabled(false)
{
/* The classes of these members do not have proper constructors yet.
* Just set them to 0 like talloc_zero did */
- memset(&list, 0, sizeof(list));
memset(&pdch, 0, sizeof(pdch));
memset(&timer, 0, sizeof(timer));
memset(&m_rlc, 0, sizeof(m_rlc));
@@ -88,9 +90,6 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir) :
m_llc.init();
m_name_buf[0] = '\0';
-
- /* Back pointer for PODS llist compatibility */
- list.back = this;
}
gprs_rlcmac_bts *gprs_rlcmac_tbf::bts_data() const
@@ -168,15 +167,15 @@ void gprs_rlcmac_tbf::set_ms_class(uint8_t ms_class_)
m_ms_class = ms_class_;
}
-uint8_t gprs_rlcmac_tbf::current_cs() const
+GprsCodingScheme gprs_rlcmac_tbf::current_cs() const
{
- uint8_t cs;
+ GprsCodingScheme cs;
if (direction == GPRS_RLCMAC_UL_TBF)
- cs = m_ms ? m_ms->current_cs_ul() : bts->bts_data()->initial_cs_ul;
+ cs = m_ms ? m_ms->current_cs_ul() : GprsCodingScheme();
else
- cs = m_ms ? m_ms->current_cs_dl() : bts->bts_data()->initial_cs_dl;
+ cs = m_ms ? m_ms->current_cs_dl() : GprsCodingScheme();
- return cs < 1 ? 1 : cs;
+ return cs;
}
gprs_llc_queue *gprs_rlcmac_tbf::llc_queue()
@@ -312,11 +311,23 @@ static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
void tbf_free(struct gprs_rlcmac_tbf *tbf)
{
+ /* update counters */
+ if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
+ tbf->bts->tbf_ul_freed();
+ if (tbf->state_is(GPRS_RLCMAC_FLOW))
+ tbf->bts->tbf_ul_aborted();
+ } else {
+ tbf->bts->tbf_dl_freed();
+ if (tbf->state_is(GPRS_RLCMAC_FLOW))
+ tbf->bts->tbf_dl_aborted();
+ }
+
/* Give final measurement report */
gprs_rlcmac_rssi_rep(tbf);
if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
- gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
- gprs_rlcmac_lost_rep(dl_tbf);
+ gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(tbf);
+
+ dl_tbf->abort();
dl_tbf->cleanup();
}
@@ -336,12 +347,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
tbf->stop_timer();
#warning "TODO: Could/Should generate bssgp_tx_llc_discarded"
tbf_unlink_pdch(tbf);
- llist_del(&tbf->list.list);
-
- if (tbf->direction == GPRS_RLCMAC_UL_TBF)
- tbf->bts->tbf_ul_freed();
- else
- tbf->bts->tbf_dl_freed();
+ llist_del(&tbf->list());
if (tbf->ms())
tbf->set_ms(NULL);
@@ -388,6 +394,7 @@ int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
const char *gprs_rlcmac_tbf::tbf_state_name[] = {
"NULL",
"ASSIGN",
+ "WAIT ASSIGN",
"FLOW",
"FINISHED",
"WAIT RELEASE",
@@ -429,10 +436,53 @@ void gprs_rlcmac_tbf::stop_timer()
}
}
+int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
+ uint32_t *poll_fn_, unsigned int *rrbp_)
+{
+ uint32_t fn_offs = 13;
+ uint32_t new_poll_fn = (fn + fn_offs) % 2715648;
+
+ if (!is_control_ts(ts)) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be "
+ "scheduled in this TS %d (first control TS %d)\n",
+ ts, control_ts);
+ return -EINVAL;
+ }
+ if (poll_state != GPRS_RLCMAC_POLL_NONE) {
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Polling is already scheduled for %s\n",
+ name());
+ return -EBUSY;
+ }
+ if (bts->sba()->find(trx->trx_no, ts, (fn + 13) % 2715648)) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s: Polling is already scheduled "
+ "for single block allocation at FN %d TS %d ...\n",
+ name(), new_poll_fn, ts);
+ return -EBUSY;
+ }
+
+ *poll_fn_ = new_poll_fn;
+ *rrbp_ = 0;
+
+ return 0;
+}
+
+void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts)
+{
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "%s: Scheduling polling at FN %d TS %d\n",
+ name(), new_poll_fn, ts);
+
+ /* schedule polling */
+ poll_state = GPRS_RLCMAC_POLL_SCHED;
+ poll_fn = new_poll_fn;
+ poll_ts = ts;
+}
+
void gprs_rlcmac_tbf::poll_timeout()
{
- LOGP(DRLCMAC, LOGL_NOTICE, "%s poll timeout for FN=%d (curr FN %d)\n",
- tbf_name(this), poll_fn, bts->current_frame_number());
+ LOGP(DRLCMAC, LOGL_NOTICE, "%s poll timeout for FN=%d, TS=%d (curr FN %d)\n",
+ tbf_name(this), poll_fn, poll_ts, bts->current_frame_number());
poll_state = GPRS_RLCMAC_POLL_NONE;
@@ -446,7 +496,7 @@ void gprs_rlcmac_tbf::poll_timeout()
ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
bts->rlc_ack_timedout();
if (state_is(GPRS_RLCMAC_FINISHED)) {
- gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
+ gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(this);
ul_tbf->m_n3103++;
if (ul_tbf->m_n3103 == ul_tbf->bts->bts_data()->n3103) {
LOGP(DRLCMAC, LOGL_NOTICE,
@@ -500,7 +550,7 @@ void gprs_rlcmac_tbf::poll_timeout()
/* reschedule DL assignment */
dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
} else if (direction == GPRS_RLCMAC_DL_TBF) {
- gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(this);
if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
@@ -546,11 +596,8 @@ static int setup_tbf(struct gprs_rlcmac_tbf *tbf,
bts = tbf->bts->bts_data();
- if (egprs_ms_class > 0 && bts->egprs_enabled) {
- /* TODO: only for 8PSK, otherwise the GPRS MS class has to be used */
+ if (ms->mode() == GprsCodingScheme::EGPRS)
ms_class = egprs_ms_class;
- tbf->enable_egprs();
- }
tbf->m_created_ts = time(NULL);
tbf->set_ms_class(ms_class);
@@ -587,7 +634,6 @@ gprs_rlcmac_ul_tbf::gprs_rlcmac_ul_tbf(BTS *bts_) :
m_contention_resolution_done(0),
m_final_ack_sent(0)
{
- memset(&m_window, 0, sizeof(m_window));
memset(&m_usf, 0, sizeof(m_usf));
}
@@ -597,6 +643,17 @@ static int ul_tbf_dtor(struct gprs_rlcmac_ul_tbf *tbf)
return 0;
}
+static void setup_egprs_mode(gprs_rlcmac_bts *bts, GprsMs *ms)
+{
+ if (GprsCodingScheme::getEgprsByNum(bts->max_mcs_ul).isEgprsGmsk() &&
+ GprsCodingScheme::getEgprsByNum(bts->max_mcs_dl).isEgprsGmsk() &&
+ ms->mode() != GprsCodingScheme::EGPRS)
+ {
+ ms->set_mode(GprsCodingScheme::EGPRS_GMSK);
+ } else {
+ ms->set_mode(GprsCodingScheme::EGPRS);
+ }
+}
struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
GprsMs *ms, int8_t use_trx,
@@ -605,6 +662,13 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_ul_tbf *tbf;
int rc;
+ if (egprs_ms_class == 0 && bts->egprs_enabled) {
+ LOGP(DRLCMAC, LOGL_NOTICE,
+ "Not accepting non-EGPRS phone in EGPRS-only mode\n");
+ bts->bts->tbf_failed_egprs_only();
+ return NULL;
+ }
+
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: MS_CLASS=%d/%d\n",
"UL", ms_class, egprs_ms_class);
@@ -620,6 +684,16 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
if (!ms)
ms = bts->bts->ms_alloc(ms_class, egprs_ms_class);
+ if (egprs_ms_class > 0 && bts->egprs_enabled) {
+ tbf->enable_egprs();
+ tbf->m_window.set_sns(RLC_EGPRS_SNS);
+ /* TODO: Allow bigger UL windows when CRBB encoding is supported */
+ tbf->m_window.set_ws(RLC_EGPRS_MIN_WS);
+ setup_egprs_mode(bts, ms);
+ LOGP(DRLCMAC, LOGL_INFO, "Enabled EGPRS for %s, mode %s\n",
+ tbf->name(), GprsCodingScheme::modeName(ms->mode()));
+ }
+
rc = setup_tbf(tbf, ms, use_trx, ms_class, egprs_ms_class, single_slot);
/* if no resource */
if (rc < 0) {
@@ -627,7 +701,7 @@ struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
return NULL;
}
- llist_add(&tbf->list.list, &bts->ul_tbfs);
+ llist_add(&tbf->list(), &bts->bts->ul_tbfs());
tbf->bts->tbf_ul_created();
return tbf;
@@ -650,7 +724,6 @@ gprs_rlcmac_dl_tbf::gprs_rlcmac_dl_tbf(BTS *bts_) :
m_last_dl_poll_fn(0),
m_last_dl_drained_fn(0)
{
- memset(&m_window, 0, sizeof(m_window));
memset(&m_llc_timer, 0, sizeof(m_llc_timer));
}
@@ -667,9 +740,19 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
+ if (egprs_ms_class == 0 && bts->egprs_enabled) {
+ if (ms_class > 0) {
+ LOGP(DRLCMAC, LOGL_NOTICE,
+ "Not accepting non-EGPRS phone in EGPRS-only mode\n");
+ bts->bts->tbf_failed_egprs_only();
+ return NULL;
+ }
+ egprs_ms_class = 1;
+ }
+
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
- LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: MS_CLASS=%d\n",
- "DL", ms_class);
+ LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: MS_CLASS=%d/%d\n",
+ "DL", ms_class, egprs_ms_class);
tbf = talloc(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
@@ -682,6 +765,14 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
if (!ms)
ms = bts->bts->ms_alloc(ms_class, egprs_ms_class);
+ if (egprs_ms_class > 0 && bts->egprs_enabled) {
+ tbf->enable_egprs();
+ tbf->m_window.set_sns(RLC_EGPRS_SNS);
+ setup_egprs_mode(bts, ms);
+ LOGP(DRLCMAC, LOGL_INFO, "Enabled EGPRS for %s, mode %s\n",
+ tbf->name(), GprsCodingScheme::modeName(ms->mode()));
+ }
+
rc = setup_tbf(tbf, ms, use_trx, ms_class, 0, single_slot);
/* if no resource */
if (rc < 0) {
@@ -689,7 +780,22 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
return NULL;
}
- llist_add(&tbf->list.list, &bts->dl_tbfs);
+ if (tbf->is_egprs_enabled()) {
+ unsigned int num_pdch = pcu_bitcount(tbf->dl_slots());
+ unsigned int ws = bts->ws_base + num_pdch * bts->ws_pdch;
+ ws = (ws / 32) * 32;
+ ws = OSMO_MAX(64, ws);
+ if (num_pdch == 1)
+ ws = OSMO_MIN(192, ws);
+ else
+ ws = OSMO_MIN(128 * num_pdch, ws);
+
+ LOGP(DRLCMAC, LOGL_INFO, "%s: Setting EGPRS window size to %d\n",
+ tbf->name(), ws);
+ tbf->m_window.set_ws(ws);
+ }
+
+ llist_add(&tbf->list(), &bts->bts->dl_tbfs());
tbf->bts->tbf_dl_created();
tbf->m_last_dl_poll_fn = -1;
@@ -719,6 +825,12 @@ void gprs_rlcmac_tbf::handle_timeout()
if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) {
if (state_is(GPRS_RLCMAC_ASSIGN)) {
LOGP(DRLCMAC, LOGL_NOTICE, "%s releasing due to "
+ "PACCH assignment timeout (not yet sent).\n",
+ tbf_name(this));
+ tbf_free(this);
+ return;
+ } else if (state_is(GPRS_RLCMAC_WAIT_ASSIGN)) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "%s releasing due to "
"PACCH assignment timeout.\n", tbf_name(this));
tbf_free(this);
return;
@@ -727,9 +839,9 @@ void gprs_rlcmac_tbf::handle_timeout()
"in assign state\n", tbf_name(this));
}
if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
- gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ gprs_rlcmac_dl_tbf *dl_tbf = as_dl_tbf(this);
dl_tbf->m_wait_confirm = 0;
- if (dl_tbf->state_is(GPRS_RLCMAC_ASSIGN)) {
+ if (dl_tbf->state_is(GPRS_RLCMAC_WAIT_ASSIGN)) {
tbf_assign_control_ts(dl_tbf);
if (!dl_tbf->upgrade_to_multislot) {
@@ -746,7 +858,6 @@ void gprs_rlcmac_tbf::handle_timeout()
/* keep to flags */
dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
- dl_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
dl_tbf->update();
@@ -794,36 +905,40 @@ int gprs_rlcmac_tbf::rlcmac_diag()
return 0;
}
-struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
+struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
{
struct msgb *msg;
struct gprs_rlcmac_dl_tbf *new_dl_tbf = NULL;
int poll_ass_dl = 1;
+ unsigned int rrbp = 0;
+ uint32_t new_poll_fn = 0;
+ int rc;
+ bool old_tfi_is_valid = is_tfi_assigned();
- if (direction == GPRS_RLCMAC_DL_TBF && control_ts != first_common_ts) {
+ if (direction == GPRS_RLCMAC_DL_TBF && !is_control_ts(ts)) {
LOGP(DRLCMAC, LOGL_NOTICE, "Cannot poll for downlink "
- "assigment, because MS cannot reply. (control TS=%d, "
- "first common TS=%d)\n", control_ts,
+ "assigment, because MS cannot reply. (TS=%d, "
+ "first common TS=%d)\n", ts,
first_common_ts);
poll_ass_dl = 0;
}
if (poll_ass_dl) {
- if (poll_state != GPRS_RLCMAC_POLL_NONE) {
- LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already sheduled "
- "for %s, so we must wait for downlink "
- "assignment...\n", tbf_name(this));
- return NULL;
- }
- if (bts->sba()->find(trx->trx_no, control_ts, (fn + 13) % 2715648)) {
+ if (poll_state == GPRS_RLCMAC_POLL_SCHED &&
+ ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK)
+ {
LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
- "scheduled for single block allocation...\n");
+ "scheduled for %s, so we must wait for the uplink "
+ "assignment...\n", tbf_name(this));
return NULL;
}
+ rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
+ if (rc < 0)
+ return NULL;
}
/* on uplink TBF we get the downlink TBF to be assigned. */
if (direction == GPRS_RLCMAC_UL_TBF) {
- gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
+ gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(this);
/* be sure to check first, if contention resolution is done,
* otherwise we cannot send the assignment yet */
@@ -846,6 +961,19 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
return NULL;
}
+ if (new_dl_tbf == as_dl_tbf(this))
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "New and old TBF are the same %s\n", name());
+
+ if (old_tfi_is_valid && !new_dl_tbf->is_tlli_valid()) {
+ LOGP(DRLCMACDL, LOGL_ERROR,
+ "The old TFI is not assigned and there is no "
+ "TLLI. Old TBF %s, new TBF %s\n",
+ name(), new_dl_tbf->name());
+ dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
+ return NULL;
+ }
+
new_dl_tbf->was_releasing = was_releasing;
msg = msgb_alloc(23, "rlcmac_dl_ass");
if (!msg)
@@ -859,9 +987,11 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
LOGP(DRLCMAC, LOGL_INFO, "%s start Packet Downlink Assignment (PACCH)\n", tbf_name(new_dl_tbf));
RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
- Encoding::write_packet_downlink_assignment(mac_control_block, m_tfi,
- (direction == GPRS_RLCMAC_DL_TBF), new_dl_tbf,
- poll_ass_dl, bts_data()->alpha, bts_data()->gamma, -1, 0);
+ Encoding::write_packet_downlink_assignment(mac_control_block,
+ old_tfi_is_valid, m_tfi, (direction == GPRS_RLCMAC_DL_TBF),
+ new_dl_tbf, poll_ass_dl, rrbp,
+ bts_data()->alpha, bts_data()->gamma, -1, 0,
+ is_egprs_enabled());
LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
LOGPC(DCSN1, LOGL_NOTICE, "\n");
@@ -871,12 +1001,13 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
talloc_free(mac_control_block);
if (poll_ass_dl) {
- poll_state = GPRS_RLCMAC_POLL_SCHED;
- poll_fn = (fn + 13) % 2715648;
+ set_polling(new_poll_fn, ts);
+ if (new_dl_tbf->state_is(GPRS_RLCMAC_ASSIGN))
+ new_dl_tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
LOGP(DRLCMACDL, LOGL_INFO,
- "%s Scheduled DL Assignment polling on FN=%d\n",
- name(), poll_fn);
+ "%s Scheduled DL Assignment polling on FN=%d, TS=%d\n",
+ name(), poll_fn, poll_ts);
} else {
dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
new_dl_tbf->set_state(GPRS_RLCMAC_FLOW);
@@ -889,22 +1020,25 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
return msg;
}
-struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
+struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn, uint8_t ts)
{
struct msgb *msg;
struct gprs_rlcmac_ul_tbf *new_tbf = NULL;
+ int rc;
+ unsigned int rrbp;
+ uint32_t new_poll_fn;
- if (poll_state != GPRS_RLCMAC_POLL_NONE) {
+ if (poll_state == GPRS_RLCMAC_POLL_SCHED &&
+ ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
- "sheduled for %s, so we must wait for uplink "
+ "scheduled for %s, so we must wait for the uplink "
"assignment...\n", tbf_name(this));
return NULL;
}
- if (bts->sba()->find(trx->trx_no, control_ts, (fn + 13) % 2715648)) {
- LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already scheduled for "
- "single block allocation...\n");
- return NULL;
- }
+
+ rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
+ if (rc < 0)
+ return NULL;
if (ms())
new_tbf = ms()->ul_tbf();
@@ -929,7 +1063,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
Encoding::write_packet_uplink_assignment(bts_data(), ass_vec, m_tfi,
(direction == GPRS_RLCMAC_DL_TBF), tlli(),
- is_tlli_valid(), new_tbf, 1, bts_data()->alpha,
+ is_tlli_valid(), new_tbf, 1, rrbp, bts_data()->alpha,
bts_data()->gamma, -1, is_egprs_enabled());
bitvec_pack(ass_vec, msgb_put(msg, 23));
RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
@@ -940,12 +1074,13 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
bitvec_free(ass_vec);
talloc_free(mac_control_block);
- poll_state = GPRS_RLCMAC_POLL_SCHED;
- poll_fn = (fn + 13) % 2715648;
+ set_polling(new_poll_fn, ts);
ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
+ if (new_tbf->state_is(GPRS_RLCMAC_ASSIGN))
+ new_tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
LOGP(DRLCMACDL, LOGL_INFO,
- "%s Scheduled UL Assignment polling on FN=%d\n",
- name(), poll_fn);
+ "%s Scheduled UL Assignment polling on FN=%d, TS=%d\n",
+ name(), poll_fn, poll_ts);
return msg;
}
@@ -1010,15 +1145,8 @@ int gprs_rlcmac_tbf::set_tlli_from_ul(uint32_t new_tlli)
if (!ms())
set_ms(old_ms);
-
- /* there might be an active and valid downlink TBF */
- if (!ms()->dl_tbf() && dl_tbf)
- /* Move it to the current MS (see the guard above) */
- dl_tbf->set_ms(ms());
}
- /* The TLLI has been taken from an UL message */
- update_ms(new_tlli, GPRS_RLCMAC_UL_TBF);
if (dl_tbf && dl_tbf->ms() != ms()) {
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still exists. "
@@ -1035,34 +1163,15 @@ int gprs_rlcmac_tbf::set_tlli_from_ul(uint32_t new_tlli)
tbf_free(ul_tbf);
ul_tbf = NULL;
}
- return 1;
-}
-
-int gprs_rlcmac_tbf::extract_tlli(const uint8_t *data, const size_t len)
-{
- struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
- uint32_t new_tlli;
- int rc;
-
- OSMO_ASSERT(direction == GPRS_RLCMAC_UL_TBF);
- /* no TLLI yet */
- if (!rh->ti) {
- LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TFI=%d without "
- "TLLI, but no TLLI received yet\n", rh->tfi);
- return 0;
- }
- rc = Decoding::tlli_from_ul_data(data, len, &new_tlli);
- if (rc) {
- bts->decode_error();
- LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
- "of UL DATA TFI=%d.\n", rh->tfi);
- return 0;
- }
- LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of "
- "UL DATA TFI=%d.\n", new_tlli, rh->tfi);
+ /* The TLLI has been taken from an UL message */
+ update_ms(new_tlli, GPRS_RLCMAC_UL_TBF);
- return set_tlli_from_ul(new_tlli);
+#if 0 /* REMOVEME ??? */
+ if (ms()->need_dl_tbf())
+ establish_dl_tbf_on_pacch();
+#endif
+ return 1;
}
const char *tbf_name(gprs_rlcmac_tbf *tbf)
@@ -1088,11 +1197,11 @@ const char *gprs_rlcmac_tbf::name() const
void gprs_rlcmac_tbf::rotate_in_list()
{
- llist_del(&list.list);
+ llist_del(&list());
if (direction == GPRS_RLCMAC_UL_TBF)
- llist_add(&list.list, &bts->bts_data()->ul_tbfs);
+ llist_add(&list(), &bts->ul_tbfs());
else
- llist_add(&list.list, &bts->bts_data()->dl_tbfs);
+ llist_add(&list(), &bts->dl_tbfs());
}
uint8_t gprs_rlcmac_tbf::tsc() const
@@ -1136,24 +1245,7 @@ uint8_t gprs_rlcmac_tbf::ul_slots() const
return slots;
}
-void tbf_print_vty_info(struct vty *vty, struct llist_head *ltbf)
+bool gprs_rlcmac_tbf::is_control_ts(uint8_t ts) const
{
- gprs_rlcmac_tbf *tbf = llist_pods_entry(ltbf, gprs_rlcmac_tbf);
-
- vty_out(vty, "TBF: TFI=%d TLLI=0x%08x (%s) DIR=%s IMSI=%s%s", tbf->tfi(),
- tbf->tlli(), tbf->is_tlli_valid() ? "valid" : "invalid",
- tbf->direction == GPRS_RLCMAC_UL_TBF ? "UL" : "DL",
- tbf->imsi(), VTY_NEWLINE);
- vty_out(vty, " created=%lu state=%08x 1st_TS=%d 1st_cTS=%d ctrl_TS=%d "
- "MS_CLASS=%d%s",
- tbf->created_ts(), tbf->state_flags, tbf->first_ts,
- tbf->first_common_ts, tbf->control_ts, tbf->ms_class(),
- VTY_NEWLINE);
- vty_out(vty, " TS_alloc=");
- for (int i = 0; i < 8; i++) {
- if (tbf->pdch[i])
- vty_out(vty, "%d ", i);
- }
- vty_out(vty, " CS=%d%s%s", tbf->ms() ? tbf->ms()->current_cs_dl() : 1,
- VTY_NEWLINE, VTY_NEWLINE);
+ return ts == control_ts;
}
diff --git a/src/tbf.h b/src/tbf.h
index a3a2eeb..ad8ad4c 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -43,7 +43,8 @@ class GprsMs;
enum gprs_rlcmac_tbf_state {
GPRS_RLCMAC_NULL = 0, /* new created TBF */
- GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
+ GPRS_RLCMAC_ASSIGN, /* wait for DL transmission */
+ GPRS_RLCMAC_WAIT_ASSIGN,/* wait for confirmation */
GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
@@ -88,28 +89,6 @@ enum gprs_rlcmac_tbf_direction {
#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
-struct llist_pods {
- struct llist_head list;
- void *back;
-};
-
-#define llist_pods_entry(ptr, type) \
- ((type *)(container_of(ptr, struct llist_pods, list)->back))
-
-/**
- * llist_pods_for_each_entry - like llist_for_each_entry, but uses
- * struct llist_pods ->back to access the entry.
- * This is necessary for non-PODS classes because container_of is
- * not guaranteed to work anymore. */
-#define llist_pods_for_each_entry(pos, head, member, lpods) \
- for (lpods = llist_entry((head)->next, typeof(struct llist_pods), list), \
- pos = ((typeof(pos))lpods->back), \
- prefetch(pos->member.list.next); \
- &lpods->list != (head); \
- lpods = llist_entry(lpods->list.next, typeof(struct llist_pods), list), \
- pos = ((typeof(pos))lpods->back),\
- prefetch(pos->member.list.next))
-
struct gprs_rlcmac_tbf {
gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
@@ -123,12 +102,14 @@ struct gprs_rlcmac_tbf {
const char *name() const;
- struct msgb *create_dl_ass(uint32_t fn);
- struct msgb *create_ul_ass(uint32_t fn);
+ struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
+ struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
GprsMs *ms() const;
void set_ms(GprsMs *ms);
+ gprs_rlc_window *window();
+
uint8_t tsc() const;
int rlcmac_diag();
@@ -139,6 +120,9 @@ struct gprs_rlcmac_tbf {
void stop_t3191();
int establish_dl_tbf_on_pacch();
+ int check_polling(uint32_t fn, uint8_t ts,
+ uint32_t *poll_fn, unsigned int *rrbp);
+ void set_polling(uint32_t poll_fn, uint8_t ts);
void poll_timeout();
/** tlli handling */
@@ -149,6 +133,7 @@ struct gprs_rlcmac_tbf {
void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
uint8_t tfi() const;
+ bool is_tfi_assigned() const;
const char *imsi() const;
void assign_imsi(const char *imsi);
@@ -156,7 +141,7 @@ struct gprs_rlcmac_tbf {
void set_ta(uint8_t);
uint8_t ms_class() const;
void set_ms_class(uint8_t);
- uint8_t current_cs() const;
+ GprsCodingScheme current_cs() const;
gprs_llc_queue *llc_queue();
const gprs_llc_queue *llc_queue() const;
@@ -164,6 +149,8 @@ struct gprs_rlcmac_tbf {
uint8_t dl_slots() const;
uint8_t ul_slots() const;
+ bool is_control_ts(uint8_t ts) const;
+
/* EGPRS */
bool is_egprs_enabled() const;
void enable_egprs();
@@ -175,7 +162,9 @@ struct gprs_rlcmac_tbf {
LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
- struct llist_pods list;
+ LListHead<gprs_rlcmac_tbf>& list();
+ const LListHead<gprs_rlcmac_tbf>& list() const;
+
uint32_t state_flags;
enum gprs_rlcmac_tbf_direction direction;
struct gprs_rlcmac_trx *trx;
@@ -193,6 +182,7 @@ struct gprs_rlcmac_tbf {
enum gprs_rlcmac_tbf_poll_state poll_state;
uint32_t poll_fn; /* frame number to poll */
+ uint8_t poll_ts; /* TS to poll */
gprs_rlc m_rlc;
@@ -238,11 +228,10 @@ struct gprs_rlcmac_tbf {
protected:
gprs_rlcmac_bts *bts_data() const;
- int extract_tlli(const uint8_t *data, const size_t len);
int set_tlli_from_ul(uint32_t new_tlli);
void merge_and_clear_ms(GprsMs *old_ms);
- static const char *tbf_state_name[6];
+ static const char *tbf_state_name[7];
class GprsMs *m_ms;
@@ -251,6 +240,7 @@ protected:
uint8_t m_ms_class;
private:
+ LListHead<gprs_rlcmac_tbf> m_list;
LListHead<gprs_rlcmac_tbf> m_ms_list;
bool m_egprs_enabled;
@@ -302,6 +292,16 @@ inline void gprs_rlcmac_tbf::set_state(enum gprs_rlcmac_tbf_state new_state)
state = new_state;
}
+inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
+{
+ return this->m_list;
+}
+
+inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
+{
+ return this->m_list;
+}
+
inline GprsMs *gprs_rlcmac_tbf::ms() const
{
return m_ms;
@@ -312,6 +312,13 @@ inline bool gprs_rlcmac_tbf::is_tlli_valid() const
return tlli() != 0;
}
+inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
+{
+ /* The TBF is established or has been assigned by a IMM.ASS for
+ * download */
+ return state > GPRS_RLCMAC_ASSIGN;
+}
+
inline uint8_t gprs_rlcmac_tbf::tfi() const
{
return m_tfi;
@@ -354,6 +361,7 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
const uint8_t *data, const uint16_t len);
int rcvd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb);
+ int rcvd_dl_ack(uint8_t final_ack, unsigned first_bsn, struct bitvec *rbb);
struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
void request_dl_ack();
bool need_control_ts() const;
@@ -362,11 +370,7 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
int frames_since_last_drain(unsigned fn) const;
bool keep_open(unsigned fn) const;
int release();
- void enable_egprs();
-
- bool is_control_ts(uint8_t ts) const {
- return ts == control_ts;
- }
+ int abort();
/* TODO: add the gettimeofday as parameter */
struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
@@ -402,10 +406,14 @@ protected:
unsigned lost_bytes;
};
- struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
+ int take_next_bsn(uint32_t fn, int previous_bsn,
+ bool *may_combine);
+ bool restart_bsn_cycle();
+ int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
- const int index);
+ int index, int index2 = -1);
int update_window(const uint8_t ssn, const uint8_t *rbb);
+ int update_window(unsigned first_bsn, const struct bitvec *rbb);
int maybe_start_new_window();
bool dl_window_stalled() const;
void reuse_tbf();
@@ -419,12 +427,12 @@ protected:
struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
gprs_rlcmac_ul_tbf(BTS *bts);
- struct msgb *create_ul_ack(uint32_t fn);
+ struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
/* blocks were acked */
int rcv_data_block_acknowledged(
- const struct gprs_rlc_ul_header_egprs *rlc,
- uint8_t *data, uint8_t len, struct pcu_l1_meas *meas);
+ const struct gprs_rlc_data_info *rlc,
+ uint8_t *data, struct pcu_l1_meas *meas);
/* TODO: extract LLC class? */
@@ -444,7 +452,7 @@ struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
uint8_t m_final_ack_sent; /* set if we sent final ack */
protected:
- void maybe_schedule_uplink_acknack(const gprs_rlc_ul_header_egprs *rlc);
+ void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
};
inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
@@ -452,15 +460,31 @@ inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir
return (enum gprs_rlcmac_tbf_direction)
((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
}
-#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/vty.h>
+inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
+{
+ if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
+ return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ else
+ return NULL;
+}
- void tbf_print_vty_info(struct vty *vty, struct llist_head *tbf);
-#ifdef __cplusplus
+inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
+{
+ if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
+ return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
+ else
+ return NULL;
}
+
+inline gprs_rlc_window *gprs_rlcmac_tbf::window()
+{
+ switch (direction)
+ {
+ case GPRS_RLCMAC_UL_TBF: return &as_ul_tbf(this)->m_window;
+ case GPRS_RLCMAC_DL_TBF: return &as_dl_tbf(this)->m_window;
+ }
+ return NULL;
+}
+
#endif
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 70194f7..7540d1b 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -27,6 +27,7 @@
#include <gprs_bssgp_pcu.h>
#include <gprs_codel.h>
#include <decoding.h>
+#include <encoding.h>
#include "pcu_utils.h"
@@ -180,7 +181,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
*/
int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts,
const uint32_t tlli, const uint32_t tlli_old, const char *imsi,
- const uint8_t ms_class, const uint8_t egprs_ms_class,
+ uint8_t ms_class, uint8_t egprs_ms_class,
const uint16_t delay_csec,
const uint8_t *data, const uint16_t len)
{
@@ -190,9 +191,16 @@ int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts,
/* check for existing TBF */
ms = bts->bts->ms_store().get_ms(tlli, tlli_old, imsi);
- if (ms)
+ if (ms) {
dl_tbf = ms->dl_tbf();
+ /* If we known the GPRS/EGPRS MS class, use it */
+ if (ms->ms_class() || ms->egprs_ms_class()) {
+ ms_class = ms->ms_class();
+ egprs_ms_class = ms->egprs_ms_class();
+ }
+ }
+
if (ms && strlen(ms->imsi()) == 0) {
ms_old = bts->bts->ms_store().get_ms(0, 0, imsi);
if (ms_old && ms_old != ms) {
@@ -318,81 +326,139 @@ drop_frame:
return msg;
}
-/*
- * Create DL data block
- * The messages are fragmented and forwarded as data blocks.
- */
-struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
+bool gprs_rlcmac_dl_tbf::restart_bsn_cycle()
{
- LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. "
- "V(S)==%d)\n", tbf_name(this),
- m_window.v_a(), m_window.v_s());
+ /* If V(S) == V(A) and finished state, we would have received
+ * acknowledgement of all transmitted block. In this case we would
+ * have transmitted the final block, and received ack from MS. But in
+ * this case we did not receive the final ack indication from MS. This
+ * should never happen if MS works correctly.
+ */
+ if (m_window.window_empty()) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks\n");
+ return false;
+ }
-do_resend:
- /* check if there is a block with negative acknowledgement */
- int resend_bsn = m_window.resend_needed();
- if (resend_bsn >= 0) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn);
- /* re-send block with negative aknowlegement */
- m_window.m_v_b.mark_unacked(resend_bsn);
- bts->rlc_resent();
- return create_dl_acked_block(fn, ts, resend_bsn);
+ /* cycle through all unacked blocks */
+ int resend = m_window.mark_for_resend();
+
+ /* At this point there should be at least one unacked block
+ * to be resent. If not, this is an software error. */
+ if (resend == 0) {
+ LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
+ "There are no unacknowledged blocks, but V(A) "
+ " != V(S). PLEASE FIX!\n");
+ return false;
}
- /* if the window has stalled, or transfer is complete,
- * send an unacknowledged block */
- if (state_is(GPRS_RLCMAC_FINISHED)) {
+ return true;
+}
+
+int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn,
+ int previous_bsn, bool *may_combine)
+{
+ int bsn;
+ int data_len2, force_data_len = -1;
+ GprsCodingScheme cs2;
+ GprsCodingScheme force_cs;
+
+ bsn = m_window.resend_needed();
+
+ if (previous_bsn >= 0) {
+ force_cs = m_rlc.block(previous_bsn)->cs;
+ if (!force_cs.isEgprs())
+ return -1;
+ force_data_len = m_rlc.block(previous_bsn)->len;
+ }
+
+ if (bsn >= 0) {
+ if (previous_bsn == bsn)
+ return -1;
+
+ if (previous_bsn >= 0 &&
+ m_window.mod_sns(bsn - previous_bsn) > RLC_EGPRS_MAX_BSN_DELTA)
+ return -1;
+
+ cs2 = m_rlc.block(bsn)->cs;
+ data_len2 = m_rlc.block(bsn)->len;
+ if (force_data_len > 0 && force_data_len != data_len2)
+ return -1;
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", bsn);
+ /* re-send block with negative aknowlegement */
+ m_window.m_v_b.mark_unacked(bsn);
+ bts->rlc_resent();
+ } else if (state_is(GPRS_RLCMAC_FINISHED)) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
"because all blocks have been transmitted.\n",
m_window.v_a());
bts->rlc_restarted();
+ if (restart_bsn_cycle())
+ return take_next_bsn(fn, previous_bsn, may_combine);
} else if (dl_window_stalled()) {
LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
- "because all window is stalled.\n",
+ "because the window is stalled.\n",
m_window.v_a());
bts->rlc_stalled();
+ if (restart_bsn_cycle())
+ return take_next_bsn(fn, previous_bsn, may_combine);
} else if (have_data()) {
/* New blocks may be send */
- return create_new_bsn(fn, ts);
+ cs2 = force_cs ? force_cs : current_cs();
+ LOGP(DRLCMACDL, LOGL_DEBUG,
+ "- Sending new block at BSN %d, CS=%s\n",
+ m_window.v_s(), cs2.name());
+
+ bsn = create_new_bsn(fn, cs2);
} else if (!m_window.window_empty()) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
"because all blocks have been transmitted (FLOW).\n",
m_window.v_a());
bts->rlc_restarted();
+ if (restart_bsn_cycle())
+ return take_next_bsn(fn, previous_bsn, may_combine);
} else {
/* Nothing left to send, create dummy LLC commands */
- return create_new_bsn(fn, ts);
+ LOGP(DRLCMACDL, LOGL_DEBUG,
+ "- Sending new dummy block at BSN %d, CS=%s\n",
+ m_window.v_s(), current_cs().name());
+ bsn = create_new_bsn(fn, current_cs());
+ /* Don't send a second block, so don't set cs2 */
}
- /* If V(S) == V(A) and finished state, we would have received
- * acknowledgement of all transmitted block. In this case we
- * would have transmitted the final block, and received ack
- * from MS. But in this case we did not receive the final ack
- * indication from MS. This should never happen if MS works
- * correctly. */
- if (m_window.window_empty()) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, "
- "so we re-transmit final block!\n");
+ if (bsn < 0) {
/* we just send final block again */
- int16_t index = m_window.v_s_mod(-1);
+ LOGP(DRLCMACDL, LOGL_DEBUG,
+ "- Nothing else to send, Re-transmit final block!\n");
+ bsn = m_window.v_s_mod(-1);
bts->rlc_resent();
- return create_dl_acked_block(fn, ts, index);
}
- /* cycle through all unacked blocks */
- int resend = m_window.mark_for_resend();
+ *may_combine = cs2.numDataBlocks() > 1;
- /* At this point there should be at least one unacked block
- * to be resent. If not, this is an software error. */
- if (resend == 0) {
- LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
- "There are no unacknowledged blocks, but V(A) "
- " != V(S). PLEASE FIX!\n");
- /* we just send final block again */
- int16_t index = m_window.v_s_mod(-1);
- return create_dl_acked_block(fn, ts, index);
- }
- goto do_resend;
+ return bsn;
+}
+
+/*
+ * Create DL data block
+ * The messages are fragmented and forwarded as data blocks.
+ */
+struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
+{
+ int bsn, bsn2 = -1;
+ bool may_combine;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. "
+ "V(S)==%d)\n", tbf_name(this),
+ m_window.v_a(), m_window.v_s());
+
+ bsn = take_next_bsn(fn, -1, &may_combine);
+ if (bsn < 0)
+ return NULL;
+
+ if (may_combine)
+ bsn2 = take_next_bsn(fn, bsn, &may_combine);
+
+ return create_dl_acked_block(fn, ts, bsn, bsn2);
}
void gprs_rlcmac_dl_tbf::schedule_next_frame()
@@ -417,55 +483,43 @@ void gprs_rlcmac_dl_tbf::schedule_next_frame()
m_last_dl_drained_fn = -1;
}
-struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts)
+int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, GprsCodingScheme cs)
{
- struct rlc_dl_header *rh;
- struct rlc_li_field *li;
- uint8_t *delimiter, *data, *e_pointer;
- uint16_t space, chunk;
+ uint8_t *data;
gprs_rlc_data *rlc_data;
const uint16_t bsn = m_window.v_s();
- uint8_t cs_n = 1;
+ gprs_rlc_data_block_info *rdbi;
+ int num_chunks = 0;
+ int write_offset = 0;
+ Encoding::AppendResult ar;
if (m_llc.frame_length() == 0)
schedule_next_frame();
- cs_n = current_cs();
-
- LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d, CS=%d\n",
- m_window.v_s(), cs_n);
+ OSMO_ASSERT(cs.isValid());
- OSMO_ASSERT(cs_n >= 1);
- OSMO_ASSERT(cs_n <= 4);
-
- /* TODO: Use GprsCodingScheme everywhere and remove cast */
- GprsCodingScheme cs((GprsCodingScheme::Scheme)cs_n);
-
- /* total length of block, including spare bits */
- const uint8_t block_length = cs.sizeDL();
- /* length of usable data of block, w/o spare bits, inc. MAC */
- const uint8_t block_data_len = cs.maxBytesDL();
+ /* length of usable data block (single data unit w/o header) */
+ const uint8_t block_data_len = cs.maxDataBlockBytes();
/* now we still have untransmitted LLC data, so we fill mac block */
rlc_data = m_rlc.block(bsn);
data = rlc_data->prepare(block_data_len);
rlc_data->cs = cs;
+ rlc_data->len = block_data_len;
+
+ rdbi = &(rlc_data->block_info);
+ memset(rdbi, 0, sizeof(*rdbi));
+ rdbi->data_len = block_data_len;
+
+ rdbi->cv = 15; /* Final Block Indicator, set late, if true */
+ rdbi->bsn = bsn; /* Block Sequence Number */
+ rdbi->e = 1; /* Extension bit, maybe set later (1: no extension) */
+
+ do {
+ bool is_final;
- rh = (struct rlc_dl_header *)data;
- rh->pt = 0; /* Data Block */
- rh->rrbp = rh->s_p = 0; /* Polling, set later, if required */
- rh->usf = 7; /* will be set at scheduler */
- rh->pr = 0; /* FIXME: power reduction */
- rh->tfi = m_tfi; /* TFI */
- rh->fbi = 0; /* Final Block Indicator, set late, if true */
- rh->bsn = bsn; /* Block Sequence Number */
- rh->e = 0; /* Extension bit, maybe set later */
- e_pointer = data + 2; /* points to E of current chunk */
- data += sizeof(*rh);
- delimiter = data; /* where next length header would be stored */
- space = block_data_len - sizeof(*rh);
- while (1) {
if (m_llc.frame_length() == 0) {
+ int space = block_data_len - write_offset;
/* A header will need to by added, so we just need
* space-1 octets */
m_llc.put_dummy_frame(space - 1);
@@ -485,141 +539,145 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
m_llc.frame_length(), frames_since_last_drain(fn));
}
- chunk = m_llc.chunk_size();
-
- /* if chunk will exceed block limit */
- if (chunk > space) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "larger than space (%d) left in block: copy "
- "only remaining space, and we are done\n",
- chunk, space);
- /* block is filled, so there is no extension */
- *e_pointer |= 0x01;
- /* fill only space */
- m_llc.consume(data, space);
- /* return data block as message */
- break;
- }
- /* if FINAL chunk would fit precisely in space left */
- if (chunk == space && llc_queue()->size() == 0 && !keep_open(fn))
- {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "would exactly fit into space (%d): because "
- "this is a final block, we don't add length "
- "header, and we are done\n", chunk, space);
- LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
- "%s that fits precisely in last block: "
- "len=%d\n", tbf_name(this), m_llc.frame_length());
- gprs_rlcmac_dl_bw(this, m_llc.frame_length());
- /* block is filled, so there is no extension */
- *e_pointer |= 0x01;
- /* fill space */
- m_llc.consume(data, space);
- m_llc.reset();
- /* final block */
- rh->fbi = 1; /* we indicate final block */
- request_dl_ack();
- set_state(GPRS_RLCMAC_FINISHED);
- /* return data block as message */
- break;
- }
- /* if chunk would fit exactly in space left */
- if (chunk == space) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
- "would exactly fit into space (%d): add length "
- "header with LI=0, to make frame extend to "
- "next block, and we are done\n", chunk, space);
- /* make space for delimiter */
- if (delimiter != data)
- memmove(delimiter + 1, delimiter,
- data - delimiter);
- data++;
- space--;
- /* add LI with 0 length */
- li = (struct rlc_li_field *)delimiter;
- li->e = 1; /* not more extension */
- li->m = 0; /* shall be set to 0, in case of li = 0 */
- li->li = 0; /* chunk fills the complete space */
- // no need to set e_pointer nor increase delimiter
- /* fill only space, which is 1 octet less than chunk */
- m_llc.consume(data, space);
- /* return data block as message */
+ is_final = llc_queue()->size() == 0 && !keep_open(fn);
+
+ ar = Encoding::rlc_data_to_dl_append(rdbi, cs,
+ &m_llc, &write_offset, &num_chunks, data, is_final);
+
+ if (ar == Encoding::AR_NEED_MORE_BLOCKS)
break;
- }
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d is less "
- "than remaining space (%d): add length header to "
- "to delimit LLC frame\n", chunk, space);
- /* the LLC frame chunk ends in this block */
- /* make space for delimiter */
- if (delimiter != data)
- memmove(delimiter + 1, delimiter, data - delimiter);
- data++;
- space--;
- /* add LI to delimit frame */
- li = (struct rlc_li_field *)delimiter;
- li->e = 0; /* Extension bit, maybe set later */
- li->m = 0; /* will be set later, if there is more LLC data */
- li->li = chunk; /* length of chunk */
- e_pointer = delimiter; /* points to E of current delimiter */
- delimiter++;
- /* copy (rest of) LLC frame to space and reset later */
- m_llc.consume(data, chunk);
- data += chunk;
- space -= chunk;
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for %s"
"len=%d\n", tbf_name(this), m_llc.frame_length());
gprs_rlcmac_dl_bw(this, m_llc.frame_length());
m_llc.reset();
- /* dequeue next LLC frame, if any */
- schedule_next_frame();
- /* if we have more data and we have space left */
- if (space > 0 && (m_llc.frame_length() || keep_open(fn))) {
- li->m = 1; /* we indicate more frames to follow */
- continue;
- }
- /* if we don't have more LLC frames */
- if (!m_llc.frame_length() && !keep_open(fn)) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
- "done.\n");
- li->e = 1; /* we cannot extend */
- rh->fbi = 1; /* we indicate final block */
+ if (is_final) {
request_dl_ack();
set_state(GPRS_RLCMAC_FINISHED);
- break;
}
- /* we have no space left */
- LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "
- "done.\n");
- li->e = 1; /* we cannot extend */
- break;
- }
- LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n",
- osmo_hexdump(rlc_data->block, block_length));
-#warning "move this up?"
- rlc_data->len = block_length;
+
+ /* dequeue next LLC frame, if any */
+ schedule_next_frame();
+ } while (ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "data block (BSN %d, %s): %s\n",
+ bsn, rlc_data->cs.name(),
+ osmo_hexdump(rlc_data->block, block_data_len));
/* raise send state and set ack state array */
m_window.m_v_b.mark_unacked(bsn);
m_window.increment_send();
- return create_dl_acked_block(fn, ts, bsn);
+ return bsn;
}
struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
const uint32_t fn, const uint8_t ts,
- const int index)
+ int index, int index2)
{
- uint8_t *data;
- struct rlc_dl_header *rh;
+ uint8_t *msg_data;
struct msgb *dl_msg;
- uint8_t len;
+ unsigned msg_len;
bool need_poll;
+ /* TODO: support MCS-7 - MCS-9, where data_block_idx can be 1 */
+ unsigned int data_block_idx = 0;
+ unsigned int rrbp;
+ uint32_t new_poll_fn;
+ int rc;
+ bool is_final = false;
+ gprs_rlc_data_info rlc;
+ GprsCodingScheme cs;
+ int bsns[ARRAY_SIZE(rlc.block_info)];
+ unsigned num_bsns;
+ int punct[ARRAY_SIZE(rlc.block_info)];
+ bool need_padding = false;
+
+ /*
+ * TODO: This is an experimental work-around to put 2 BSN into
+ * MSC-7 to MCS-9 encoded messages. It just sends the same BSN
+ * twice in the block. The cs should be derived from the TBF's
+ * current CS such that both BSNs (that must be compatible) can
+ * be put into the data area, even if the resulting CS is higher than
+ * the current limit.
+ */
+ cs = m_rlc.block(index)->cs;
+ bsns[0] = index;
+ num_bsns = 1;
+
+ if (index2 >= 0) {
+ bsns[num_bsns] = index2;
+ num_bsns += 1;
+ }
+
+ if (num_bsns == 1) {
+ /* TODO: remove the conditional when MCS-6 padding isn't
+ * failing to be decoded by MEs anymore */
+ if (cs != GprsCodingScheme(GprsCodingScheme::MCS8))
+ cs.decToSingleBlock(&need_padding);
+ }
- /* get data and header from current block */
- data = m_rlc.block(index)->block;
- len = m_rlc.block(index)->len;
- rh = (struct rlc_dl_header *)data;
+ gprs_rlc_data_info_init_dl(&rlc, cs, need_padding);
+
+ rlc.usf = 7; /* will be set at scheduler */
+ rlc.pr = 0; /* FIXME: power reduction */
+ rlc.tfi = m_tfi; /* TFI */
+
+ /* return data block(s) as message */
+ msg_len = cs.sizeDL();
+ dl_msg = msgb_alloc(msg_len, "rlcmac_dl_data");
+ if (!dl_msg)
+ return NULL;
+
+ msg_data = msgb_put(dl_msg, msg_len);
+
+ /* Copy block(s) to RLC message */
+ for (data_block_idx = 0; data_block_idx < rlc.num_data_blocks;
+ data_block_idx++)
+ {
+ int bsn;
+ GprsCodingScheme cs_enc;
+ uint8_t *block_data;
+ gprs_rlc_data_block_info *rdbi, *block_info;
+
+ /* Check if there are more blocks than BSNs */
+ if (data_block_idx < num_bsns)
+ bsn = bsns[data_block_idx];
+ else
+ bsn = bsns[0];
+
+ cs_enc = m_rlc.block(bsn)->cs;
+
+ /* get data and header from current block */
+ block_data = m_rlc.block(bsn)->block;
+
+ /* TODO: Use real puncturing values */
+ punct[data_block_idx] = data_block_idx;
+
+ rdbi = &rlc.block_info[data_block_idx];
+ block_info = &m_rlc.block(bsn)->block_info;
+
+ if(rdbi->data_len != m_rlc.block(bsn)->len) {
+ LOGP(DRLCMACDL, LOGL_ERROR,
+ "ERROR: Expected len = %d for %s instead of "
+ "%d in data unit %d (BSN %d, %s)\n",
+ rdbi->data_len, cs.name(), m_rlc.block(bsn)->len,
+ data_block_idx, bsn, cs_enc.name());
+ OSMO_ASSERT(rdbi->data_len == m_rlc.block(bsn)->len);
+ }
+ rdbi->e = block_info->e;
+ rdbi->cv = block_info->cv;
+ rdbi->bsn = bsn;
+ is_final = is_final || rdbi->cv == 0;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- Copying data unit %d (BSN %d)\n",
+ data_block_idx, bsn);
+
+ Encoding::rlc_copy_from_aligned_buffer(&rlc, data_block_idx,
+ msg_data, block_data);
+ }
+
+ OSMO_ASSERT(ARRAY_SIZE(punct) >= 2);
+ rlc.cps = gprs_rlc_mcs_cps(cs, punct[0], punct[1], need_padding);
/* If the TBF has just started, relate frames_since_last_poll to the
* current fn */
@@ -627,9 +685,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
m_last_dl_poll_fn = fn;
need_poll = state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
- /* Clear Polling, if still set in history buffer */
- rh->s_p = 0;
-
+
/* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
*/
if (m_tx_counter >= POLL_ACK_AFTER_FRAMES || m_dl_ack_requested ||
@@ -646,31 +702,18 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
"polling, because %d blocks sent.\n",
POLL_ACK_AFTER_FRAMES);
}
- /* scheduling not possible, because: */
- if (poll_state != GPRS_RLCMAC_POLL_NONE)
- LOGP(DRLCMACDL, LOGL_DEBUG, "Polling is already "
- "sheduled for %s, so we must wait for "
- "requesting downlink ack\n", tbf_name(this));
- else if (control_ts != ts)
- LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
- "sheduled in this TS %d, waiting for "
- "TS %d\n", ts, control_ts);
- else if (bts->sba()->find(trx->trx_no, ts, (fn + 13) % 2715648))
- LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
- "sheduled, because single block alllocation "
- "already exists\n");
- else {
- LOGP(DRLCMACDL, LOGL_DEBUG, "Polling sheduled in this "
+
+ rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
+ if (rc >= 0) {
+ set_polling(new_poll_fn, ts);
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "Polling scheduled in this "
"TS %d\n", ts);
m_tx_counter = 0;
/* start timer whenever we send the final block */
- if (rh->fbi == 1)
+ if (is_final)
tbf_timer_start(this, 3191, bts_data()->t3191, 0);
- /* schedule polling */
- poll_state = GPRS_RLCMAC_POLL_SCHED;
- poll_fn = (fn + 13) % 2715648;
-
/* Clear poll timeout flag */
state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
@@ -678,34 +721,35 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
m_dl_ack_requested = false;
/* set polling in header */
- rh->rrbp = 0; /* N+13 */
- rh->s_p = 1; /* Polling */
+ rlc.rrbp = rrbp;
+ rlc.es_p = 1; /* Polling */
m_last_dl_poll_fn = poll_fn;
LOGP(DRLCMACDL, LOGL_INFO,
"%s Scheduled Ack/Nack polling on FN=%d, TS=%d\n",
- name(), poll_fn, ts);
+ name(), poll_fn, poll_ts);
}
}
- /* return data block as message */
- dl_msg = msgb_alloc(len, "rlcmac_dl_data");
- if (!dl_msg)
- return NULL;
+ Encoding::rlc_write_dl_data_header(&rlc, msg_data);
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "msg block (BSN %d, %s%s): %s\n",
+ index, cs.name(),
+ need_padding ? ", padded" : "",
+ msgb_hexdump(dl_msg));
/* Increment TX-counter */
m_tx_counter++;
- memcpy(msgb_put(dl_msg, len), data, len);
bts->rlc_sent();
return dl_msg;
}
-static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns)
+static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn)
{
- return (ssn - 1 - bitnum) & mod_sns;
+ return ssn - 1 - bitnum;
}
int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
@@ -713,20 +757,24 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
{
gprs_rlc_data *rlc_data;
uint16_t lost = 0, received = 0, skipped = 0;
- char info[65];
- memset(info, '.', sizeof(info));
- info[64] = 0;
+ char info[RLC_MAX_WS + 1];
+ memset(info, '.', m_window.ws());
+ info[m_window.ws()] = 0;
uint16_t bsn = 0;
unsigned received_bytes = 0, lost_bytes = 0;
unsigned received_packets = 0, lost_packets = 0;
+ unsigned num_blocks = strlen(show_rbb);
/* SSN - 1 is in range V(A)..V(S)-1 */
- for (int bitpos = 0; bitpos < m_window.ws(); bitpos++) {
- bool is_received = show_rbb[m_window.ws() - 1 - bitpos] == 'R';
+ for (unsigned int bitpos = 0; bitpos < num_blocks; bitpos++) {
+ bool is_received;
+ int index = num_blocks - 1 - bitpos;
- bsn = bitnum_to_bsn(bitpos, ssn, m_window.mod_sns());
+ is_received = (index >= 0 && show_rbb[index] == 'R');
- if (bsn == ((m_window.v_a() - 1) & m_window.mod_sns())) {
+ bsn = m_window.mod_sns(bitnum_to_bsn(bitpos, ssn));
+
+ if (bsn == m_window.mod_sns(m_window.v_a() - 1)) {
info[bitpos] = '$';
break;
}
@@ -748,8 +796,7 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
/* Get statistics for current CS */
- /* TODO: Use GprsCodingScheme everywhere and remove cast */
- if (rlc_data->cs != (GprsCodingScheme::Scheme)current_cs()) {
+ if (rlc_data->cs != current_cs()) {
/* This block has already been encoded with a different
* CS, so it doesn't help us to decide, whether the
* current CS is ok. Ignore it. */
@@ -787,6 +834,69 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
return lost * 100 / (lost + received);
}
+int gprs_rlcmac_dl_tbf::update_window(unsigned first_bsn,
+ const struct bitvec *rbb)
+{
+ int16_t dist; /* must be signed */
+ uint16_t lost = 0, received = 0;
+ char show_v_b[RLC_MAX_SNS + 1];
+ char show_rbb[RLC_MAX_SNS + 1];
+ int error_rate;
+ struct ana_result ana_res;
+ unsigned num_blocks = rbb->cur_bit;
+ unsigned behind_last_bsn = m_window.mod_sns(first_bsn + num_blocks);
+
+ Decoding::extract_rbb(rbb, show_rbb);
+ /* show received array in debug */
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
+ "(BSN=%d) R=ACK I=NACK\n", first_bsn,
+ show_rbb, m_window.mod_sns(behind_last_bsn - 1));
+
+ /* apply received array to receive state (first_bsn..behind_last_bsn-1) */
+ if (num_blocks > 0) {
+ /* calculate distance of ssn from V(S) */
+ dist = m_window.mod_sns(m_window.v_s() - behind_last_bsn);
+ /* check if distance is less than distance V(A)..V(S) */
+ if (dist >= m_window.distance()) {
+ /* this might happpen, if the downlink assignment
+ * was not received by ms and the ack refers
+ * to previous TBF
+ * FIXME: we should implement polling for
+ * control ack!
+ * TODO: check whether this FIXME still makes sense
+ */
+ LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
+ "V(A)..V(S) range %s Free TBF!\n", tbf_name(this));
+ return 1; /* indicate to free TBF */
+ }
+ }
+
+ error_rate = analyse_errors(show_rbb, behind_last_bsn, &ana_res);
+
+ if (bts_data()->cs_adj_enabled && ms())
+ ms()->update_error_rate(this, error_rate);
+
+ m_window.update(bts, rbb, first_bsn, &lost, &received);
+
+ /* report lost and received packets */
+ gprs_rlcmac_received_lost(this, received, lost);
+
+ /* Used to measure the leak rate */
+ gprs_bssgp_update_bytes_received(ana_res.received_bytes,
+ ana_res.received_packets + ana_res.lost_packets);
+
+ /* raise V(A), if possible */
+ m_window.raise(m_window.move_window());
+
+ /* show receive state array in debug (V(A)..V(S)-1) */
+ m_window.show_state(show_v_b);
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
+ "(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
+ "X=Resend-Unacked I=Invalid\n",
+ m_window.v_a(), show_v_b,
+ m_window.v_s_mod(-1));
+ return 0;
+}
int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
{
@@ -794,19 +904,18 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
uint16_t lost = 0, received = 0;
char show_rbb[65];
char show_v_b[RLC_MAX_SNS + 1];
- const uint16_t mod_sns = m_window.mod_sns();
int error_rate;
struct ana_result ana_res;
Decoding::extract_rbb(rbb, show_rbb);
/* show received array in debug (bit 64..1) */
LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
- "(BSN=%d) R=ACK I=NACK\n", (ssn - 64) & mod_sns,
- show_rbb, (ssn - 1) & mod_sns);
+ "(BSN=%d) R=ACK I=NACK\n", m_window.mod_sns(ssn - 64),
+ show_rbb, m_window.mod_sns(ssn - 1));
/* apply received array to receive state (SSN-64..SSN-1) */
/* calculate distance of ssn from V(S) */
- dist = (m_window.v_s() - ssn) & mod_sns;
+ dist = m_window.mod_sns(m_window.v_s() - ssn);
/* check if distance is less than distance V(A)..V(S) */
if (dist >= m_window.distance()) {
/* this might happpen, if the downlink assignment
@@ -895,6 +1004,53 @@ int gprs_rlcmac_dl_tbf::release()
return 0;
}
+int gprs_rlcmac_dl_tbf::abort()
+{
+ uint16_t lost;
+
+ if (state_is(GPRS_RLCMAC_FLOW)) {
+ /* range V(A)..V(S)-1 */
+ lost = m_window.count_unacked();
+
+ /* report all outstanding packets as lost */
+ gprs_rlcmac_received_lost(this, 0, lost);
+ gprs_rlcmac_lost_rep(this);
+
+ /* TODO: Reschedule all LLC frames starting with the one that is
+ * (partly) encoded in chunk 1 of block V(A). (optional) */
+ }
+
+ set_state(GPRS_RLCMAC_RELEASING);
+
+ /* reset rlc states */
+ m_window.reset();
+
+ /* keep to flags */
+ state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+ state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+
+ return 0;
+}
+
+int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, unsigned first_bsn,
+ struct bitvec *rbb)
+{
+ int rc;
+ LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));
+
+ rc = update_window(first_bsn, rbb);
+
+ if (final_ack) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
+ rc = maybe_start_new_window();
+ } else if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
+ LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
+ "all blocks, but without final ack "
+ "indication (don't worry)\n");
+ }
+
+ return rc;
+}
int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb)
{
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index a133d3e..9e763f4 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -50,7 +50,7 @@ int gprs_rlcmac_ul_tbf::assemble_forward_llc(const gprs_rlc_data *_data)
{
const uint8_t *data = _data->block;
uint8_t len = _data->len;
- const struct gprs_rlc_ul_data_block_info *rdbi = &_data->block_info;
+ const struct gprs_rlc_data_block_info *rdbi = &_data->block_info;
GprsCodingScheme cs = _data->cs;
Decoding::RlcData frames[16], *frame;
@@ -87,23 +87,26 @@ int gprs_rlcmac_ul_tbf::assemble_forward_llc(const gprs_rlc_data *_data)
}
-struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn)
+struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn, uint8_t ts)
{
int final = (state_is(GPRS_RLCMAC_FINISHED));
struct msgb *msg;
+ int rc;
+ unsigned int rrbp = 0;
+ uint32_t new_poll_fn = 0;
if (final) {
- if (poll_state != GPRS_RLCMAC_POLL_NONE) {
+ if (poll_state == GPRS_RLCMAC_POLL_SCHED &&
+ ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
- "sheduled for %s, so we must wait for "
- "final uplink ack...\n", tbf_name(this));
+ "scheduled for %s, so we must wait for "
+ "the final uplink ack...\n", tbf_name(this));
return NULL;
}
- if (bts->sba()->find(trx->trx_no, control_ts, (fn + 13) % 2715648)) {
- LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
- "scheduled for single block allocation...\n");
+
+ rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
+ if (rc < 0)
return NULL;
- }
}
msg = msgb_alloc(23, "rlcmac_ul_ack");
@@ -116,20 +119,16 @@ struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn)
}
bitvec_unhex(ack_vec,
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
- Encoding::write_packet_uplink_ack(bts_data(), mac_control_block, this, final);
- encode_gsm_rlcmac_downlink(ack_vec, mac_control_block);
+ Encoding::write_packet_uplink_ack(bts_data(), ack_vec, this, final, rrbp);
bitvec_pack(ack_vec, msgb_put(msg, 23));
bitvec_free(ack_vec);
- talloc_free(mac_control_block);
/* now we must set this flag, so we are allowed to assign downlink
* TBF on PACCH. it is only allowed when TLLI is acknowledged. */
m_contention_resolution_done = 1;
if (final) {
- poll_state = GPRS_RLCMAC_POLL_SCHED;
- poll_fn = (fn + 13) % 2715648;
+ set_polling(new_poll_fn, ts);
/* waiting for final acknowledge */
ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
m_final_ack_sent = 1;
@@ -140,12 +139,11 @@ struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn)
}
int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
- const struct gprs_rlc_ul_header_egprs *rlc,
- uint8_t *data, uint8_t len, struct pcu_l1_meas *meas)
+ const struct gprs_rlc_data_info *rlc,
+ uint8_t *data, struct pcu_l1_meas *meas)
{
int8_t rssi = meas->have_rssi ? meas->rssi : 0;
- const uint16_t mod_sns = m_window.mod_sns();
const uint16_t ws = m_window.ws();
this->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA);
@@ -174,7 +172,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
for (block_idx = 0; block_idx < rlc->num_data_blocks; block_idx++) {
int num_chunks;
uint8_t *rlc_data;
- const struct gprs_rlc_ul_data_block_info *rdbi =
+ const struct gprs_rlc_data_block_info *rdbi =
&rlc->block_info[block_idx];
bool need_rlc_data = false;
struct gprs_rlc_data *block;
@@ -194,7 +192,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
"%d..%d (it's normal)\n", rdbi->bsn,
m_window.v_q(),
- (m_window.v_q() + ws - 1) & mod_sns);
+ m_window.mod_sns(m_window.v_q() + ws - 1));
} else if (m_window.is_received(rdbi->bsn)) {
LOGP(DRLCMACUL, LOGL_DEBUG,
"- BSN %d already received\n", rdbi->bsn);
@@ -219,7 +217,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
rdbi->bsn, m_window.v_q(),
- (m_window.v_q() + ws - 1) & mod_sns);
+ m_window.mod_sns(m_window.v_q() + ws - 1));
block = m_rlc.block(rdbi->bsn);
block->block_info = *rdbi;
block->cs = rlc->cs;
@@ -242,6 +240,9 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
Decoding::rlc_copy_to_aligned_buffer(rlc, block_idx, data,
rlc_data);
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "%s: data_length=%d, data=%s\n",
+ name(), block->len, osmo_hexdump(rlc_data, block->len));
/* TODO: Handle SPB != 0 -> set state to partly received
* (upper/lower) and continue with the loop, unless the other
@@ -293,7 +294,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
/* Retrieve LLC frames from blocks that are ready */
for (uint16_t i = 0; i < count; ++i) {
- uint16_t index = (v_q_beg + i) & mod_sns;
+ uint16_t index = m_window.mod_sns(v_q_beg + i);
assemble_forward_llc(m_rlc.block(index));
}
@@ -301,8 +302,8 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
&& this->m_window.v_q() == this->m_window.v_r()) { /* if complete */
struct gprs_rlc_data *block =
- m_rlc.block((m_window.v_r() - 1) & mod_sns);
- const struct gprs_rlc_ul_data_block_info *rdbi =
+ m_rlc.block(m_window.mod_sns(m_window.v_r() - 1));
+ const struct gprs_rlc_data_block_info *rdbi =
&block->block_info;
LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
@@ -325,7 +326,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
}
void gprs_rlcmac_ul_tbf::maybe_schedule_uplink_acknack(
- const gprs_rlc_ul_header_egprs *rlc)
+ const gprs_rlc_data_info *rlc)
{
bool have_ti = rlc->block_info[0].ti ||
(rlc->num_data_blocks > 1 && rlc->block_info[1].ti);
diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp
index d338b78..c3efd4d 100644
--- a/tests/alloc/AllocTest.cpp
+++ b/tests/alloc/AllocTest.cpp
@@ -52,23 +52,23 @@ static gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts,
static void check_tfi_usage(BTS *the_bts)
{
int pdch_no;
- struct gprs_rlcmac_bts *bts = the_bts->bts_data();
struct gprs_rlcmac_tbf *tfi_usage[8][8][2][32] = {{{{NULL}}}};
- struct llist_head *tbf_lists[2] = {
- &bts->ul_tbfs,
- &bts->dl_tbfs
+ LListHead<gprs_rlcmac_tbf> *tbf_lists[2] = {
+ &the_bts->ul_tbfs(),
+ &the_bts->dl_tbfs()
};
+ LListHead<gprs_rlcmac_tbf> *pos;
gprs_rlcmac_tbf *tbf;
- struct llist_pods *lpods;
unsigned list_idx;
struct gprs_rlcmac_tbf **tbf_var;
for (list_idx = 0; list_idx < ARRAY_SIZE(tbf_lists); list_idx += 1)
{
- llist_pods_for_each_entry(tbf, tbf_lists[list_idx], list, lpods) {
+ llist_for_each(pos, tbf_lists[list_idx]) {
+ tbf = pos->entry();
for (pdch_no = 0; pdch_no < 8; pdch_no += 1) {
struct gprs_rlcmac_pdch *pdch = tbf->pdch[pdch_no];
if (pdch == NULL)
diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp
index 3115054..96ea0c1 100644
--- a/tests/edge/EdgeTest.cpp
+++ b/tests/edge/EdgeTest.cpp
@@ -23,7 +23,9 @@
#include "gprs_debug.h"
#include "gprs_coding_scheme.h"
#include "decoding.h"
+#include "encoding.h"
#include "rlc.h"
+#include "llc.h"
extern "C" {
#include "pcu_vty.h"
@@ -36,6 +38,7 @@ extern "C" {
}
#include <errno.h>
+#include <string.h>
void *tall_pcu_ctx;
int16_t spoof_mnc = 0, spoof_mcc = 0;
@@ -43,21 +46,22 @@ int16_t spoof_mnc = 0, spoof_mcc = 0;
static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
{
volatile unsigned expected_size;
+ bool need_padding;
GprsCodingScheme new_cs;
OSMO_ASSERT(cs.isValid());
OSMO_ASSERT(cs.isCompatible(mode));
/* Check static getBySizeUL() */
- expected_size = cs.maxBytesUL();
- if (cs.spareBitsUL() > 0)
+ expected_size = cs.usedSizeUL();
+ if (cs.spareBitsUL() > 0 && cs.isGprs())
expected_size += 1;
OSMO_ASSERT(expected_size == cs.sizeUL());
OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
/* Check static sizeUL() */
- expected_size = cs.maxBytesDL();
- if (cs.spareBitsDL() > 0)
+ expected_size = cs.usedSizeDL();
+ if (cs.spareBitsDL() > 0 && cs.isGprs())
expected_size += 1;
OSMO_ASSERT(expected_size == cs.sizeDL());
@@ -81,6 +85,19 @@ static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mod
OSMO_ASSERT(new_cs.isCompatible(mode));
OSMO_ASSERT(new_cs == cs);
}
+
+ new_cs = cs;
+ new_cs.decToSingleBlock(&need_padding);
+ OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
+ OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
+ OSMO_ASSERT(cs.isCompatible(new_cs));
+ if (need_padding) {
+ OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
+ new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
+ } else {
+ OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
+ }
+
}
static void test_coding_scheme()
@@ -113,7 +130,8 @@ static void test_coding_scheme()
GprsCodingScheme cs;
OSMO_ASSERT(!cs);
- OSMO_ASSERT(cs == GprsCodingScheme::UNKNOWN);
+ OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
+ OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
@@ -126,7 +144,7 @@ static void test_coding_scheme()
OSMO_ASSERT(current_cs.isGprs());
OSMO_ASSERT(!current_cs.isEgprs());
OSMO_ASSERT(!current_cs.isEgprsGmsk());
- OSMO_ASSERT(current_cs == gprs_schemes[i]);
+ OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
/* Check strong monotonicity */
@@ -153,7 +171,7 @@ static void test_coding_scheme()
OSMO_ASSERT(!current_cs.isGprs());
OSMO_ASSERT(current_cs.isEgprs());
OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
- OSMO_ASSERT(current_cs == egprs_schemes[i].s);
+ OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
/* Check strong monotonicity */
@@ -171,9 +189,9 @@ static void test_coding_scheme()
printf("=== end %s ===\n", __func__);
}
-static void test_rlc_decoder()
+static void test_rlc_unit_decoder()
{
- struct gprs_rlc_ul_data_block_info rdbi = {0};
+ struct gprs_rlc_data_block_info rdbi = {0};
GprsCodingScheme cs;
uint8_t data[74];
Decoding::RlcData chunks[16];
@@ -480,6 +498,582 @@ static void test_rlc_decoder()
printf("=== end %s ===\n", __func__);
}
+static void test_rlc_unit_encoder()
+{
+ struct gprs_rlc_data_block_info rdbi = {0};
+ GprsCodingScheme cs;
+ uint8_t data[74];
+ uint8_t llc_data[1500] = {0,};
+ int num_chunks = 0;
+ int write_offset;
+ struct gprs_llc llc;
+ Encoding::AppendResult ar;
+
+ printf("=== start %s ===\n", __func__);
+
+ llc.init();
+
+ /* TS 44.060, B.1 */
+ cs = GprsCodingScheme::CS4;
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 11);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 11);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 26);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 2 + 11 + 26);
+ OSMO_ASSERT(num_chunks == 2);
+
+ llc.reset();
+ llc.put_frame(llc_data, 99);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv != 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 3);
+
+ OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[2] == 0);
+
+ /* TS 44.060, B.2 */
+ cs = GprsCodingScheme::CS1;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 20);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 19);
+ OSMO_ASSERT(num_chunks == 1);
+
+ OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[1] == 0);
+
+ /* Block 2 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ OSMO_ASSERT(llc.chunk_size() == 1);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 1);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 99);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 1 + 18);
+ OSMO_ASSERT(num_chunks == 2);
+
+ OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[1] == 0);
+
+ /* TS 44.060, B.3 */
+ cs = GprsCodingScheme::CS1;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 7);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 7);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 11);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 2 + 7 + 11);
+ OSMO_ASSERT(num_chunks == 2);
+
+ OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[2] == 0);
+
+ /* TS 44.060, B.4 */
+ cs = GprsCodingScheme::CS1;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 99);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 1);
+ OSMO_ASSERT(write_offset == 20);
+ OSMO_ASSERT(num_chunks == 1);
+ OSMO_ASSERT(rdbi.cv != 0);
+
+ OSMO_ASSERT(data[0] == 0);
+
+ /* TS 44.060, B.5 */
+ cs = GprsCodingScheme::CS1;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 20);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, true);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 1);
+ OSMO_ASSERT(write_offset == 20);
+ OSMO_ASSERT(num_chunks == 1);
+ OSMO_ASSERT(rdbi.cv == 0);
+
+ OSMO_ASSERT(data[0] == 0);
+
+ /* TS 44.060, B.7 */
+ cs = GprsCodingScheme::CS1;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 30);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 1);
+ OSMO_ASSERT(write_offset == 20);
+ OSMO_ASSERT(num_chunks == 1);
+
+ OSMO_ASSERT(data[0] == 0);
+
+ /* Block 2 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ OSMO_ASSERT(llc.chunk_size() == 10);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 10);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 99);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 10 + 9);
+ OSMO_ASSERT(num_chunks == 2);
+
+ OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[1] == 0);
+
+ /* TS 44.060, B.8.1 */
+ cs = GprsCodingScheme::MCS4;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 11);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 11);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 26);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 2 + 11 + 26);
+ OSMO_ASSERT(num_chunks == 2);
+
+ llc.reset();
+ llc.put_frame(llc_data, 99);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv != 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 3);
+
+ OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[2] == 0);
+
+ /* TS 44.060, B.8.2 */
+
+ /* Note that the spec confuses the byte numbering here, since it
+ * includes the FBI/E header bits into the N2 octet count which
+ * is not consistent with Section 10.3a.1 & 10.3a.2. */
+
+ cs = GprsCodingScheme::MCS2;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 15);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 15);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 12);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv != 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 2);
+
+ OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[1] == 0);
+
+ /* Block 2 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ OSMO_ASSERT(llc.chunk_size() == 0);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 0);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 7);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv != 0);
+ OSMO_ASSERT(write_offset == 2 + 0 + 7);
+ OSMO_ASSERT(num_chunks == 2);
+
+ llc.reset();
+ llc.put_frame(llc_data, 18);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv != 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 3);
+
+ OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[3] == 0);
+
+ /* Block 3 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, 6);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, false);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(write_offset == 1 + 6);
+ OSMO_ASSERT(num_chunks == 1);
+
+ llc.reset();
+ llc.put_frame(llc_data, 12);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, true);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv == 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 3);
+
+ OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
+ OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[3] == 0);
+
+ /* TS 44.060, B.8.3 */
+
+ /* Note that the spec confuses the byte numbering here, too (see above) */
+
+ cs = GprsCodingScheme::MCS2;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, rdbi.data_len);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, true);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 1);
+ OSMO_ASSERT(rdbi.cv == 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 1);
+
+ OSMO_ASSERT(data[0] == 0);
+
+ /* Final block with an LLC of size data_len-1 */
+
+ cs = GprsCodingScheme::MCS2;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, rdbi.data_len - 1);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, true);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv == 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 1);
+
+ OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
+ OSMO_ASSERT(data[1] == 0);
+
+ /* Final block with an LLC of size data_len-2 */
+
+ cs = GprsCodingScheme::MCS2;
+
+ /* Block 1 */
+ gprs_rlc_data_block_info_init(&rdbi, cs, false);
+ num_chunks = 0;
+ write_offset = 0;
+ memset(data, 0, sizeof(data));
+
+ llc.reset();
+ llc.put_frame(llc_data, rdbi.data_len - 2);
+
+ ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
+ &llc, &write_offset, &num_chunks, data, true);
+
+ OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
+ OSMO_ASSERT(rdbi.e == 0);
+ OSMO_ASSERT(rdbi.cv == 0);
+ OSMO_ASSERT(write_offset == (int)rdbi.data_len);
+ OSMO_ASSERT(num_chunks == 2);
+
+ OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
+ OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
+ OSMO_ASSERT(data[2] == 0);
+
+ printf("=== end %s ===\n", __func__);
+}
+
+static void test_rlc_unaligned_copy()
+{
+ uint8_t bits[256];
+ uint8_t saved_block[256];
+ uint8_t test_block[256];
+ uint8_t out_block[256];
+ GprsCodingScheme::Scheme scheme;
+ int pattern;
+ volatile unsigned int block_idx, i;
+
+ for (scheme = GprsCodingScheme::CS1;
+ scheme < GprsCodingScheme::NUM_SCHEMES;
+ scheme = GprsCodingScheme::Scheme(scheme + 1))
+ {
+ GprsCodingScheme cs(scheme);
+
+ for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
+ /* prepare test block */
+ test_block[0] = pattern ^ 0xff;
+ for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
+ test_block[i] = i;
+ test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
+
+ for (block_idx = 0;
+ block_idx < cs.numDataBlocks();
+ block_idx++)
+ {
+ struct gprs_rlc_data_info rlc;
+ gprs_rlc_data_info_init_dl(&rlc, cs, false);
+
+ memset(bits, pattern, sizeof(bits));
+ Decoding::rlc_copy_to_aligned_buffer(
+ &rlc, block_idx, bits, saved_block);
+
+ fprintf(stderr,
+ "Test data block: %s\n",
+ osmo_hexdump(test_block, cs.maxDataBlockBytes()));
+
+ Encoding::rlc_copy_from_aligned_buffer(
+ &rlc, block_idx, bits, test_block);
+
+ fprintf(stderr,
+ "Encoded message block, %s, idx %d, "
+ "pattern %02x: %s\n",
+ rlc.cs.name(), block_idx, pattern,
+ osmo_hexdump(bits, cs.sizeDL()));
+
+ Decoding::rlc_copy_to_aligned_buffer(
+ &rlc, block_idx, bits, out_block);
+
+ fprintf(stderr,
+ "Out data block: %s\n",
+ osmo_hexdump(out_block, cs.maxDataBlockBytes()));
+ /* restore original bits */
+ Encoding::rlc_copy_from_aligned_buffer(
+ &rlc, block_idx, bits, saved_block);
+
+ OSMO_ASSERT(memcmp(test_block, out_block,
+ rlc.cs.maxDataBlockBytes()) == 0);
+
+ for (i = 0; i < sizeof(bits); i++)
+ OSMO_ASSERT(bits[i] == pattern);
+ }
+ }
+ }
+}
+
+static void test_rlc_info_init()
+{
+ struct gprs_rlc_data_info rlc;
+
+ printf("=== start %s ===\n", __func__);
+ gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1), false);
+ OSMO_ASSERT(rlc.num_data_blocks == 1);
+ OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
+ OSMO_ASSERT(rlc.block_info[0].data_len == 20);
+
+ gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1), false);
+ OSMO_ASSERT(rlc.num_data_blocks == 1);
+ OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
+ OSMO_ASSERT(rlc.block_info[0].data_len == 22);
+
+ printf("=== end %s ===\n", __func__);
+}
static const struct log_info_cat default_categories[] = {
{"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
@@ -524,7 +1118,10 @@ int main(int argc, char **argv)
pcu_vty_init(&debug_log_info);
test_coding_scheme();
- test_rlc_decoder();
+ test_rlc_info_init();
+ test_rlc_unit_decoder();
+ test_rlc_unaligned_copy();
+ test_rlc_unit_encoder();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/edge/EdgeTest.ok b/tests/edge/EdgeTest.ok
index 6597f07..9554df3 100644
--- a/tests/edge/EdgeTest.ok
+++ b/tests/edge/EdgeTest.ok
@@ -1,4 +1,8 @@
=== start test_coding_scheme ===
=== end test_coding_scheme ===
-=== start test_rlc_decoder ===
-=== end test_rlc_decoder ===
+=== start test_rlc_info_init ===
+=== end test_rlc_info_init ===
+=== start test_rlc_unit_decoder ===
+=== end test_rlc_unit_decoder ===
+=== start test_rlc_unit_encoder ===
+=== end test_rlc_unit_encoder ===
diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp
index 344b0b4..0930354 100644
--- a/tests/ms/MsTest.cpp
+++ b/tests/ms/MsTest.cpp
@@ -503,11 +503,11 @@ static void test_ms_cs_selection()
dl_tbf->set_ms(ms);
OSMO_ASSERT(!ms->is_idle());
- OSMO_ASSERT(ms->current_cs_dl() == 4);
+ OSMO_ASSERT(ms->current_cs_dl().to_num() == 4);
bts->cs_downgrade_threshold = 200;
- OSMO_ASSERT(ms->current_cs_dl() == 3);
+ OSMO_ASSERT(ms->current_cs_dl().to_num() == 3);
talloc_free(dl_tbf);
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index 66fa982..e1be844 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -81,6 +81,8 @@ static void test_tbf_tlli_update()
BTS the_bts;
GprsMs *ms, *ms_new;
+ printf("=== start %s ===\n", __func__);
+
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_a;
the_bts.bts_data()->trx[0].pdch[2].enable();
the_bts.bts_data()->trx[0].pdch[3].enable();
@@ -138,6 +140,8 @@ static void test_tbf_tlli_update()
OSMO_ASSERT(ul_tbf->ta() == 6);
OSMO_ASSERT(dl_tbf->ta() == 6);
+
+ printf("=== end %s ===\n", __func__);
}
static uint8_t llc_data[200];
@@ -162,7 +166,7 @@ static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
}
static gprs_rlcmac_dl_tbf *create_dl_tbf(BTS *the_bts, uint8_t ms_class,
- uint8_t *trx_no_)
+ uint8_t egprs_ms_class, uint8_t *trx_no_)
{
gprs_rlcmac_bts *bts;
int tfi;
@@ -174,7 +178,7 @@ static gprs_rlcmac_dl_tbf *create_dl_tbf(BTS *the_bts, uint8_t ms_class,
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
- dl_tbf = tbf_alloc_dl_tbf(bts, NULL, trx_no, ms_class, 0, 1);
+ dl_tbf = tbf_alloc_dl_tbf(bts, NULL, trx_no, ms_class, egprs_ms_class, 1);
check_tbf(dl_tbf);
/* "Establish" the DL TBF */
@@ -239,11 +243,13 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
uint8_t rbb[64/8];
+ printf("=== start %s ===\n", __func__);
+
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no);
- dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
+ dl_tbf = create_dl_tbf(&the_bts, ms_class, 0, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
@@ -292,6 +298,8 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
tbf_free(new_tbf);
OSMO_ASSERT(ms->dl_tbf() == NULL);
}
+
+ printf("=== end %s ===\n", __func__);
}
static void test_tbf_delayed_release()
@@ -316,7 +324,7 @@ static void test_tbf_delayed_release()
setup_bts(&the_bts, ts_no);
bts->dl_tbf_idle_msec = 200;
- dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
+ dl_tbf = create_dl_tbf(&the_bts, ms_class, 0, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
for (i = 0; i < sizeof(llc_data); i++)
@@ -381,8 +389,8 @@ static void test_tbf_imsi()
setup_bts(&the_bts, ts_no);
- dl_tbf[0] = create_dl_tbf(&the_bts, ms_class, &trx_no);
- dl_tbf[1] = create_dl_tbf(&the_bts, ms_class, &trx_no);
+ dl_tbf[0] = create_dl_tbf(&the_bts, ms_class, 0, &trx_no);
+ dl_tbf[1] = create_dl_tbf(&the_bts, ms_class, 0, &trx_no);
dl_tbf[0]->update_ms(0xf1000001, GPRS_RLCMAC_DL_TBF);
dl_tbf[1]->update_ms(0xf1000002, GPRS_RLCMAC_DL_TBF);
@@ -597,6 +605,7 @@ static void send_control_ack(gprs_rlcmac_tbf *tbf)
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
+ OSMO_ASSERT(tbf->is_control_ts(tbf->poll_ts));
ulreq.u.MESSAGE_TYPE = MT_PACKET_CONTROL_ACK;
Packet_Control_Acknowledgement_t *ctrl_ack =
@@ -604,13 +613,13 @@ static void send_control_ack(gprs_rlcmac_tbf *tbf)
ctrl_ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ctrl_ack->TLLI = tbf->tlli();
- send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
+ send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->poll_ts,
&ulreq, tbf->poll_fn);
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
- uint8_t ms_class)
+ uint8_t ms_class, uint8_t egprs_ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
@@ -651,6 +660,14 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(BTS *the_bts,
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
+ if (egprs_ms_class) {
+ ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
+ MS_RA_capability_value[0].u.Content.Multislot_capability.
+ Exist_EGPRS_multislot_class = 1;
+ ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
+ MS_RA_capability_value[0].u.Content.Multislot_capability.
+ EGPRS_multislot_class = ms_class;
+ }
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
@@ -706,7 +723,8 @@ static void send_dl_data(BTS *the_bts, uint32_t tlli, const char *imsi,
}
}
-static void transmit_dl_data(BTS *the_bts, uint32_t tlli, uint32_t *fn)
+static void transmit_dl_data(BTS *the_bts, uint32_t tlli, uint32_t *fn,
+ uint8_t slots = 0xff)
{
gprs_rlcmac_dl_tbf *dl_tbf;
GprsMs *ms;
@@ -719,10 +737,13 @@ static void transmit_dl_data(BTS *the_bts, uint32_t tlli, uint32_t *fn)
while (dl_tbf->have_data()) {
uint8_t bn = fn2bn(*fn);
- for (ts_no = 0 ; ts_no < 8; ts_no += 1)
+ for (ts_no = 0 ; ts_no < 8; ts_no += 1) {
+ if (!(slots & (1 << ts_no)))
+ continue;
gprs_rlcmac_rcv_rts_block(the_bts->bts_data(),
dl_tbf->trx->trx_no, ts_no, 0,
*fn, bn);
+ }
*fn = fn_add_blocks(*fn, 1);
}
}
@@ -769,7 +790,8 @@ static void test_tbf_two_phase()
setup_bts(&the_bts, ts_no, 4);
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli, &fn, qta,
+ ms_class, 0);
ms = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
@@ -797,7 +819,8 @@ static void test_tbf_ra_update_rach()
setup_bts(&the_bts, ts_no, 4);
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta,
+ ms_class, 0);
ms1 = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
@@ -818,7 +841,8 @@ static void test_tbf_ra_update_rach()
OSMO_ASSERT(ms1->llc_queue()->size() == 0);
/* Now establish a new TBF for the RA UPDATE COMPLETE (new TLLI) */
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli2, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli2, &fn, qta,
+ ms_class, 0);
ms2 = ul_tbf->ms();
@@ -863,7 +887,8 @@ static void test_tbf_dl_flow_and_rach_two_phase()
setup_bts(&the_bts, ts_no, 1);
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta,
+ ms_class, 0);
ms1 = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
@@ -883,7 +908,8 @@ static void test_tbf_dl_flow_and_rach_two_phase()
OSMO_ASSERT(ms1 == ms);
/* Now establish a new UL TBF, this will consume one LLC packet */
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta,
+ ms_class, 0);
ms2 = ul_tbf->ms();
fprintf(stderr, "New MS: TLLI = 0x%08x, TA = %d, IMSI = %s, LLC = %d\n",
@@ -922,7 +948,8 @@ static void test_tbf_dl_flow_and_rach_single_phase()
setup_bts(&the_bts, ts_no, 1);
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta,
+ ms_class, 0);
ms1 = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
@@ -955,9 +982,8 @@ static void test_tbf_dl_flow_and_rach_single_phase()
OSMO_ASSERT(ms2 == ms);
OSMO_ASSERT(ms1 != ms);
- /* DL TBF should be the same */
- OSMO_ASSERT(ms->dl_tbf());
- OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
+ /* DL TBF should be removed */
+ OSMO_ASSERT(!ms->dl_tbf());
/* No queued packets should be lost */
OSMO_ASSERT(ms->llc_queue()->size() == 2);
@@ -984,7 +1010,8 @@ static void test_tbf_dl_reuse()
setup_bts(&the_bts, ts_no, 1);
- ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta, ms_class);
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli1, &fn, qta,
+ ms_class, 0);
ms1 = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
@@ -1036,7 +1063,7 @@ static void test_tbf_dl_reuse()
ack->DOWNLINK_TFI = dl_tbf1->tfi();
ack->Ack_Nack_Description.FINAL_ACK_INDICATION = 1;
- send_ul_mac_block(&the_bts, 0, ts_no, &ulreq, dl_tbf1->poll_fn);
+ send_ul_mac_block(&the_bts, 0, dl_tbf1->poll_ts, &ulreq, dl_tbf1->poll_fn);
OSMO_ASSERT(dl_tbf1->state_is(GPRS_RLCMAC_WAIT_RELEASE));
@@ -1045,7 +1072,7 @@ static void test_tbf_dl_reuse()
ms2 = the_bts.ms_by_tlli(tlli1);
OSMO_ASSERT(ms2 == ms1);
OSMO_ASSERT(ms2->dl_tbf());
- OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_ASSIGN));
+ OSMO_ASSERT(ms2->dl_tbf()->state_is(GPRS_RLCMAC_WAIT_ASSIGN));
dl_tbf2 = ms2->dl_tbf();
@@ -1063,6 +1090,210 @@ static void test_tbf_dl_reuse()
printf("=== end %s ===\n", __func__);
}
+static void test_tbf_gprs_egprs()
+{
+ BTS the_bts;
+ gprs_rlcmac_bts *bts;
+ uint8_t ts_no = 4;
+ uint8_t ms_class = 45;
+ int rc = 0;
+ uint32_t tlli = 0xc0006789;
+ const char *imsi = "001001123456789";
+ unsigned delay_csec = 1000;
+
+ uint8_t buf[256] = {0};
+
+ printf("=== start %s ===\n", __func__);
+
+ bts = the_bts.bts_data();
+ setup_bts(&the_bts, ts_no);
+
+ /* EGPRS-only */
+ bts->egprs_enabled = 1;
+
+ gprs_bssgp_create_and_connect(bts, 33001, 0, 33001,
+ 1234, 1234, 1234, 1, 1, 0, 0, 0);
+
+ /* Does not support EGPRS */
+ rc = gprs_rlcmac_dl_tbf::handle(bts, tlli, 0, imsi, ms_class, 0,
+ delay_csec, buf, sizeof(buf));
+
+ OSMO_ASSERT(rc == -EBUSY);
+ printf("=== end %s ===\n", __func__);
+
+ gprs_bssgp_destroy();
+}
+
+static void test_tbf_ws()
+{
+ BTS the_bts;
+ gprs_rlcmac_bts *bts;
+ uint8_t ts_no = 4;
+ uint8_t ms_class = 12;
+ gprs_rlcmac_dl_tbf *dl_tbf;
+
+ printf("=== start %s ===\n", __func__);
+
+ bts = the_bts.bts_data();
+ setup_bts(&the_bts, ts_no);
+
+ bts->ws_base = 128;
+ bts->ws_pdch = 64;
+ bts->alloc_algorithm = alloc_algorithm_b;
+ bts->trx[0].pdch[2].enable();
+ bts->trx[0].pdch[3].enable();
+ bts->trx[0].pdch[4].enable();
+ bts->trx[0].pdch[5].enable();
+
+ gprs_bssgp_create_and_connect(bts, 33001, 0, 33001,
+ 1234, 1234, 1234, 1, 1, 0, 0, 0);
+
+ /* Does no support EGPRS */
+ dl_tbf = tbf_alloc_dl_tbf(bts, NULL, 0, ms_class, 0, 0);
+ OSMO_ASSERT(dl_tbf != NULL);
+ fprintf(stderr, "DL TBF slots: 0x%02x, N: %d, WS: %d\n",
+ dl_tbf->dl_slots(),
+ pcu_bitcount(dl_tbf->dl_slots()),
+ dl_tbf->window()->ws());
+ OSMO_ASSERT(pcu_bitcount(dl_tbf->dl_slots()) == 4);
+ OSMO_ASSERT(dl_tbf->window()->ws() == 64);
+ tbf_free(dl_tbf);
+
+ /* EGPRS-only */
+ bts->egprs_enabled = 1;
+
+ /* Does support EGPRS */
+ dl_tbf = tbf_alloc_dl_tbf(bts, NULL, 0, ms_class, ms_class, 0);
+
+ OSMO_ASSERT(dl_tbf != NULL);
+ fprintf(stderr, "DL TBF slots: 0x%02x, N: %d, WS: %d\n",
+ dl_tbf->dl_slots(),
+ pcu_bitcount(dl_tbf->dl_slots()),
+ dl_tbf->window()->ws());
+ OSMO_ASSERT(pcu_bitcount(dl_tbf->dl_slots()) == 4);
+ OSMO_ASSERT(dl_tbf->window()->ws() == 128 + 4 * 64);
+ tbf_free(dl_tbf);
+
+ printf("=== end %s ===\n", __func__);
+
+ gprs_bssgp_destroy();
+}
+
+static void test_tbf_egprs_two_phase()
+{
+ BTS the_bts;
+ int ts_no = 7;
+ uint32_t fn = 2654218;
+ uint16_t qta = 31;
+ uint32_t tlli = 0xf1223344;
+ const char *imsi = "0011223344";
+ uint8_t ms_class = 1;
+ uint8_t egprs_ms_class = 1;
+ gprs_rlcmac_ul_tbf *ul_tbf;
+ GprsMs *ms;
+ uint8_t test_data[256];
+
+ printf("=== start %s ===\n", __func__);
+
+ memset(test_data, 1, sizeof(test_data));
+
+ setup_bts(&the_bts, ts_no, 4);
+ the_bts.bts_data()->initial_mcs_dl = 9;
+ the_bts.bts_data()->egprs_enabled = 1;
+
+ ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli, &fn, qta,
+ ms_class, egprs_ms_class);
+
+ ms = ul_tbf->ms();
+ fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
+ fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms->tlli(), ms->ta());
+
+ send_dl_data(&the_bts, tlli, imsi, test_data, sizeof(test_data));
+
+ printf("=== end %s ===\n", __func__);
+}
+
+static void establish_and_use_egprs_dl_tbf(BTS *the_bts, int mcs)
+{
+ unsigned i;
+ uint8_t ms_class = 11;
+ uint8_t egprs_ms_class = 11;
+ uint32_t fn = 0;
+ uint8_t trx_no;
+ uint32_t tlli = 0xffeeddcc;
+ uint8_t test_data[512];
+
+ uint8_t rbb[64/8];
+
+ gprs_rlcmac_dl_tbf *dl_tbf;
+
+ printf("Testing MCS-%d\n", mcs);
+
+ memset(test_data, 1, sizeof(test_data));
+ the_bts->bts_data()->initial_mcs_dl = mcs;
+
+ dl_tbf = create_dl_tbf(the_bts, ms_class, egprs_ms_class, &trx_no);
+ dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
+
+ for (i = 0; i < sizeof(llc_data); i++)
+ llc_data[i] = i%256;
+
+ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
+
+ /* Schedule a small LLC frame */
+ dl_tbf->append_data(ms_class, 1000, test_data, 10);
+
+ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
+
+ /* Drain the queue */
+ while (dl_tbf->have_data())
+ /* Request to send one RLC/MAC block */
+ request_dl_rlc_block(dl_tbf, &fn);
+
+ /* Schedule a large LLC frame */
+ dl_tbf->append_data(ms_class, 1000, test_data, sizeof(test_data));
+
+ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
+
+ /* Drain the queue */
+ while (dl_tbf->have_data())
+ /* Request to send one RLC/MAC block */
+ request_dl_rlc_block(dl_tbf, &fn);
+
+ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
+
+ /* Receive a final ACK */
+ dl_tbf->rcvd_dl_ack(1, dl_tbf->m_window.v_s(), rbb);
+
+ /* Clean up and ensure tbfs are in the correct state */
+ OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE));
+ dl_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
+ check_tbf(dl_tbf);
+ tbf_free(dl_tbf);
+}
+
+static void test_tbf_egprs_dl()
+{
+ BTS the_bts;
+ gprs_rlcmac_bts *bts;
+ uint8_t ts_no = 4;
+ int i;
+
+ printf("=== start %s ===\n", __func__);
+
+ bts = the_bts.bts_data();
+
+ setup_bts(&the_bts, ts_no);
+ bts->dl_tbf_idle_msec = 200;
+ bts->egprs_enabled = 1;
+
+ for (i = 1; i <= 9; i++)
+ establish_and_use_egprs_dl_tbf(&the_bts, i);
+
+ printf("=== end %s ===\n", __func__);
+}
+
+
static const struct log_info_cat default_categories[] = {
{"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
@@ -1121,6 +1352,10 @@ int main(int argc, char **argv)
test_tbf_dl_flow_and_rach_two_phase();
test_tbf_dl_flow_and_rach_single_phase();
test_tbf_dl_reuse();
+ test_tbf_gprs_egprs();
+ test_tbf_ws();
+ test_tbf_egprs_two_phase();
+ test_tbf_egprs_dl();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err
index 27c5fe3..7796659 100644
--- a/tests/tbf/TbfTest.err
+++ b/tests/tbf/TbfTest.err
@@ -1,5 +1,5 @@
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
+Allocating DL TBF: MS_CLASS=0/0
Creating MS object, TLLI = 0x00000000
Slot Allocation (Algorithm A) for class 0
- Skipping TS 0, because not enabled
@@ -38,7 +38,7 @@ Modifying MS object, TLLI = 0x00004232, TA 4 -> 6
Searching for first unallocated TFI: TRX=0
Found TFI=0.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -58,32 +58,38 @@ TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW
The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13, TS=4
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (TRX=0, TS=4)
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (len=200)
-- Sending new block at BSN 0, CS=1
-- Chunk with length 200 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+data block (BSN 0, CS-1): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 180 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+data block (BSN 1, CS-1): 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge
- Final ACK received.
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) changes state from FLOW to WAIT RELEASE
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) starting timer 3193.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Slot Allocation (Algorithm A) for class 45
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -101,22 +107,23 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger downlink assignment
Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) exists
TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) starting timer 0.
-DL packet loss of IMSI= / TLLI=0xffeeddcc: 0%
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) free
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) stopping timer 3193.
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE), 1 TBFs, USFs = 00, TFIs = 00000002.
-Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING), 1 TBFs, USFs = 00, TFIs = 00000002.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING)
********** TBF ends here **********
-TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) free
-TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) stopping timer 0.
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN), 0 TBFs, USFs = 00, TFIs = 00000000.
-Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN)
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) changes state from ASSIGN to RELEASING
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) free
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) stopping timer 0.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING)
********** TBF ends here **********
Destroying MS object, TLLI = 0xffeeddcc
Searching for first unallocated TFI: TRX=0
Found TFI=0.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -136,32 +143,38 @@ TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW
The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13, TS=4
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (TRX=0, TS=4)
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (len=200)
-- Sending new block at BSN 0, CS=1
-- Chunk with length 200 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+data block (BSN 0, CS-1): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 180 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+data block (BSN 1, CS-1): 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge
- Final ACK received.
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) changes state from FLOW to WAIT RELEASE
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) starting timer 3193.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Slot Allocation (Algorithm A) for class 45
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -179,22 +192,23 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger downlink assignment
Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) exists
TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) starting timer 0.
-TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) free
-TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) stopping timer 0.
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN), 1 TBFs, USFs = 00, TFIs = 00000001.
-Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN)
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) changes state from ASSIGN to RELEASING
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) free
+TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) stopping timer 0.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING), 1 TBFs, USFs = 00, TFIs = 00000001.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=RELEASING)
********** TBF ends here **********
-DL packet loss of IMSI= / TLLI=0xffeeddcc: 0%
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) free
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) stopping timer 3193.
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE), 0 TBFs, USFs = 00, TFIs = 00000000.
-Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING)
********** TBF ends here **********
Destroying MS object, TLLI = 0xffeeddcc
Searching for first unallocated TFI: TRX=0
Found TFI=0.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -214,149 +228,193 @@ TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW
The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) Scheduled DL Assignment polling on FN=13, TS=4
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (TRX=0, TS=4)
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (len=200)
-- Sending new block at BSN 0, CS=1
-- Chunk with length 200 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+data block (BSN 0, CS-1): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 01 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 180 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+data block (BSN 1, CS-1): 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 03 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==2)
-- Sending new block at BSN 2, CS=1
+- Sending new block at BSN 2, CS=CS-1
-- Chunk with length 160 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 05 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
+data block (BSN 2, CS-1): 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
+- Copying data unit 0 (BSN 2)
+msg block (BSN 2, CS-1): 07 00 05 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 00 05 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==3)
-- Sending new block at BSN 3, CS=1
+- Sending new block at BSN 3, CS=CS-1
-- Chunk with length 140 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 07 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+data block (BSN 3, CS-1): 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+- Copying data unit 0 (BSN 3)
+msg block (BSN 3, CS-1): 07 00 07 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 00 07 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==4)
-- Sending new block at BSN 4, CS=1
+- Sending new block at BSN 4, CS=CS-1
-- Chunk with length 120 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 09 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63
+data block (BSN 4, CS-1): 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63
+- Copying data unit 0 (BSN 4)
+msg block (BSN 4, CS-1): 07 00 09 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 09 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==5)
-- Sending new block at BSN 5, CS=1
+- Sending new block at BSN 5, CS=CS-1
-- Chunk with length 100 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 0b 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77
+data block (BSN 5, CS-1): 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77
+- Copying data unit 0 (BSN 5)
+msg block (BSN 5, CS-1): 07 00 0b 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 00 0b 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==6)
-- Sending new block at BSN 6, CS=1
+- Sending new block at BSN 6, CS=CS-1
-- Chunk with length 80 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 0d 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b
+data block (BSN 6, CS-1): 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b
+- Copying data unit 0 (BSN 6)
+msg block (BSN 6, CS-1): 07 00 0d 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 00 0d 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==7)
-- Sending new block at BSN 7, CS=1
+- Sending new block at BSN 7, CS=CS-1
-- Chunk with length 60 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 0f 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
+data block (BSN 7, CS-1): 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
+- Copying data unit 0 (BSN 7)
+msg block (BSN 7, CS-1): 07 00 0f 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 00 0f 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==8)
-- Sending new block at BSN 8, CS=1
+- Sending new block at BSN 8, CS=CS-1
-- Chunk with length 40 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 11 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3
+data block (BSN 8, CS-1): a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3
+- Copying data unit 0 (BSN 8)
+msg block (BSN 8, CS-1): 07 00 11 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 11 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==9)
-- Sending new block at BSN 9, CS=1
+- Sending new block at BSN 9, CS=CS-1
-- Chunk with length 20 would exactly fit into space (20): add length header with LI=0, to make frame extend to next block, and we are done
-data block: 07 00 12 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
+data block (BSN 9, CS-1): 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
+- Copying data unit 0 (BSN 9)
+msg block (BSN 9, CS-1): 07 00 12 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 00 12 01 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10)
-- Sending new block at BSN 10, CS=1
+- Sending new block at BSN 10, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=200
- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) (len=200)
-- Chunk with length 200 larger than space (18) left in block: copy only remaining space, and we are done
-data block: 07 00 14 07 c7 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
+data block (BSN 10, CS-1): 07 c7 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
+- Copying data unit 0 (BSN 10)
+msg block (BSN 10, CS-1): 07 00 14 07 c7 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 00 14 07 c7 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==11)
-- Sending new block at BSN 11, CS=1
+- Sending new block at BSN 11, CS=CS-1
-- Chunk with length 182 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 17 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
+data block (BSN 11, CS-1): 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
+- Copying data unit 0 (BSN 11)
+msg block (BSN 11, CS-1): 07 00 17 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=52 block=0 data=07 00 17 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==12)
-- Sending new block at BSN 12, CS=1
+- Sending new block at BSN 12, CS=CS-1
-- Chunk with length 162 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 19 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39
+data block (BSN 12, CS-1): 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39
+- Copying data unit 0 (BSN 12)
+msg block (BSN 12, CS-1): 07 00 19 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=56 block=1 data=07 00 19 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==13)
-- Sending new block at BSN 13, CS=1
+- Sending new block at BSN 13, CS=CS-1
-- Chunk with length 142 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 1b 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
+data block (BSN 13, CS-1): 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
+- Copying data unit 0 (BSN 13)
+msg block (BSN 13, CS-1): 07 00 1b 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=60 block=2 data=07 00 1b 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==14)
-- Sending new block at BSN 14, CS=1
+- Sending new block at BSN 14, CS=CS-1
-- Chunk with length 122 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 1d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61
+data block (BSN 14, CS-1): 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61
+- Copying data unit 0 (BSN 14)
+msg block (BSN 14, CS-1): 07 00 1d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=65 block=3 data=07 00 1d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==15)
-- Sending new block at BSN 15, CS=1
+- Sending new block at BSN 15, CS=CS-1
-- Chunk with length 102 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 1f 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
+data block (BSN 15, CS-1): 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
+- Copying data unit 0 (BSN 15)
+msg block (BSN 15, CS-1): 07 00 1f 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=69 block=4 data=07 00 1f 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==16)
-- Sending new block at BSN 16, CS=1
+- Sending new block at BSN 16, CS=CS-1
-- Chunk with length 82 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 21 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
+data block (BSN 16, CS-1): 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
+- Copying data unit 0 (BSN 16)
+msg block (BSN 16, CS-1): 07 00 21 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=73 block=5 data=07 00 21 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==17)
-- Sending new block at BSN 17, CS=1
+- Sending new block at BSN 17, CS=CS-1
-- Chunk with length 62 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 23 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
+data block (BSN 17, CS-1): 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
+- Copying data unit 0 (BSN 17)
+msg block (BSN 17, CS-1): 07 00 23 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=78 block=6 data=07 00 23 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==18)
-- Sending new block at BSN 18, CS=1
+- Sending new block at BSN 18, CS=CS-1
-- Chunk with length 42 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 25 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1
+data block (BSN 18, CS-1): 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1
+- Copying data unit 0 (BSN 18)
+msg block (BSN 18, CS-1): 07 00 25 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=82 block=7 data=07 00 25 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==19)
-- Sending new block at BSN 19, CS=1
+- Sending new block at BSN 19, CS=CS-1
-- Chunk with length 22 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 00 27 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
+data block (BSN 19, CS-1): b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
+- Copying data unit 0 (BSN 19)
+msg block (BSN 19, CS-1): 07 00 27 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=86 block=8 data=07 00 27 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==20)
-- Sending new block at BSN 20, CS=1
+- Sending new block at BSN 20, CS=CS-1
-- Chunk with length 2 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=200
-- Empty chunk, added LLC dummy command of size 16, drained_since=0
-- Chunk with length 16 is less than remaining space (17): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=16
-- No space left, so we are done.
-data block: 07 00 28 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=16
+data block (BSN 20, CS-1): 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 20)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so we must wait for requesting downlink ack
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
+msg block (BSN 20, CS-1): 07 00 28 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=91 block=9 data=07 00 28 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge
- ack: (BSN=85)"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"(BSN=20) R=ACK I=NACK
@@ -385,14 +443,16 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) DL analysis, range=0:21, lost=0, re
- V(B): (V(A)=21)""(V(S)-1=20) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==21 .. V(S)==21)
-- Sending new block at BSN 21, CS=1
+- Sending new dummy block at BSN 21, CS=CS-1
-- Empty chunk, added LLC dummy command of size 19, drained_since=4
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
-- No space left, so we are done.
-data block: 07 00 2a 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
+data block (BSN 21, CS-1): 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 21)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so we must wait for requesting downlink ack
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)
+msg block (BSN 21, CS-1): 07 00 2a 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=95 block=10 data=07 00 2a 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge
- ack: (BSN=86)"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"(BSN=21) R=ACK I=NACK
@@ -401,31 +461,33 @@ TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) DL analysis, range=21:22, lost=0, r
- V(B): (V(A)=22)""(V(S)-1=21) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink (V(A)==22 .. V(S)==22)
-- Sending new block at BSN 22, CS=1
+- Sending new dummy block at BSN 22, CS=CS-1
-- Empty chunk, added LLC dummy command of size 19, drained_since=112
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW)len=19
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
-data block: 07 01 2c 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+data block (BSN 22, CS-1): 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 22)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED), so we must wait for requesting downlink ack
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED)
+msg block (BSN 22, CS-1): 07 01 2c 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=203 block=11 data=07 01 2c 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED) downlink acknowledge
- Final ACK received.
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FINISHED) changes state from FINISHED to WAIT RELEASE
TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) starting timer 3193.
-DL packet loss of IMSI= / TLLI=0xffeeddcc: 0%
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) free
-TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) stopping timer 3193.
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE), 0 TBFs, USFs = 00, TFIs = 00000000.
-Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING)
Destroying MS object, TLLI = 0xffeeddcc
********** TBF ends here **********
Searching for first unallocated TFI: TRX=0
Found TFI=0.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -445,7 +507,7 @@ TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW
Searching for first unallocated TFI: TRX=0
Found TFI=1.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -467,22 +529,24 @@ The MS object cannot fully confirm an unexpected TLLI: 0xf1000002, partly confir
Modifying MS object, TLLI = 0xf1000001, IMSI '' -> '001001000000001'
Modifying MS object, TLLI = 0xf1000001, IMSI '001001000000001' -> '001001000000002'
TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW) the IMSI '001001000000002' was already assigned to another MS object: TLLI = 0xf1000001, that IMSI will be removed
-TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=FLOW) free
-TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=FLOW) Software error: Pending downlink assignment. This may not happen, because the assignment message never gets transmitted. Please be sure not to free in this state. PLEASE FIX!
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=FLOW), 1 TBFs, USFs = 00, TFIs = 00000002.
-Detaching TBF from MS object, TLLI = 0xf1000001, TBF = TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=FLOW)
+TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=FLOW) changes state from FLOW to RELEASING
+TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=RELEASING) Software error: Pending downlink assignment. This may not happen, because the assignment message never gets transmitted. Please be sure not to free in this state. PLEASE FIX!
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=RELEASING), 1 TBFs, USFs = 00, TFIs = 00000002.
+Detaching TBF from MS object, TLLI = 0xf1000001, TBF = TBF(TFI=0 TLLI=0xf1000001 DIR=DL STATE=RELEASING)
********** TBF ends here **********
Modifying MS object, TLLI = 0xf1000002, IMSI '' -> '001001000000002'
Clearing MS object, TLLI: 0xf1000001, IMSI: '001001000000002'
Destroying MS object, TLLI = 0x00000000
-TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW) free
-TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW) Software error: Pending downlink assignment. This may not happen, because the assignment message never gets transmitted. Please be sure not to free in this state. PLEASE FIX!
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW), 0 TBFs, USFs = 00, TFIs = 00000000.
-Detaching TBF from MS object, TLLI = 0xf1000002, TBF = TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW)
+TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW) changes state from FLOW to RELEASING
+TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=RELEASING) free
+TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=RELEASING) Software error: Pending downlink assignment. This may not happen, because the assignment message never gets transmitted. Please be sure not to free in this state. PLEASE FIX!
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xf1000002, TBF = TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=RELEASING)
Destroying MS object, TLLI = 0xf1000002
********** TBF ends here **********
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -504,10 +568,12 @@ Modifying MS object, TLLI = 0xc0000000, IMSI '' -> '001001000000000'
Send dowlink assignment for TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000000)
TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 30 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 08 00 23 2b 2b 2b 2b
-TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=ASSIGN) append
+TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xc0000000 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -529,10 +595,12 @@ Modifying MS object, TLLI = 0xc0000001, IMSI '' -> '001001000000001'
Send dowlink assignment for TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000001)
TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 31 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 18 40 23 2b 2b 2b 2b
-TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=ASSIGN) append
+TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=1 TLLI=0xc0000001 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -554,10 +622,12 @@ Modifying MS object, TLLI = 0xc0000002, IMSI '' -> '001001000000002'
Send dowlink assignment for TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000002)
TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 32 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 28 80 23 2b 2b 2b 2b
-TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=ASSIGN) append
+TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=2 TLLI=0xc0000002 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -579,10 +649,12 @@ Modifying MS object, TLLI = 0xc0000003, IMSI '' -> '001001000000003'
Send dowlink assignment for TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000003)
TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 33 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 38 c0 23 2b 2b 2b 2b
-TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=ASSIGN) append
+TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=3 TLLI=0xc0000003 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -604,10 +676,12 @@ Modifying MS object, TLLI = 0xc0000004, IMSI '' -> '001001000000004'
Send dowlink assignment for TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000004)
TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 34 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 49 00 23 2b 2b 2b 2b
-TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=ASSIGN) append
+TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=4 TLLI=0xc0000004 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -629,10 +703,12 @@ Modifying MS object, TLLI = 0xc0000005, IMSI '' -> '001001000000005'
Send dowlink assignment for TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000005)
TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 35 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 59 40 23 2b 2b 2b 2b
-TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=ASSIGN) append
+TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=5 TLLI=0xc0000005 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -654,10 +730,12 @@ Modifying MS object, TLLI = 0xc0000006, IMSI '' -> '001001000000006'
Send dowlink assignment for TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000006)
TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 36 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 69 80 23 2b 2b 2b 2b
-TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=ASSIGN) append
+TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=6 TLLI=0xc0000006 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -679,10 +757,12 @@ Modifying MS object, TLLI = 0xc0000007, IMSI '' -> '001001000000007'
Send dowlink assignment for TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000007)
TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 37 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 79 c0 23 2b 2b 2b 2b
-TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=ASSIGN) append
+TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=7 TLLI=0xc0000007 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -704,10 +784,12 @@ Modifying MS object, TLLI = 0xc0000008, IMSI '' -> '001001000000008'
Send dowlink assignment for TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000008)
TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 38 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 8a 00 23 2b 2b 2b 2b
-TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=ASSIGN) append
+TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=8 TLLI=0xc0000008 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -729,10 +811,12 @@ Modifying MS object, TLLI = 0xc0000009, IMSI '' -> '001001000000009'
Send dowlink assignment for TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000009)
TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 30 39 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 9a 40 23 2b 2b 2b 2b
-TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=ASSIGN) append
+TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=9 TLLI=0xc0000009 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -754,10 +838,12 @@ Modifying MS object, TLLI = 0xc000000a, IMSI '' -> '001001000000010'
Send dowlink assignment for TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000010)
TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 30 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 aa 80 23 2b 2b 2b 2b
-TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=ASSIGN) append
+TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=10 TLLI=0xc000000a DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -779,10 +865,12 @@ Modifying MS object, TLLI = 0xc000000b, IMSI '' -> '001001000000011'
Send dowlink assignment for TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000011)
TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 31 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 ba c0 23 2b 2b 2b 2b
-TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=ASSIGN) append
+TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=11 TLLI=0xc000000b DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -804,10 +892,12 @@ Modifying MS object, TLLI = 0xc000000c, IMSI '' -> '001001000000012'
Send dowlink assignment for TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000012)
TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 32 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 cb 00 23 2b 2b 2b 2b
-TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=ASSIGN) append
+TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=12 TLLI=0xc000000c DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -829,10 +919,12 @@ Modifying MS object, TLLI = 0xc000000d, IMSI '' -> '001001000000013'
Send dowlink assignment for TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000013)
TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 33 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 db 40 23 2b 2b 2b 2b
-TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=ASSIGN) append
+TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=13 TLLI=0xc000000d DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -854,10 +946,12 @@ Modifying MS object, TLLI = 0xc000000e, IMSI '' -> '001001000000014'
Send dowlink assignment for TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000014)
TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 34 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 eb 80 23 2b 2b 2b 2b
-TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=ASSIGN) append
+TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=14 TLLI=0xc000000e DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -879,10 +973,12 @@ Modifying MS object, TLLI = 0xc000000f, IMSI '' -> '001001000000015'
Send dowlink assignment for TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000015)
TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 35 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 00 fb c0 23 2b 2b 2b 2b
-TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=ASSIGN) append
+TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=15 TLLI=0xc000000f DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -904,10 +1000,12 @@ Modifying MS object, TLLI = 0xc0000010, IMSI '' -> '001001000000016'
Send dowlink assignment for TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000016)
TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 36 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 0c 00 23 2b 2b 2b 2b
-TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=ASSIGN) append
+TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=16 TLLI=0xc0000010 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -929,10 +1027,12 @@ Modifying MS object, TLLI = 0xc0000011, IMSI '' -> '001001000000017'
Send dowlink assignment for TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000017)
TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 37 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 1c 40 23 2b 2b 2b 2b
-TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=ASSIGN) append
+TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=17 TLLI=0xc0000011 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -954,10 +1054,12 @@ Modifying MS object, TLLI = 0xc0000012, IMSI '' -> '001001000000018'
Send dowlink assignment for TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000018)
TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 38 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 2c 80 23 2b 2b 2b 2b
-TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=ASSIGN) append
+TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=18 TLLI=0xc0000012 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -979,10 +1081,12 @@ Modifying MS object, TLLI = 0xc0000013, IMSI '' -> '001001000000019'
Send dowlink assignment for TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000019)
TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 31 39 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 3c c0 23 2b 2b 2b 2b
-TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=ASSIGN) append
+TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=19 TLLI=0xc0000013 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1004,10 +1108,12 @@ Modifying MS object, TLLI = 0xc0000014, IMSI '' -> '001001000000020'
Send dowlink assignment for TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000020)
TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 30 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 4d 00 23 2b 2b 2b 2b
-TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=ASSIGN) append
+TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=20 TLLI=0xc0000014 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1029,10 +1135,12 @@ Modifying MS object, TLLI = 0xc0000015, IMSI '' -> '001001000000021'
Send dowlink assignment for TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000021)
TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 31 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 5d 40 23 2b 2b 2b 2b
-TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=ASSIGN) append
+TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=21 TLLI=0xc0000015 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1054,10 +1162,12 @@ Modifying MS object, TLLI = 0xc0000016, IMSI '' -> '001001000000022'
Send dowlink assignment for TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000022)
TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 32 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 6d 80 23 2b 2b 2b 2b
-TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=ASSIGN) append
+TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=22 TLLI=0xc0000016 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1079,10 +1189,12 @@ Modifying MS object, TLLI = 0xc0000017, IMSI '' -> '001001000000023'
Send dowlink assignment for TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000023)
TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 33 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 7d c0 23 2b 2b 2b 2b
-TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=ASSIGN) append
+TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=23 TLLI=0xc0000017 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1104,10 +1216,12 @@ Modifying MS object, TLLI = 0xc0000018, IMSI '' -> '001001000000024'
Send dowlink assignment for TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000024)
TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 34 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 8e 00 23 2b 2b 2b 2b
-TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=ASSIGN) append
+TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=24 TLLI=0xc0000018 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1129,10 +1243,12 @@ Modifying MS object, TLLI = 0xc0000019, IMSI '' -> '001001000000025'
Send dowlink assignment for TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000025)
TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 35 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 9e 40 23 2b 2b 2b 2b
-TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=ASSIGN) append
+TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=25 TLLI=0xc0000019 DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1154,10 +1270,12 @@ Modifying MS object, TLLI = 0xc000001a, IMSI '' -> '001001000000026'
Send dowlink assignment for TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000026)
TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 36 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 ae 80 23 2b 2b 2b 2b
-TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=ASSIGN) append
+TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=26 TLLI=0xc000001a DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1179,10 +1297,12 @@ Modifying MS object, TLLI = 0xc000001b, IMSI '' -> '001001000000027'
Send dowlink assignment for TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000027)
TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 37 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 be c0 23 2b 2b 2b 2b
-TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=ASSIGN) append
+TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=27 TLLI=0xc000001b DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1204,10 +1324,12 @@ Modifying MS object, TLLI = 0xc000001c, IMSI '' -> '001001000000028'
Send dowlink assignment for TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000028)
TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 38 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 cf 00 23 2b 2b 2b 2b
-TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=ASSIGN) append
+TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=28 TLLI=0xc000001c DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1229,10 +1351,12 @@ Modifying MS object, TLLI = 0xc000001d, IMSI '' -> '001001000000029'
Send dowlink assignment for TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000029)
TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 32 39 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 df 40 23 2b 2b 2b 2b
-TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=ASSIGN) append
+TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=29 TLLI=0xc000001d DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1254,10 +1378,12 @@ Modifying MS object, TLLI = 0xc000001e, IMSI '' -> '001001000000030'
Send dowlink assignment for TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000030)
TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 33 30 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 ef 80 23 2b 2b 2b 2b
-TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=ASSIGN) append
+TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=30 TLLI=0xc000001e DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1279,10 +1405,12 @@ Modifying MS object, TLLI = 0xc000001f, IMSI '' -> '001001000000031'
Send dowlink assignment for TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000000031)
TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=30 33 31 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 00 00 01 ff c0 23 2b 2b 2b 2b
-TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=ASSIGN) append
+TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=31 TLLI=0xc000001f DIR=DL STATE=WAIT ASSIGN) append
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1290,7 +1418,7 @@ Slot Allocation (Algorithm A) for class 45
No PDCH resource
Destroying MS object, TLLI = 0x00000000
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Creating MS object, TLLI = 0x00000000
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 45
Slot Allocation (Algorithm A) for class 45
@@ -1312,15 +1440,18 @@ Modifying MS object, TLLI = 0xc0123456, IMSI '' -> '001001000123456'
Send dowlink assignment for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000123456)
TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=34 35 36 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 01 23 45 68 00 23 2b 2b 2b 2b
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) append
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) append
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) free
-PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN), 0 TBFs, USFs = 00, TFIs = 00000000.
-Detaching TBF from MS object, TLLI = 0xc0123456, TBF = TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) append
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) append
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to RELEASING
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=RELEASING) free
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xc0123456, TBF = TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=RELEASING)
********** TBF ends here **********
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=45
+Allocating DL TBF: MS_CLASS=45/0
Slot Allocation (Algorithm A) for class 45
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -1338,34 +1469,42 @@ TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=NULL) [DOWNLINK] START
Send dowlink assignment for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=001001000123456)
TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=4 TA=0 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=34 35 36 2d 06 3f 30 0c 00 00 7d 80 00 00 00 dc 01 23 45 68 00 23 2b 2b 2b 2b
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) append
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==0)
-- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
-- Sending new block at BSN 0, CS=1
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) append
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) (len=19)
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
-- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
-- No space left, so we are done.
-data block: 07 00 00 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN)len=19
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) (len=19)
+data block (BSN 0, CS-1): 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 00 00 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
MSG = 07 00 00 4d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
-- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) (len=19)
-- No space left, so we are done.
-data block: 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN)len=19
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) (len=19)
+data block (BSN 1, CS-1): 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
MSG = 07 00 02 4d 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) downlink (V(A)==0 .. V(S)==2)
-- Sending new block at BSN 2, CS=1
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN)len=19
-- Final block, so we done.
-TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=ASSIGN) changes state from ASSIGN to FINISHED
-data block: 07 01 04 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
+Complete DL frame for TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN)len=19
+TBF(TFI=0 TLLI=0xc0123456 DIR=DL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FINISHED
+data block (BSN 2, CS-1): 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
+- Copying data unit 0 (BSN 2)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling cannot be sheduled in this TS 7, waiting for TS 4
+Polling cannot be scheduled in this TS 7 (first control TS 4)
+msg block (BSN 2, CS-1): 07 01 04 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
MSG = 07 01 04 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1392,31 +1531,31 @@ TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) starting timer 3169.
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) [UPLINK] START
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x03, Fn=2654167 (17,25,9)
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) TX: START Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=0 USF=0
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 03 8b 29 07 00 c8 00 10 0b 2b 2b 2b 2b 2b 2b 2b
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) changes state from FLOW to WAIT ASSIGN
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 00 01 01 f1 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
-TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
-TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=0, BSN=0, SPB=0, PI=0, E=1, TI=1, bitoffs=24
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN) restarting timer 3169 while old timer 3169 pending
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN): Got CS-1 RLC data block: CV=0, BSN=0, SPB=0, PI=0, E=1, TI=1, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN): data_length=20, data=f1 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Decoded premier TLLI=0x00000000 of UL DATA TFI=0.
Modifying MS object, UL TLLI: 0x00000000 -> 0xf1223344, not yet confirmed
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
-- Frame 1 starts at offset 4, length=16, is_complete=1
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) complete UL frame len=16
-LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) len=16
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) complete UL frame len=16
+LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) len=16
No bctx
-- No gaps in received block, last block: BSN=0 CV=0
-- Finished with UL TBF
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) changes state from FLOW to FINISHED
- Scheduling Ack/Nack, because TLLI is included.
-- Scheduling Ack/Nack, because last block has CV==0.
-Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FINISHED)', TA=7
+Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)', TA=7
Got MS: TLLI = 0xf1223344, TA = 7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
+Allocating DL TBF: MS_CLASS=0/0
Slot Allocation (Algorithm A) for class 0
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -1436,13 +1575,16 @@ Modifying MS object, TLLI = 0xf1223344, IMSI '' -> '0011223344'
Send dowlink assignment for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL) on PCH, no TBF exist (IMSI=0011223344)
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
TX: START TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) Immediate Assignment Downlink (PCH)
+ - TRX=0 (0) TS=7 TA=7 pollFN=-1
Sending data request: trx=0 ts=0 sapi=3 arfcn=0 fn=0 block=0 data=33 34 34 2d 06 3f 30 0f 00 00 7d 80 00 07 00 df 12 23 34 48 00 23 2b 2b 2b 2b
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) append
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT ASSIGN) append
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654218 block=8 data=47 94 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1475,21 +1617,25 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654283
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 8f 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1498,8 +1644,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BS
Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)', TA=7
Got MS: TLLI = 0xf1223344, TA = 7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
-Slot Allocation (Algorithm A) for class 0
+Allocating DL TBF: MS_CLASS=1/0
+Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
- Skipping TS 2, because not enabled
@@ -1524,6 +1670,7 @@ MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1556,21 +1703,25 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654283
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 8f 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1578,8 +1729,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BS
- No gaps in received block, last block: BSN=0 CV=15
Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)', TA=7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
-Slot Allocation (Algorithm A) for class 0
+Allocating DL TBF: MS_CLASS=1/0
+Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
- Skipping TS 2, because not enabled
@@ -1604,7 +1755,9 @@ Received RTS for PDCH: TRX=0 TS=7 FN=2654275 block_nr=9 scheduling USF=0 for req
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Scheduled DL Assignment polling on FN=2654288
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Scheduling polling at FN 2654288 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Scheduled DL Assignment polling on FN=2654288, TS=7
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654275 block=9 data=48 08 00 00 0c 72 00 02 08 00 80 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
@@ -1612,7 +1765,7 @@ Got RLC block, coding scheme: CS-1, length: 23 (23))
------------------------- RX : Uplink Control Block -------------------------
RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Packet Control Ack
TBF: [UPLINK] DOWNLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to FLOW
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) stopping timer 0.
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -1624,32 +1777,38 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654279 block_nr=10 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-4
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=10)
-- Sending new block at BSN 0, CS=4
-- Chunk with length 10 is less than remaining space (50): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=10
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=10
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
-data block: 07 01 00 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
+data block (BSN 0, CS-4): 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling sheduled in this TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED): Scheduling polling at FN 2654292 TS 7
+Polling scheduled in this TS 7
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) starting timer 3191.
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) Scheduled Ack/Nack polling on FN=2654292, TS=7
+msg block (BSN 0, CS-4): 0f 01 00 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654279 block=10 data=08 01 00 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
Received RTS for PDCH: TRX=0 TS=7 FN=2654283 block_nr=11 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=1
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) downlink (V(A)==0 .. V(S)==1)
- Restarting at BSN 0, because all blocks have been transmitted.
- Resending BSN 0
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-4): 07 01 00 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654283 block=11 data=00 01 00 29 52 41 55 5f 41 43 43 45 50 54 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654232 (17,39,22), SBFn=2654335
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8c f6 07 00 c0 0c 68 ab 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=1.
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) poll timeout for FN=2654292 (curr FN 2654335)
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) poll timeout for FN=2654292, TS=7 (curr FN 2654335)
- Timeout for polling PACKET DOWNLINK ACK.
- Assignment was on PACCH
- No downlink ACK received yet
@@ -1683,21 +1842,25 @@ Received RTS for PDCH: TRX=0 TS=7 FN=2654335 block_nr=11 scheduling USF=0 for re
TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654348
-Scheduling control message at RTS for TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654348 TS 7
+TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654348, TS=7
+Scheduling control message at RTS for TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654335 block=11 data=48 28 5e ac ce f1 0f 1d 00 00 88 40 09 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN)
-TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=1, CPS=0, RSB=0, rc=184
UL DATA TFI=1 received (V(Q)=0 .. V(R)=0)
TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=1 TLLI=0xf5667788 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1718,6 +1881,7 @@ MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1750,21 +1914,25 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654283
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 83 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1772,8 +1940,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BS
- No gaps in received block, last block: BSN=0 CV=15
Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)', TA=7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
-Slot Allocation (Algorithm A) for class 0
+Allocating DL TBF: MS_CLASS=1/0
+Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
- Skipping TS 2, because not enabled
@@ -1807,6 +1975,7 @@ MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654224 (17,31,14), SBFn=2654327
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b ee 07 00 c0 0c 60 6b 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1814,8 +1983,12 @@ Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
Got RACH from TLLI=0xf1223344 while TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) still exists. Release pending DL TBF
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT RELEASE
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) restarting timer 3193 while old timer 0 pending
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to RELEASING
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) stopping timer 0.
+PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING)
+********** TBF ends here **********
MS requests UL TBF in packet resource request of single block, so we provide one:
********** TBF starts here **********
Allocating UL TBF: MS_CLASS=1/0
@@ -1838,17 +2011,19 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654340
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654340 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654340, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654327 block=9 data=4f 28 5e 24 46 68 83 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=1
+Allocating DL TBF: MS_CLASS=1/0
Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -1857,21 +2032,23 @@ Slot Allocation (Algorithm A) for class 1
- Skipping TS 4, because not enabled
- Skipping TS 5, because not enabled
- Skipping TS 6, because not enabled
-- Assign downlink TS=7 TFI=1
-PDCH(TS 7, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBFs, USFs = 01, TFIs = 00000003.
+- Assign downlink TS=7 TFI=0
+PDCH(TS 7, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 01, TFIs = 00000001.
- Setting Control TS 7
-Attaching TBF to MS object, TLLI = 0xf1223344, TBF = TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL)
-Allocated TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL): trx = 0, ul_slots = 80, dl_slots = 80
+Attaching TBF to MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL)
+Allocated TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL): trx = 0, ul_slots = 80, dl_slots = 80
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Trigger downlink assignment on PACCH
Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) exists
-TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
-TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) starting timer 0.
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL) changes state from NULL to ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) starting timer 0.
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1883,6 +2060,7 @@ MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -1915,21 +2093,25 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654283
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 83 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -1937,8 +2119,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BS
- No gaps in received block, last block: BSN=0 CV=15
Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)', TA=7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
-Slot Allocation (Algorithm A) for class 0
+Allocating DL TBF: MS_CLASS=1/0
+Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
- Skipping TS 2, because not enabled
@@ -1992,16 +2174,25 @@ TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) starting timer 3169.
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) [UPLINK] START
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x03, Fn=2654275 (17,31,13)
TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) TX: START Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=0 USF=0
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 03 8b ed 07 00 c8 00 10 0b 2b 2b 2b 2b 2b 2b 2b
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) changes state from FLOW to WAIT ASSIGN
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 00 01 01 f1 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
-TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
-TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=0, BSN=0, SPB=0, PI=0, E=1, TI=1, bitoffs=24
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN) restarting timer 3169 while old timer 3169 pending
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN): Got CS-1 RLC data block: CV=0, BSN=0, SPB=0, PI=0, E=1, TI=1, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=WAIT ASSIGN): data_length=20, data=f1 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Decoded premier TLLI=0x00000000 of UL DATA TFI=0.
-Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN)
-Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=ASSIGN)
+Got RACH from TLLI=0x00000000 while TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) still exists. Killing pending DL TBF
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to RELEASING
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) stopping timer 0.
+PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 01, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING)
+********** TBF ends here **********
Modifying MS object, TLLI = 0x00000000, IMSI '' -> '0011223344'
Modifying MS object, TLLI = 0x00000000, MS class 0 -> 1
Clearing MS object, TLLI: 0xf1223344, IMSI: '0011223344'
@@ -2011,20 +2202,17 @@ Destroying MS object, TLLI = 0x00000000
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
-- Frame 1 starts at offset 4, length=16, is_complete=1
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) complete UL frame len=16
-LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) len=16
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) complete UL frame len=16
+LLC [PCU -> SGSN] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) len=16
No bctx
-- No gaps in received block, last block: BSN=0 CV=0
-- Finished with UL TBF
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) changes state from FLOW to FINISHED
- Scheduling Ack/Nack, because TLLI is included.
-- Scheduling Ack/Nack, because last block has CV==0.
New MS: TLLI = 0xf1223344, TA = 7, IMSI = 0011223344, LLC = 2
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654218 block=8 data=47 94 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
MS requests UL TBF on RACH, so we provide one:
MS requests single block allocation
RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
Searching for first unallocated TFI: TRX=0
Found TFI=0.
@@ -2057,21 +2245,25 @@ Change control TS to 7 until assinment is complete.
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)s start Packet Uplink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Uplink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Scheduled UL Assignment polling on FN=2654283
-Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) (TRX=0, TS=7)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 83 1d 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
-RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) Packet Control Ack
-TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN)
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN) changes state from ASSIGN to FLOW
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Raising V(R) to 1
- Taking block 0 out, raising V(Q) to 1
- Assembling frames: (len=20)
@@ -2079,8 +2271,8 @@ TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Got CS-1 RLC data block: CV=15, BS
- No gaps in received block, last block: BSN=0 CV=15
Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)', TA=7
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=0
-Slot Allocation (Algorithm A) for class 0
+Allocating DL TBF: MS_CLASS=1/0
+Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
- Skipping TS 2, because not enabled
@@ -2144,7 +2336,9 @@ Received RTS for PDCH: TRX=0 TS=7 FN=2654275 block_nr=9 scheduling USF=0 for req
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Scheduled DL Assignment polling on FN=2654288
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW): Scheduling polling at FN 2654288 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Scheduled DL Assignment polling on FN=2654288, TS=7
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654275 block=9 data=48 08 00 00 0c 72 00 02 08 00 80 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
@@ -2152,7 +2346,7 @@ Got RLC block, coding scheme: CS-1, length: 23 (23))
------------------------- RX : Uplink Control Block -------------------------
RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) Packet Control Ack
TBF: [UPLINK] DOWNLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW)
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to FLOW
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) stopping timer 0.
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2164,13 +2358,15 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654279 block_nr=10 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Sending new block at BSN 0, CS=1
-- Chunk with length 13 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (6) left in block: copy only remaining space, and we are done
-data block: 07 00 00 37 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 4c 4c 43 20 50 41
+data block (BSN 0, CS-1): 37 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 4c 4c 43 20 50 41
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 00 00 37 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 4c 4c 43 20 50 41
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654279 block=10 data=00 00 00 37 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 4c 4c 43 20 50 41
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2182,12 +2378,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654283 block_nr=11 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 7 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (12) left in block: copy only remaining space, and we are done
-data block: 07 00 02 1f 43 4b 45 54 20 30 31 4c 4c 43 20 50 41 43 4b 45 54 20 30
+data block (BSN 1, CS-1): 1f 43 4b 45 54 20 30 31 4c 4c 43 20 50 41 43 4b 45 54 20 30
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 00 02 1f 43 4b 45 54 20 30 31 4c 4c 43 20 50 41 43 4b 45 54 20 30
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654283 block=11 data=00 00 02 1f 43 4b 45 54 20 30 31 4c 4c 43 20 50 41 43 4b 45 54 20 30
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2199,7 +2397,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654288 block_nr=0 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==2)
-- Sending new block at BSN 2, CS=1
+- Sending new block at BSN 2, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2207,7 +2405,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (4) left in block: copy only remaining space, and we are done
-data block: 07 00 04 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 4c 4c 43 20
+data block (BSN 2, CS-1): 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 4c 4c 43 20
+- Copying data unit 0 (BSN 2)
+msg block (BSN 2, CS-1): 07 00 04 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 4c 4c 43 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654288 block=0 data=00 00 04 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 4c 4c 43 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2219,12 +2419,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654292 block_nr=1 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==3)
-- Sending new block at BSN 3, CS=1
+- Sending new block at BSN 3, CS=CS-1
-- Chunk with length 9 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (10) left in block: copy only remaining space, and we are done
-data block: 07 00 06 27 50 41 43 4b 45 54 20 30 34 4c 4c 43 20 50 41 43 4b 45 54
+data block (BSN 3, CS-1): 27 50 41 43 4b 45 54 20 30 34 4c 4c 43 20 50 41 43 4b 45 54
+- Copying data unit 0 (BSN 3)
+msg block (BSN 3, CS-1): 07 00 06 27 50 41 43 4b 45 54 20 30 34 4c 4c 43 20 50 41 43 4b 45 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654292 block=1 data=00 00 06 27 50 41 43 4b 45 54 20 30 34 4c 4c 43 20 50 41 43 4b 45 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2236,7 +2438,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654296 block_nr=2 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==4)
-- Sending new block at BSN 4, CS=1
+- Sending new block at BSN 4, CS=CS-1
-- Chunk with length 3 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2244,7 +2446,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (2) left in block: copy only remaining space, and we are done
-data block: 07 00 08 0e 37 20 30 35 4c 4c 43 20 50 41 43 4b 45 54 20 30 36 4c 4c
+data block (BSN 4, CS-1): 0e 37 20 30 35 4c 4c 43 20 50 41 43 4b 45 54 20 30 36 4c 4c
+- Copying data unit 0 (BSN 4)
+msg block (BSN 4, CS-1): 07 00 08 0e 37 20 30 35 4c 4c 43 20 50 41 43 4b 45 54 20 30 36 4c 4c
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654296 block=2 data=00 00 08 0e 37 20 30 35 4c 4c 43 20 50 41 43 4b 45 54 20 30 36 4c 4c
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2256,12 +2460,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654301 block_nr=3 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==5)
-- Sending new block at BSN 5, CS=1
+- Sending new block at BSN 5, CS=CS-1
-- Chunk with length 11 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (8) left in block: copy only remaining space, and we are done
-data block: 07 00 0a 2f 43 20 50 41 43 4b 45 54 20 30 37 4c 4c 43 20 50 41 43 4b
+data block (BSN 5, CS-1): 2f 43 20 50 41 43 4b 45 54 20 30 37 4c 4c 43 20 50 41 43 4b
+- Copying data unit 0 (BSN 5)
+msg block (BSN 5, CS-1): 07 00 0a 2f 43 20 50 41 43 4b 45 54 20 30 37 4c 4c 43 20 50 41 43 4b
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654301 block=3 data=00 00 0a 2f 43 20 50 41 43 4b 45 54 20 30 37 4c 4c 43 20 50 41 43 4b
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2273,15 +2479,17 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654305 block_nr=4 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==6)
-- Sending new block at BSN 6, CS=1
+- Sending new block at BSN 6, CS=CS-1
-- Chunk with length 5 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
-data block: 07 00 0c 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
+data block (BSN 6, CS-1): 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
+- Copying data unit 0 (BSN 6)
+msg block (BSN 6, CS-1): 07 00 0c 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654305 block=4 data=00 00 0c 16 35 45 54 20 30 38 4c 4c 43 20 50 41 43 4b 45 54 20 30 39
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2293,12 +2501,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654309 block_nr=5 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==7)
-- Sending new block at BSN 7, CS=1
+- Sending new block at BSN 7, CS=CS-1
-- Chunk with length 13 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (6) left in block: copy only remaining space, and we are done
-data block: 07 00 0e 37 4c 4c 43 20 50 41 43 4b 45 54 20 31 30 4c 4c 43 20 50 41
+data block (BSN 7, CS-1): 37 4c 4c 43 20 50 41 43 4b 45 54 20 31 30 4c 4c 43 20 50 41
+- Copying data unit 0 (BSN 7)
+msg block (BSN 7, CS-1): 07 00 0e 37 4c 4c 43 20 50 41 43 4b 45 54 20 31 30 4c 4c 43 20 50 41
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654309 block=5 data=00 00 0e 37 4c 4c 43 20 50 41 43 4b 45 54 20 31 30 4c 4c 43 20 50 41
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2310,12 +2520,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654314 block_nr=6 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==8)
-- Sending new block at BSN 8, CS=1
+- Sending new block at BSN 8, CS=CS-1
-- Chunk with length 7 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (12) left in block: copy only remaining space, and we are done
-data block: 07 00 10 1f 43 4b 45 54 20 31 31 4c 4c 43 20 50 41 43 4b 45 54 20 31
+data block (BSN 8, CS-1): 1f 43 4b 45 54 20 31 31 4c 4c 43 20 50 41 43 4b 45 54 20 31
+- Copying data unit 0 (BSN 8)
+msg block (BSN 8, CS-1): 07 00 10 1f 43 4b 45 54 20 31 31 4c 4c 43 20 50 41 43 4b 45 54 20 31
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654314 block=6 data=00 00 10 1f 43 4b 45 54 20 31 31 4c 4c 43 20 50 41 43 4b 45 54 20 31
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2327,7 +2539,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654318 block_nr=7 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==9)
-- Sending new block at BSN 9, CS=1
+- Sending new block at BSN 9, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2335,7 +2547,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (4) left in block: copy only remaining space, and we are done
-data block: 07 00 12 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 31 33 4c 4c 43 20
+data block (BSN 9, CS-1): 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 31 33 4c 4c 43 20
+- Copying data unit 0 (BSN 9)
+msg block (BSN 9, CS-1): 07 00 12 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 31 33 4c 4c 43 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654318 block=7 data=00 00 12 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 31 33 4c 4c 43 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2347,12 +2561,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654322 block_nr=8 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10)
-- Sending new block at BSN 10, CS=1
+- Sending new block at BSN 10, CS=CS-1
-- Chunk with length 9 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (10) left in block: copy only remaining space, and we are done
-data block: 07 00 14 27 50 41 43 4b 45 54 20 31 34 4c 4c 43 20 50 41 43 4b 45 54
+data block (BSN 10, CS-1): 27 50 41 43 4b 45 54 20 31 34 4c 4c 43 20 50 41 43 4b 45 54
+- Copying data unit 0 (BSN 10)
+msg block (BSN 10, CS-1): 07 00 14 27 50 41 43 4b 45 54 20 31 34 4c 4c 43 20 50 41 43 4b 45 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654322 block=8 data=00 00 14 27 50 41 43 4b 45 54 20 31 34 4c 4c 43 20 50 41 43 4b 45 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2364,7 +2580,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654327 block_nr=9 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==11)
-- Sending new block at BSN 11, CS=1
+- Sending new block at BSN 11, CS=CS-1
-- Chunk with length 3 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2372,7 +2588,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (2) left in block: copy only remaining space, and we are done
-data block: 07 00 16 0e 37 20 31 35 4c 4c 43 20 50 41 43 4b 45 54 20 31 36 4c 4c
+data block (BSN 11, CS-1): 0e 37 20 31 35 4c 4c 43 20 50 41 43 4b 45 54 20 31 36 4c 4c
+- Copying data unit 0 (BSN 11)
+msg block (BSN 11, CS-1): 07 00 16 0e 37 20 31 35 4c 4c 43 20 50 41 43 4b 45 54 20 31 36 4c 4c
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654327 block=9 data=00 00 16 0e 37 20 31 35 4c 4c 43 20 50 41 43 4b 45 54 20 31 36 4c 4c
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2384,12 +2602,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654331 block_nr=10 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==12)
-- Sending new block at BSN 12, CS=1
+- Sending new block at BSN 12, CS=CS-1
-- Chunk with length 11 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (8) left in block: copy only remaining space, and we are done
-data block: 07 00 18 2f 43 20 50 41 43 4b 45 54 20 31 37 4c 4c 43 20 50 41 43 4b
+data block (BSN 12, CS-1): 2f 43 20 50 41 43 4b 45 54 20 31 37 4c 4c 43 20 50 41 43 4b
+- Copying data unit 0 (BSN 12)
+msg block (BSN 12, CS-1): 07 00 18 2f 43 20 50 41 43 4b 45 54 20 31 37 4c 4c 43 20 50 41 43 4b
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654331 block=10 data=00 00 18 2f 43 20 50 41 43 4b 45 54 20 31 37 4c 4c 43 20 50 41 43 4b
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2401,15 +2621,17 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654335 block_nr=11 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==13)
-- Sending new block at BSN 13, CS=1
+- Sending new block at BSN 13, CS=CS-1
-- Chunk with length 5 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
-data block: 07 00 1a 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
+data block (BSN 13, CS-1): 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
+- Copying data unit 0 (BSN 13)
+msg block (BSN 13, CS-1): 07 00 1a 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654335 block=11 data=00 00 1a 16 35 45 54 20 31 38 4c 4c 43 20 50 41 43 4b 45 54 20 31 39
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2421,12 +2643,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654340 block_nr=0 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==14)
-- Sending new block at BSN 14, CS=1
+- Sending new block at BSN 14, CS=CS-1
-- Chunk with length 13 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (6) left in block: copy only remaining space, and we are done
-data block: 07 00 1c 37 4c 4c 43 20 50 41 43 4b 45 54 20 32 30 4c 4c 43 20 50 41
+data block (BSN 14, CS-1): 37 4c 4c 43 20 50 41 43 4b 45 54 20 32 30 4c 4c 43 20 50 41
+- Copying data unit 0 (BSN 14)
+msg block (BSN 14, CS-1): 07 00 1c 37 4c 4c 43 20 50 41 43 4b 45 54 20 32 30 4c 4c 43 20 50 41
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654340 block=0 data=00 00 1c 37 4c 4c 43 20 50 41 43 4b 45 54 20 32 30 4c 4c 43 20 50 41
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2438,12 +2662,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654344 block_nr=1 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==15)
-- Sending new block at BSN 15, CS=1
+- Sending new block at BSN 15, CS=CS-1
-- Chunk with length 7 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (12) left in block: copy only remaining space, and we are done
-data block: 07 00 1e 1f 43 4b 45 54 20 32 31 4c 4c 43 20 50 41 43 4b 45 54 20 32
+data block (BSN 15, CS-1): 1f 43 4b 45 54 20 32 31 4c 4c 43 20 50 41 43 4b 45 54 20 32
+- Copying data unit 0 (BSN 15)
+msg block (BSN 15, CS-1): 07 00 1e 1f 43 4b 45 54 20 32 31 4c 4c 43 20 50 41 43 4b 45 54 20 32
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654344 block=1 data=00 00 1e 1f 43 4b 45 54 20 32 31 4c 4c 43 20 50 41 43 4b 45 54 20 32
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2455,7 +2681,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654348 block_nr=2 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==16)
-- Sending new block at BSN 16, CS=1
+- Sending new block at BSN 16, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2463,7 +2689,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (4) left in block: copy only remaining space, and we are done
-data block: 07 00 20 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 32 33 4c 4c 43 20
+data block (BSN 16, CS-1): 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 32 33 4c 4c 43 20
+- Copying data unit 0 (BSN 16)
+msg block (BSN 16, CS-1): 07 00 20 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 32 33 4c 4c 43 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654348 block=2 data=00 00 20 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 32 33 4c 4c 43 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2475,12 +2703,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654353 block_nr=3 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==17)
-- Sending new block at BSN 17, CS=1
+- Sending new block at BSN 17, CS=CS-1
-- Chunk with length 9 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (10) left in block: copy only remaining space, and we are done
-data block: 07 00 22 27 50 41 43 4b 45 54 20 32 34 4c 4c 43 20 50 41 43 4b 45 54
+data block (BSN 17, CS-1): 27 50 41 43 4b 45 54 20 32 34 4c 4c 43 20 50 41 43 4b 45 54
+- Copying data unit 0 (BSN 17)
+msg block (BSN 17, CS-1): 07 00 22 27 50 41 43 4b 45 54 20 32 34 4c 4c 43 20 50 41 43 4b 45 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654353 block=3 data=00 00 22 27 50 41 43 4b 45 54 20 32 34 4c 4c 43 20 50 41 43 4b 45 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2492,7 +2722,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654357 block_nr=4 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==18)
-- Sending new block at BSN 18, CS=1
+- Sending new block at BSN 18, CS=CS-1
-- Chunk with length 3 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2500,7 +2730,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (2) left in block: copy only remaining space, and we are done
-data block: 07 00 24 0e 37 20 32 35 4c 4c 43 20 50 41 43 4b 45 54 20 32 36 4c 4c
+data block (BSN 18, CS-1): 0e 37 20 32 35 4c 4c 43 20 50 41 43 4b 45 54 20 32 36 4c 4c
+- Copying data unit 0 (BSN 18)
+msg block (BSN 18, CS-1): 07 00 24 0e 37 20 32 35 4c 4c 43 20 50 41 43 4b 45 54 20 32 36 4c 4c
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654357 block=4 data=00 00 24 0e 37 20 32 35 4c 4c 43 20 50 41 43 4b 45 54 20 32 36 4c 4c
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2512,12 +2744,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654361 block_nr=5 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==19)
-- Sending new block at BSN 19, CS=1
+- Sending new block at BSN 19, CS=CS-1
-- Chunk with length 11 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (8) left in block: copy only remaining space, and we are done
-data block: 07 00 26 2f 43 20 50 41 43 4b 45 54 20 32 37 4c 4c 43 20 50 41 43 4b
+data block (BSN 19, CS-1): 2f 43 20 50 41 43 4b 45 54 20 32 37 4c 4c 43 20 50 41 43 4b
+- Copying data unit 0 (BSN 19)
+msg block (BSN 19, CS-1): 07 00 26 2f 43 20 50 41 43 4b 45 54 20 32 37 4c 4c 43 20 50 41 43 4b
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654361 block=5 data=00 00 26 2f 43 20 50 41 43 4b 45 54 20 32 37 4c 4c 43 20 50 41 43 4b
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2529,18 +2763,21 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654366 block_nr=6 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=5
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==20)
-- Sending new block at BSN 20, CS=1
+- Sending new block at BSN 20, CS=CS-1
-- Chunk with length 5 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
+-- No space left, so we are done.
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
--- No space left, so we are done.
-data block: 07 00 28 16 35 45 54 20 32 38 4c 4c 43 20 50 41 43 4b 45 54 20 32 39
+data block (BSN 20, CS-1): 16 35 45 54 20 32 38 4c 4c 43 20 50 41 43 4b 45 54 20 32 39
+- Copying data unit 0 (BSN 20)
- Scheduling Ack/Nack polling, because 20 blocks sent.
-Polling sheduled in this TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW): Scheduling polling at FN 2654379 TS 7
+Polling scheduled in this TS 7
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) Scheduled Ack/Nack polling on FN=2654379, TS=7
+msg block (BSN 20, CS-1): 0f 00 28 16 35 45 54 20 32 38 4c 4c 43 20 50 41 43 4b 45 54 20 32 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654366 block=6 data=08 00 28 16 35 45 54 20 32 38 4c 4c 43 20 50 41 43 4b 45 54 20 32 39
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2552,12 +2789,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654370 block_nr=7 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==21)
-- Sending new block at BSN 21, CS=1
+- Sending new block at BSN 21, CS=CS-1
-- Chunk with length 13 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (6) left in block: copy only remaining space, and we are done
-data block: 07 00 2a 37 4c 4c 43 20 50 41 43 4b 45 54 20 33 30 4c 4c 43 20 50 41
+data block (BSN 21, CS-1): 37 4c 4c 43 20 50 41 43 4b 45 54 20 33 30 4c 4c 43 20 50 41
+- Copying data unit 0 (BSN 21)
+msg block (BSN 21, CS-1): 07 00 2a 37 4c 4c 43 20 50 41 43 4b 45 54 20 33 30 4c 4c 43 20 50 41
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654370 block=7 data=00 00 2a 37 4c 4c 43 20 50 41 43 4b 45 54 20 33 30 4c 4c 43 20 50 41
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2569,12 +2808,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654374 block_nr=8 scheduling free USF for polling at FN=2654379 of TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==22)
-- Sending new block at BSN 22, CS=1
+- Sending new block at BSN 22, CS=CS-1
-- Chunk with length 7 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (12) left in block: copy only remaining space, and we are done
-data block: 07 00 2c 1f 43 4b 45 54 20 33 31 4c 4c 43 20 50 41 43 4b 45 54 20 33
+data block (BSN 22, CS-1): 1f 43 4b 45 54 20 33 31 4c 4c 43 20 50 41 43 4b 45 54 20 33
+- Copying data unit 0 (BSN 22)
+msg block (BSN 22, CS-1): 07 00 2c 1f 43 4b 45 54 20 33 31 4c 4c 43 20 50 41 43 4b 45 54 20 33
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654374 block=8 data=07 00 2c 1f 43 4b 45 54 20 33 31 4c 4c 43 20 50 41 43 4b 45 54 20 33
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2586,7 +2827,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654379 block_nr=9 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==23)
-- Sending new block at BSN 23, CS=1
+- Sending new block at BSN 23, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2594,7 +2835,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (4) left in block: copy only remaining space, and we are done
-data block: 07 00 2e 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 33 33 4c 4c 43 20
+data block (BSN 23, CS-1): 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 33 33 4c 4c 43 20
+- Copying data unit 0 (BSN 23)
+msg block (BSN 23, CS-1): 07 00 2e 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 33 33 4c 4c 43 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654379 block=9 data=00 00 2e 06 37 32 4c 4c 43 20 50 41 43 4b 45 54 20 33 33 4c 4c 43 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2606,12 +2849,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654383 block_nr=10 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==24)
-- Sending new block at BSN 24, CS=1
+- Sending new block at BSN 24, CS=CS-1
-- Chunk with length 9 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (10) left in block: copy only remaining space, and we are done
-data block: 07 00 30 27 50 41 43 4b 45 54 20 33 34 4c 4c 43 20 50 41 43 4b 45 54
+data block (BSN 24, CS-1): 27 50 41 43 4b 45 54 20 33 34 4c 4c 43 20 50 41 43 4b 45 54
+- Copying data unit 0 (BSN 24)
+msg block (BSN 24, CS-1): 07 00 30 27 50 41 43 4b 45 54 20 33 34 4c 4c 43 20 50 41 43 4b 45 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654383 block=10 data=00 00 30 27 50 41 43 4b 45 54 20 33 34 4c 4c 43 20 50 41 43 4b 45 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2623,7 +2868,7 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654387 block_nr=11 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==25)
-- Sending new block at BSN 25, CS=1
+- Sending new block at BSN 25, CS=CS-1
-- Chunk with length 3 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
@@ -2631,7 +2876,9 @@ Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (2) left in block: copy only remaining space, and we are done
-data block: 07 00 32 0e 37 20 33 35 4c 4c 43 20 50 41 43 4b 45 54 20 33 36 4c 4c
+data block (BSN 25, CS-1): 0e 37 20 33 35 4c 4c 43 20 50 41 43 4b 45 54 20 33 36 4c 4c
+- Copying data unit 0 (BSN 25)
+msg block (BSN 25, CS-1): 07 00 32 0e 37 20 33 35 4c 4c 43 20 50 41 43 4b 45 54 20 33 36 4c 4c
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654387 block=11 data=00 00 32 0e 37 20 33 35 4c 4c 43 20 50 41 43 4b 45 54 20 33 36 4c 4c
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2643,12 +2890,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654392 block_nr=0 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==26)
-- Sending new block at BSN 26, CS=1
+- Sending new block at BSN 26, CS=CS-1
-- Chunk with length 11 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 larger than space (8) left in block: copy only remaining space, and we are done
-data block: 07 00 34 2f 43 20 50 41 43 4b 45 54 20 33 37 4c 4c 43 20 50 41 43 4b
+data block (BSN 26, CS-1): 2f 43 20 50 41 43 4b 45 54 20 33 37 4c 4c 43 20 50 41 43 4b
+- Copying data unit 0 (BSN 26)
+msg block (BSN 26, CS-1): 07 00 34 2f 43 20 50 41 43 4b 45 54 20 33 37 4c 4c 43 20 50 41 43 4b
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654392 block=0 data=00 00 34 2f 43 20 50 41 43 4b 45 54 20 33 37 4c 4c 43 20 50 41 43 4b
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2660,17 +2909,19 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654396 block_nr=1 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=7) prio=3
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==27)
-- Sending new block at BSN 27, CS=1
+- Sending new block at BSN 27, CS=CS-1
-- Chunk with length 5 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
- Dequeue next LLC for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=13)
-- Chunk with length 13 is less than remaining space (14): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
-- Final block, so we done.
+Complete DL frame for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=13
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
-data block: 07 01 36 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39
+data block (BSN 27, CS-1): 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39
+- Copying data unit 0 (BSN 27)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling is already sheduled for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED), so we must wait for requesting downlink ack
+Polling is already scheduled for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED)
+msg block (BSN 27, CS-1): 07 01 36 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654396 block=1 data=00 01 36 16 35 45 54 20 33 38 4c 4c 43 20 50 41 43 4b 45 54 20 33 39
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) append
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) append
@@ -2686,12 +2937,44 @@ Got RLC block, coding scheme: CS-1, length: 23 (23))
+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
------------------------- RX : Uplink Control Block -------------------------
RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) Packet Downlink Ack/Nack
+Got GPRS DL ACK bitmap: SSN: 0, BSN 0 to 28 - 1 (28 blocks), "RRRRRRRRRRRRRRRRRRRRRRRRRRRR"
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) downlink acknowledge
+- ack: (BSN=0)"RRRRRRRRRRRRRRRRRRRRRRRRRRRR"(BSN=27) R=ACK I=NACK
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) DL analysis, range=0:28, lost=0, recv=28, skipped=0, bsn=0, info='RRRRRRRRRRRRRRRRRRRRRRRRRRRR....................................'
+- got ack for BSN=0
+- got ack for BSN=1
+- got ack for BSN=2
+- got ack for BSN=3
+- got ack for BSN=4
+- got ack for BSN=5
+- got ack for BSN=6
+- got ack for BSN=7
+- got ack for BSN=8
+- got ack for BSN=9
+- got ack for BSN=10
+- got ack for BSN=11
+- got ack for BSN=12
+- got ack for BSN=13
+- got ack for BSN=14
+- got ack for BSN=15
+- got ack for BSN=16
+- got ack for BSN=17
+- got ack for BSN=18
+- got ack for BSN=19
+- got ack for BSN=20
+- got ack for BSN=21
+- got ack for BSN=22
+- got ack for BSN=23
+- got ack for BSN=24
+- got ack for BSN=25
+- got ack for BSN=26
+- got ack for BSN=27
+- V(B): (V(A)=28)""(V(S)-1=27) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid
- Final ACK received.
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=FINISHED) changes state from FINISHED to WAIT RELEASE
TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) starting timer 3193.
********** TBF starts here **********
-Allocating DL TBF: MS_CLASS=1
+Allocating DL TBF: MS_CLASS=1/0
Slot Allocation (Algorithm A) for class 1
- Skipping TS 0, because not enabled
- Skipping TS 1, because not enabled
@@ -2713,7 +2996,9 @@ Received RTS for PDCH: TRX=0 TS=7 FN=2654400 block_nr=2 scheduling USF=0 for req
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) start Packet Downlink Assignment (PACCH)
+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
------------------------- TX : Packet Downlink Assignment -------------------------
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) Scheduled DL Assignment polling on FN=2654413
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE): Scheduling polling at FN 2654413 TS 7
+TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) Scheduled DL Assignment polling on FN=2654413, TS=7
Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) (TRX=0, TS=7)
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654400 block=2 data=48 08 20 08 0c 72 00 02 18 00 80 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
Got RLC block, coding scheme: CS-1, length: 23 (23))
@@ -2721,13 +3006,13 @@ Got RLC block, coding scheme: CS-1, length: 23 (23))
------------------------- RX : Uplink Control Block -------------------------
RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) Packet Control Ack
TBF: [UPLINK] DOWNLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE)
-DL packet loss of IMSI=0011223344 / TLLI=0xf1223344: 0%
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) free
-TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) stopping timer 3193.
-PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE), 1 TBFs, USFs = 01, TFIs = 00000002.
-Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE)
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) free
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING) stopping timer 3193.
+PDCH(TS 7, TRX 0): Detaching TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING), 1 TBFs, USFs = 01, TFIs = 00000002.
+Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=RELEASING)
********** TBF ends here **********
-TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) changes state from ASSIGN to FLOW
+TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=WAIT ASSIGN) changes state from WAIT ASSIGN to FLOW
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) stopping timer 0.
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2739,10 +3024,12 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654405 block_nr=3 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=CS-1
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Sending new block at BSN 0, CS=1
-- Chunk with length 21 larger than space (20) left in block: copy only remaining space, and we are done
-data block: 07 02 01 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 20 28 54 42 46 20 32
+data block (BSN 0, CS-1): 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 20 28 54 42 46 20 32
+- Copying data unit 0 (BSN 0)
+msg block (BSN 0, CS-1): 07 02 01 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 20 28 54 42 46 20 32
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654405 block=3 data=00 02 01 4c 4c 43 20 50 41 43 4b 45 54 20 30 30 20 28 54 42 46 20 32
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2754,12 +3041,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654409 block_nr=4 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==1)
-- Sending new block at BSN 1, CS=1
+- Sending new block at BSN 1, CS=CS-1
-- Chunk with length 1 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (18) left in block: copy only remaining space, and we are done
-data block: 07 02 02 07 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 31 20 28 54 42 46
+data block (BSN 1, CS-1): 07 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 31 20 28 54 42 46
+- Copying data unit 0 (BSN 1)
+msg block (BSN 1, CS-1): 07 02 02 07 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 31 20 28 54 42 46
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654409 block=4 data=00 02 02 07 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 31 20 28 54 42 46
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2771,12 +3060,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654413 block_nr=5 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==2)
-- Sending new block at BSN 2, CS=1
+- Sending new block at BSN 2, CS=CS-1
-- Chunk with length 3 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (16) left in block: copy only remaining space, and we are done
-data block: 07 02 04 0f 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 32 20 28 54
+data block (BSN 2, CS-1): 0f 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 32 20 28 54
+- Copying data unit 0 (BSN 2)
+msg block (BSN 2, CS-1): 07 02 04 0f 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 32 20 28 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654413 block=5 data=00 02 04 0f 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 32 20 28 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2788,12 +3079,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654418 block_nr=6 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==3)
-- Sending new block at BSN 3, CS=1
+- Sending new block at BSN 3, CS=CS-1
-- Chunk with length 5 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (14) left in block: copy only remaining space, and we are done
-data block: 07 02 06 17 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 20
+data block (BSN 3, CS-1): 17 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 20
+- Copying data unit 0 (BSN 3)
+msg block (BSN 3, CS-1): 07 02 06 17 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654418 block=6 data=00 02 06 17 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30 33 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2805,12 +3098,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654422 block_nr=7 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==4)
-- Sending new block at BSN 4, CS=1
+- Sending new block at BSN 4, CS=CS-1
-- Chunk with length 7 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (12) left in block: copy only remaining space, and we are done
-data block: 07 02 08 1f 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30
+data block (BSN 4, CS-1): 1f 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30
+- Copying data unit 0 (BSN 4)
+msg block (BSN 4, CS-1): 07 02 08 1f 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654422 block=7 data=00 02 08 1f 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54 20 30
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2822,12 +3117,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654426 block_nr=8 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==5)
-- Sending new block at BSN 5, CS=1
+- Sending new block at BSN 5, CS=CS-1
-- Chunk with length 9 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (10) left in block: copy only remaining space, and we are done
-data block: 07 02 0a 27 34 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54
+data block (BSN 5, CS-1): 27 34 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54
+- Copying data unit 0 (BSN 5)
+msg block (BSN 5, CS-1): 07 02 0a 27 34 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654426 block=8 data=00 02 0a 27 34 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b 45 54
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2839,12 +3136,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654431 block_nr=9 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==6)
-- Sending new block at BSN 6, CS=1
+- Sending new block at BSN 6, CS=CS-1
-- Chunk with length 11 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (8) left in block: copy only remaining space, and we are done
-data block: 07 02 0c 2f 20 30 35 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b
+data block (BSN 6, CS-1): 2f 20 30 35 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b
+- Copying data unit 0 (BSN 6)
+msg block (BSN 6, CS-1): 07 02 0c 2f 20 30 35 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654431 block=9 data=00 02 0c 2f 20 30 35 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41 43 4b
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2856,12 +3155,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654435 block_nr=10 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==7)
-- Sending new block at BSN 7, CS=1
+- Sending new block at BSN 7, CS=CS-1
-- Chunk with length 13 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (6) left in block: copy only remaining space, and we are done
-data block: 07 02 0e 37 45 54 20 30 36 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41
+data block (BSN 7, CS-1): 37 45 54 20 30 36 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41
+- Copying data unit 0 (BSN 7)
+msg block (BSN 7, CS-1): 07 02 0e 37 45 54 20 30 36 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654435 block=10 data=00 02 0e 37 45 54 20 30 36 20 28 54 42 46 20 32 29 4c 4c 43 20 50 41
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2873,12 +3174,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654439 block_nr=11 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==8)
-- Sending new block at BSN 8, CS=1
+- Sending new block at BSN 8, CS=CS-1
-- Chunk with length 15 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (4) left in block: copy only remaining space, and we are done
-data block: 07 02 10 3f 43 4b 45 54 20 30 37 20 28 54 42 46 20 32 29 4c 4c 43 20
+data block (BSN 8, CS-1): 3f 43 4b 45 54 20 30 37 20 28 54 42 46 20 32 29 4c 4c 43 20
+- Copying data unit 0 (BSN 8)
+msg block (BSN 8, CS-1): 07 02 10 3f 43 4b 45 54 20 30 37 20 28 54 42 46 20 32 29 4c 4c 43 20
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654439 block=11 data=00 02 10 3f 43 4b 45 54 20 30 37 20 28 54 42 46 20 32 29 4c 4c 43 20
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2890,12 +3193,14 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654444 block_nr=0 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==9)
-- Sending new block at BSN 9, CS=1
+- Sending new block at BSN 9, CS=CS-1
-- Chunk with length 17 is less than remaining space (20): add length header to to delimit LLC frame
Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
- Dequeue next LLC for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) (len=21)
-- Chunk with length 21 larger than space (2) left in block: copy only remaining space, and we are done
-data block: 07 02 12 47 50 41 43 4b 45 54 20 30 38 20 28 54 42 46 20 32 29 4c 4c
+data block (BSN 9, CS-1): 47 50 41 43 4b 45 54 20 30 38 20 28 54 42 46 20 32 29 4c 4c
+- Copying data unit 0 (BSN 9)
+msg block (BSN 9, CS-1): 07 02 12 47 50 41 43 4b 45 54 20 30 38 20 28 54 42 46 20 32 29 4c 4c
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654444 block=0 data=00 02 12 47 50 41 43 4b 45 54 20 30 38 20 28 54 42 46 20 32 29 4c 4c
Received RTS on disabled PDCH: TRX=0 TS=0
Received RTS on disabled PDCH: TRX=0 TS=1
@@ -2907,14 +3212,1904 @@ Received RTS on disabled PDCH: TRX=0 TS=6
Received RTS for PDCH: TRX=0 TS=7 FN=2654448 block_nr=1 scheduling USF=0 for required uplink resource of UL TFI=0
Scheduling data message at RTS for DL TFI=1 (TRX=0, TS=7) prio=3
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==10)
-- Sending new block at BSN 10, CS=1
+- Sending new block at BSN 10, CS=CS-1
-- Chunk with length 19 is less than remaining space (20): add length header to to delimit LLC frame
-Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
-- Final block, so we done.
+Complete DL frame for TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW)len=21
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FLOW) changes state from FLOW to FINISHED
-data block: 07 03 14 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29
+data block (BSN 10, CS-1): 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29
+- Copying data unit 0 (BSN 10)
- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
-Polling sheduled in this TS 7
+TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FINISHED): Scheduling polling at FN 2654461 TS 7
+Polling scheduled in this TS 7
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FINISHED) starting timer 3191.
TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=FINISHED) Scheduled Ack/Nack polling on FN=2654461, TS=7
+msg block (BSN 10, CS-1): 0f 03 14 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29
Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654448 block=1 data=08 03 14 4d 43 20 50 41 43 4b 45 54 20 30 39 20 28 54 42 46 20 32 29
+Not accepting non-EGPRS phone in EGPRS-only mode
+No PDCH resource
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=12/0
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 12
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+Slot Allocation (Algorithm B) for class 12
+- Rx=4 Tx=4 Sum Rx+Tx=5 Tta=2 Ttb=1 Tra=2 Trb=1 Type=1
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Possible DL/UL slots: (TS=0)"..CCCC.."(TS=7)
+- Selected DL slots: (TS=0)"..DDDD.."(TS=7)
+Using 4 slots for DL
+- Reserved DL/UL slots: (TS=0)"..DDCD.."(TS=7)
+- Assigning DL TS 2
+PDCH(TS 2, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 3
+PDCH(TS 3, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 4
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 5
+PDCH(TS 5, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 3c
+DL TBF slots: 0x3c, N: 4, WS: 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to RELEASING
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING) free
+PDCH(TS 2, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 3, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING)
+Destroying MS object, TLLI = 0x00000000
+********** TBF ends here **********
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=12/12
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 12
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 12
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+Slot Allocation (Algorithm B) for class 12
+- Rx=4 Tx=4 Sum Rx+Tx=5 Tta=2 Ttb=1 Tra=2 Trb=1 Type=1
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Possible DL/UL slots: (TS=0)"..CCCC.."(TS=7)
+- Selected DL slots: (TS=0)"..DDDD.."(TS=7)
+Using 4 slots for DL
+- Reserved DL/UL slots: (TS=0)"..DDCD.."(TS=7)
+- Assigning DL TS 2
+PDCH(TS 2, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 3
+PDCH(TS 3, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 4
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Assigning DL TS 5
+PDCH(TS 5, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 3c
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 384
+DL TBF slots: 0x3c, N: 4, WS: 384
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to RELEASING
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS) free
+PDCH(TS 2, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 3, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+PDCH(TS 5, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0x00000000
+********** TBF ends here **********
+Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654218 block=8 data=47 94 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+MS requests UL TBF on RACH, so we provide one:
+MS requests single block allocation
+RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270
+TX: Immediate Assignment Uplink (AGCH)
+ - TRX=0 (0) TS=7 TA=7 TSC=0 TFI=-1 USF=7
+Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+Got RLC block, coding scheme: CS-1, length: 23 (23))
++++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
+------------------------- RX : Uplink Control Block -------------------------
+MS requests UL TBF in packet resource request of single block, so we provide one:
+MS supports EGPRS multislot class 1.
+********** TBF starts here **********
+Allocating UL TBF: MS_CLASS=1/1
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 1
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 1
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 1
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 4, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Assign uplink TS=7 TFI=0 USF=0
+PDCH(TS 7, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS), 1 TBFs, USFs = 01, TFIs = 00000001.
+- Setting Control TS 7
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS): trx = 0, ul_slots = 80, dl_slots = 00
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL EGPRS) changes state from NULL to ASSIGN
+TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=ASSIGN EGPRS) starting timer 3169.
+Modifying MS object, UL TLLI: 0x00000000 -> 0xf1223344, not yet confirmed
+Modifying MS object, TLLI = 0xf1223344, TA 0 -> 7
+Change control TS to 7 until assinment is complete.
+max_cs_ul cannot be derived (current UL CS: UNKNOWN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN EGPRS)s start Packet Uplink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Uplink Assignment -------------------------
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN EGPRS): Scheduling polling at FN 2654283 TS 7
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=ASSIGN EGPRS) changes state from ASSIGN to WAIT ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN EGPRS) Scheduled UL Assignment polling on FN=2654283, TS=7
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN EGPRS) (TRX=0, TS=7)
+Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654270 block=8 data=4f 28 5e 24 46 68 90 f0 0a 39 00 00 88 00 08 2b 2b 2b 2b 2b 2b 2b 2b
+Got RLC block, coding scheme: CS-1, length: 23 (23))
++++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++
+------------------------- RX : Uplink Control Block -------------------------
+RX: [PCU <- BTS] TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN EGPRS) Packet Control Ack
+TBF: [DOWNLINK] UPLINK ASSIGNED TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN EGPRS)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=WAIT ASSIGN EGPRS) changes state from WAIT ASSIGN to FLOW
+Got RLC block, coding scheme: CS-1, length: 23 (23))
+ UL data: 3c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Got CS-1 RLC block: R=0, SI=0, TFI=0, CPS=0, RSB=0, rc=184
+UL DATA TFI=0 received (V(Q)=0 .. V(R)=0)
+max_cs_ul cannot be derived (current UL CS: UNKNOWN)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW EGPRS) restarting timer 3169 while old timer 3169 pending
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW EGPRS): Got CS-1 RLC data block: CV=15, BSN=0, SPB=0, PI=0, E=1, TI=0, bitoffs=24
+- BSN 0 storing in window (0..63)
+TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW EGPRS): data_length=20, data=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+- Raising V(R) to 1
+- Taking block 0 out, raising V(Q) to 1
+- Assembling frames: (len=20)
+-- Frame 1 starts at offset 0, length=20, is_complete=0
+- No gaps in received block, last block: BSN=0 CV=15
+Got 'TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW EGPRS)', TA=7
+Got MS: TLLI = 0xf1223344, TA = 7
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=1/1
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 4, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Assign downlink TS=7 TFI=0
+PDCH(TS 7, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 01, TFIs = 00000001.
+- Setting Control TS 7
+Attaching TBF to MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 80, dl_slots = 80
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+Modifying MS object, TLLI: 0xf1223344 confirmed
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL EGPRS) [DOWNLINK] START
+Modifying MS object, TLLI = 0xf1223344, IMSI '' -> '0011223344'
+Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW EGPRS) exists
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=NULL EGPRS) changes state from NULL to ASSIGN
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN EGPRS) starting timer 0.
+TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN EGPRS) append
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-1
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (22): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 10, drained_since=0
+-- Chunk with length 10 is less than remaining space (11): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+data block (BSN 0, MCS-1): 14 15 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-1): 07 00 00 16 28 2a 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 16 28 2a 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-1
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-1): 07 40 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-1
+-- Chunk with length 490 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-1): 07 80 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-1
+-- Chunk with length 468 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-1): 07 c0 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-1
+-- Chunk with length 446 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-1): 07 00 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-1
+-- Chunk with length 424 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-1): 07 40 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-1
+-- Chunk with length 402 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-1): 07 80 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-1
+-- Chunk with length 380 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-1): 07 c0 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-1
+-- Chunk with length 358 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-1): 07 00 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==9)
+- Sending new block at BSN 9, CS=MCS-1
+-- Chunk with length 336 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 9, MCS-1): 07 40 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 40 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-1
+-- Chunk with length 314 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 10, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-1): 07 80 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 80 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==11)
+- Sending new block at BSN 11, CS=MCS-1
+-- Chunk with length 292 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 11, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 11)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 11, MCS-1): 07 c0 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=52 block=0 data=07 c0 02 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==12)
+- Sending new block at BSN 12, CS=MCS-1
+-- Chunk with length 270 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 12, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 12)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 12, MCS-1): 07 00 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=56 block=1 data=07 00 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==13)
+- Sending new block at BSN 13, CS=MCS-1
+-- Chunk with length 248 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 13, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 13)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 13, MCS-1): 07 40 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=60 block=2 data=07 40 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==14)
+- Sending new block at BSN 14, CS=MCS-1
+-- Chunk with length 226 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 14, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 14)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 14, MCS-1): 07 80 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=65 block=3 data=07 80 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==15)
+- Sending new block at BSN 15, CS=MCS-1
+-- Chunk with length 204 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 15, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 15)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 15, MCS-1): 07 c0 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=69 block=4 data=07 c0 03 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==16)
+- Sending new block at BSN 16, CS=MCS-1
+-- Chunk with length 182 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 16, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 16)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 16, MCS-1): 07 00 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=73 block=5 data=07 00 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==17)
+- Sending new block at BSN 17, CS=MCS-1
+-- Chunk with length 160 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 17, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 17)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 17, MCS-1): 07 40 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=78 block=6 data=07 40 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==18)
+- Sending new block at BSN 18, CS=MCS-1
+-- Chunk with length 138 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 18, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 18)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 18, MCS-1): 07 80 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=82 block=7 data=07 80 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==19)
+- Sending new block at BSN 19, CS=MCS-1
+-- Chunk with length 116 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 19, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 19)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 19, MCS-1): 07 c0 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=86 block=8 data=07 c0 04 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==20)
+- Sending new block at BSN 20, CS=MCS-1
+-- Chunk with length 94 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 20, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 20)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 20, MCS-1): 07 00 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=91 block=9 data=07 00 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==21)
+- Sending new block at BSN 21, CS=MCS-1
+-- Chunk with length 72 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 21, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 21)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 21, MCS-1): 07 40 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=95 block=10 data=07 40 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==22)
+- Sending new block at BSN 22, CS=MCS-1
+-- Chunk with length 50 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 22, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 22)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 22, MCS-1): 07 80 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=99 block=11 data=07 80 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==23)
+- Sending new block at BSN 23, CS=MCS-1
+-- Chunk with length 28 larger than space (22) left in block: copy only remaining space, and we are done
+data block (BSN 23, MCS-1): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 23)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 23, MCS-1): 07 c0 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=104 block=0 data=07 c0 05 96 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==24)
+- Sending new block at BSN 24, CS=MCS-1
+-- Chunk with length 6 is less than remaining space (22): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 14, drained_since=0
+-- Chunk with length 14 is less than remaining space (15): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=14
+data block (BSN 24, MCS-1): 0c 1d 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 24)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 24, MCS-1): 07 00 06 16 18 3a 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=108 block=1 data=07 00 06 16 18 3a 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-2
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (28): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 16, drained_since=0
+-- Chunk with length 16 is less than remaining space (17): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=16
+data block (BSN 0, MCS-2): 14 21 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-2): 07 00 00 12 28 42 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 12 28 42 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-2
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-2): 07 40 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-2
+-- Chunk with length 484 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-2): 07 80 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-2
+-- Chunk with length 456 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-2): 07 c0 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-2
+-- Chunk with length 428 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-2): 07 00 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-2
+-- Chunk with length 400 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-2): 07 40 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-2
+-- Chunk with length 372 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-2): 07 80 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-2
+-- Chunk with length 344 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-2): 07 c0 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-2
+-- Chunk with length 316 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-2): 07 00 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==9)
+- Sending new block at BSN 9, CS=MCS-2
+-- Chunk with length 288 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 9, MCS-2): 07 40 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 40 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-2
+-- Chunk with length 260 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 10, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-2): 07 80 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 80 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==11)
+- Sending new block at BSN 11, CS=MCS-2
+-- Chunk with length 232 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 11, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 11)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 11, MCS-2): 07 c0 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=52 block=0 data=07 c0 02 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==12)
+- Sending new block at BSN 12, CS=MCS-2
+-- Chunk with length 204 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 12, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 12)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 12, MCS-2): 07 00 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=56 block=1 data=07 00 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==13)
+- Sending new block at BSN 13, CS=MCS-2
+-- Chunk with length 176 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 13, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 13)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 13, MCS-2): 07 40 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=60 block=2 data=07 40 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==14)
+- Sending new block at BSN 14, CS=MCS-2
+-- Chunk with length 148 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 14, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 14)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 14, MCS-2): 07 80 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=65 block=3 data=07 80 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==15)
+- Sending new block at BSN 15, CS=MCS-2
+-- Chunk with length 120 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 15, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 15)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 15, MCS-2): 07 c0 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=69 block=4 data=07 c0 03 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==16)
+- Sending new block at BSN 16, CS=MCS-2
+-- Chunk with length 92 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 16, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 16)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 16, MCS-2): 07 00 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=73 block=5 data=07 00 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==17)
+- Sending new block at BSN 17, CS=MCS-2
+-- Chunk with length 64 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 17, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 17)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 17, MCS-2): 07 40 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=78 block=6 data=07 40 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==18)
+- Sending new block at BSN 18, CS=MCS-2
+-- Chunk with length 36 larger than space (28) left in block: copy only remaining space, and we are done
+data block (BSN 18, MCS-2): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 18)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 18, MCS-2): 07 80 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=82 block=7 data=07 80 04 92 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==19)
+- Sending new block at BSN 19, CS=MCS-2
+-- Chunk with length 8 is less than remaining space (28): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 18, drained_since=0
+-- Chunk with length 18 is less than remaining space (19): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=18
+data block (BSN 19, MCS-2): 10 25 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 19)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 19, MCS-2): 07 c0 04 12 20 4a 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=86 block=8 data=07 c0 04 12 20 4a 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-3
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (37): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 25, drained_since=0
+-- Chunk with length 25 is less than remaining space (26): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=25
+data block (BSN 0, MCS-3): 14 33 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-3): 07 00 00 06 28 66 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 06 28 66 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-3
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-3): 07 40 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-3
+-- Chunk with length 475 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-3): 07 80 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-3
+-- Chunk with length 438 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-3): 07 c0 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-3
+-- Chunk with length 401 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-3): 07 00 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-3
+-- Chunk with length 364 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-3): 07 40 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-3
+-- Chunk with length 327 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-3): 07 80 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-3
+-- Chunk with length 290 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-3): 07 c0 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-3
+-- Chunk with length 253 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-3): 07 00 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==9)
+- Sending new block at BSN 9, CS=MCS-3
+-- Chunk with length 216 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 9, MCS-3): 07 40 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 40 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-3
+-- Chunk with length 179 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 10, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-3): 07 80 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 80 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==11)
+- Sending new block at BSN 11, CS=MCS-3
+-- Chunk with length 142 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 11, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 11)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 11, MCS-3): 07 c0 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=52 block=0 data=07 c0 02 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==12)
+- Sending new block at BSN 12, CS=MCS-3
+-- Chunk with length 105 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 12, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 12)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 12, MCS-3): 07 00 03 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=56 block=1 data=07 00 03 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==13)
+- Sending new block at BSN 13, CS=MCS-3
+-- Chunk with length 68 larger than space (37) left in block: copy only remaining space, and we are done
+data block (BSN 13, MCS-3): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 13)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 13, MCS-3): 07 40 03 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=60 block=2 data=07 40 03 86 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==14)
+- Sending new block at BSN 14, CS=MCS-3
+-- Chunk with length 31 is less than remaining space (37): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 6, drained_since=0
+-- Chunk with length 6 larger than space (5) left in block: copy only remaining space, and we are done
+data block (BSN 14, MCS-3): 3f 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b
+- Copying data unit 0 (BSN 14)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 14, MCS-3): 07 80 03 06 7e 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=65 block=3 data=07 80 03 06 7e 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==15)
+- Sending new block at BSN 15, CS=MCS-3
+-- Chunk with length 1 is less than remaining space (37): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=6
+-- Empty chunk, added LLC dummy command of size 34, drained_since=4
+-- Chunk with length 34 is less than remaining space (35): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=34
+data block (BSN 15, MCS-3): 02 45 2b 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 15)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 15, MCS-3): 07 c0 03 06 04 8a 56 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=69 block=4 data=07 c0 03 06 04 8a 56 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-4
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (44): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 32, drained_since=0
+-- Chunk with length 32 is less than remaining space (33): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=32
+data block (BSN 0, MCS-4): 14 41 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-4): 07 00 00 00 28 82 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 00 28 82 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-4
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-4): 07 40 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-4
+-- Chunk with length 468 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-4): 07 80 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-4
+-- Chunk with length 424 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-4): 07 c0 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-4
+-- Chunk with length 380 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-4): 07 00 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-4
+-- Chunk with length 336 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-4): 07 40 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-4
+-- Chunk with length 292 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-4): 07 80 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-4
+-- Chunk with length 248 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-4): 07 c0 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-4
+-- Chunk with length 204 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-4): 07 00 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==9)
+- Sending new block at BSN 9, CS=MCS-4
+-- Chunk with length 160 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 9, MCS-4): 07 40 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 40 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-4
+-- Chunk with length 116 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 10, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-4): 07 80 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 80 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==11)
+- Sending new block at BSN 11, CS=MCS-4
+-- Chunk with length 72 larger than space (44) left in block: copy only remaining space, and we are done
+data block (BSN 11, MCS-4): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 11)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 11, MCS-4): 07 c0 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=52 block=0 data=07 c0 02 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==12)
+- Sending new block at BSN 12, CS=MCS-4
+-- Chunk with length 28 is less than remaining space (44): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 14, drained_since=0
+-- Chunk with length 14 is less than remaining space (15): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=14
+data block (BSN 12, MCS-4): 38 1d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 12)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 12, MCS-4): 07 00 03 00 70 3a 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=56 block=1 data=07 00 03 00 70 3a 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 86 80 03 56 56 56 56 56 56 56 56 56 56 56 00
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-5
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (56): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 44, drained_since=0
+-- Chunk with length 44 is less than remaining space (45): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=44
+data block (BSN 0, MCS-5): 14 59 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-5): 07 00 00 08 45 56 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 08 45 56 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-5
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-5): 07 40 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-5
+-- Chunk with length 456 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-5): 07 80 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-5
+-- Chunk with length 400 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-5): 07 c0 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-5
+-- Chunk with length 344 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-5): 07 00 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-5
+-- Chunk with length 288 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-5): 07 40 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-5
+-- Chunk with length 232 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-5): 07 80 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-5
+-- Chunk with length 176 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-5): 07 c0 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-5
+-- Chunk with length 120 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-5): 07 00 02 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==9)
+- Sending new block at BSN 9, CS=MCS-5
+-- Chunk with length 64 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-5): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 9, MCS-5): 07 40 02 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=43 block=10 data=07 40 02 58 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-5
+-- Chunk with length 8 is less than remaining space (56): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 46, drained_since=0
+-- Chunk with length 46 is less than remaining space (47): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=46
+data block (BSN 10, MCS-5): 10 5d 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-5): 07 80 02 08 44 57 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=47 block=11 data=07 80 02 08 44 57 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-6
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 62, drained_since=0
+-- Chunk with length 62 is less than remaining space (63): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=62
+data block (BSN 0, MCS-6): 14 7d 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-6): 07 00 00 00 45 5f 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 00 45 5f 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Sending new block at BSN 1, CS=MCS-6
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 1, MCS-6): 07 40 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 40 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-6
+-- Chunk with length 438 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-6): 07 80 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==3)
+- Sending new block at BSN 3, CS=MCS-6
+-- Chunk with length 364 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 3, MCS-6): 07 c0 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 c0 00 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-6
+-- Chunk with length 290 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-6): 07 00 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 00 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==5)
+- Sending new block at BSN 5, CS=MCS-6
+-- Chunk with length 216 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 5, MCS-6): 07 40 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 40 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-6
+-- Chunk with length 142 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-6): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-6): 07 80 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 01 50 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==7)
+- Sending new block at BSN 7, CS=MCS-6
+-- Chunk with length 68 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 6, drained_since=0
+-- Chunk with length 6 larger than space (5) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-6): 89 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b
+- Copying data unit 0 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 7, MCS-6): 07 c0 01 40 62 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=34 block=8 data=07 c0 01 40 62 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca 0a
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-6
+-- Chunk with length 1 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=6
+-- Empty chunk, added LLC dummy command of size 71, drained_since=5
+-- Chunk with length 71 is less than remaining space (72): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=71
+data block (BSN 8, MCS-6): 02 8f 2b 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-6): 07 00 02 80 c0 e3 ca 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=39 block=9 data=07 00 02 80 c0 e3 ca 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-7
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (56): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 44, drained_since=0
+-- Chunk with length 44 is less than remaining space (45): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=44
+data block (BSN 0, MCS-7): 14 59 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-5): 07 00 00 08 45 56 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 08 45 56 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Resending BSN 0
+- Sending new block at BSN 1, CS=MCS-7
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 0)
+- Copying data unit 1 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-7): 07 00 00 02 a8 50 64 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 00 02 a8 50 64 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-7
+-- Chunk with length 456 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 3, CS=MCS-7
+-- Chunk with length 400 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Copying data unit 1 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-7): 07 80 00 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-7
+-- Chunk with length 344 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 5, CS=MCS-7
+-- Chunk with length 288 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Copying data unit 1 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-7): 07 00 01 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 00 01 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-7
+-- Chunk with length 232 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 7, CS=MCS-7
+-- Chunk with length 176 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Copying data unit 1 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-7): 07 80 01 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 80 01 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-7
+-- Chunk with length 120 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 8, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 9, CS=MCS-7
+-- Chunk with length 64 larger than space (56) left in block: copy only remaining space, and we are done
+data block (BSN 9, MCS-7): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 8)
+- Copying data unit 1 (BSN 9)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-7): 07 00 02 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 00 02 02 a8 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==10)
+- Sending new block at BSN 10, CS=MCS-7
+-- Chunk with length 8 is less than remaining space (56): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 46, drained_since=0
+-- Chunk with length 46 is less than remaining space (47): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=46
+data block (BSN 10, MCS-7): 10 5d 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 10)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 10, MCS-5): 07 80 02 08 44 57 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=30 block=7 data=07 80 02 08 44 57 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-8
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (68): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 56, drained_since=0
+-- Chunk with length 56 is less than remaining space (57): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=56
+data block (BSN 0, MCS-8): 14 71 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 0)
+- Copying data unit 1 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-8): 07 00 00 00 60 50 c4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 40 11 17 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 00 60 50 c4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 40 11 17 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Resending BSN 0
+- Sending new block at BSN 1, CS=MCS-8
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 0)
+- Copying data unit 1 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-8): 07 00 00 02 60 50 c4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 00 02 60 50 c4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-8
+-- Chunk with length 444 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 3, CS=MCS-8
+-- Chunk with length 376 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Copying data unit 1 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-8): 07 80 00 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-8
+-- Chunk with length 308 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 5, CS=MCS-8
+-- Chunk with length 240 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Copying data unit 1 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-8): 07 00 01 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 00 01 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-8
+-- Chunk with length 172 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 7, CS=MCS-8
+-- Chunk with length 104 larger than space (68) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-8): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 6)
+- Copying data unit 1 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-8): 07 80 01 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 80 01 02 60 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-8
+-- Chunk with length 36 is less than remaining space (68): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 30, drained_since=0
+-- Chunk with length 30 is less than remaining space (31): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=30
+data block (BSN 8, MCS-8): 48 3d 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 8)
+- Copying data unit 1 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-8): 07 00 02 00 60 20 f5 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 80 d4 13 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 00 02 00 60 20 f5 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 80 d4 13 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
+Searching for first unallocated TFI: TRX=0
+ Found TFI=0.
+********** TBF starts here **********
+Allocating DL TBF: MS_CLASS=11/11
+Creating MS object, TLLI = 0x00000000
+Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11
+Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11
+Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS
+Slot Allocation (Algorithm A) for class 0
+- Skipping TS 0, because not enabled
+- Skipping TS 1, because not enabled
+- Skipping TS 2, because not enabled
+- Skipping TS 3, because not enabled
+- Skipping TS 5, because not enabled
+- Skipping TS 6, because not enabled
+- Skipping TS 7, because not enabled
+- Assign downlink TS=4 TFI=0
+PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001.
+- Setting Control TS 4
+Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS)
+Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64
+TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW
+The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+New and old TBF are the same TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) start Packet Downlink Assignment (PACCH)
++++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++
+------------------------- TX : Packet Downlink Assignment -------------------------
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 13 TS 4
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled DL Assignment polling on FN=13, TS=4
+Scheduling control message at RTS for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (TRX=0, TS=4)
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=0 block=0 data=4f 08 20 00 44 02 00 02 08 04 00 c0 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0)
+- Sending new block at BSN 0, CS=MCS-9
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=10)
+-- Chunk with length 10 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10
+-- Empty chunk, added LLC dummy command of size 62, drained_since=0
+-- Chunk with length 62 is less than remaining space (63): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=62
+data block (BSN 0, MCS-9): 14 7d 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 0)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-6): 07 00 00 00 45 5f 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=4 block=1 data=07 00 00 00 45 5f 40 40 40 40 40 40 40 40 40 c0 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append
+Received RTS for PDCH: TRX=0 TS=4 FN=8 block_nr=2 scheduling free USF for polling at FN=13 of TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1)
+- Resending BSN 0
+- Sending new block at BSN 1, CS=MCS-9
+- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=512)
+-- Chunk with length 512 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 1, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 0)
+- Copying data unit 1 (BSN 1)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 0, MCS-9): 07 00 00 02 08 50 f4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=8 block=2 data=07 00 00 02 08 50 f4 05 04 04 04 04 04 04 04 04 04 0c 01 07 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2)
+- Sending new block at BSN 2, CS=MCS-9
+-- Chunk with length 438 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 2, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 3, CS=MCS-9
+-- Chunk with length 364 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 3, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 2)
+- Copying data unit 1 (BSN 3)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 2, MCS-9): 07 80 00 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=13 block=3 data=07 80 00 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==4)
+- Sending new block at BSN 4, CS=MCS-9
+-- Chunk with length 290 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 4, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 5, CS=MCS-9
+-- Chunk with length 216 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 5, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Copying data unit 0 (BSN 4)
+- Copying data unit 1 (BSN 5)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 4, MCS-9): 07 00 01 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=17 block=4 data=07 00 01 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 14 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==6)
+- Sending new block at BSN 6, CS=MCS-9
+-- Chunk with length 142 larger than space (74) left in block: copy only remaining space, and we are done
+data block (BSN 6, MCS-9): 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+- Sending new block at BSN 7, CS=MCS-9
+-- Chunk with length 68 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=512
+-- Empty chunk, added LLC dummy command of size 6, drained_since=0
+-- Chunk with length 6 larger than space (5) left in block: copy only remaining space, and we are done
+data block (BSN 7, MCS-9): 89 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 43 c0 01 2b 2b
+- Copying data unit 0 (BSN 6)
+- Copying data unit 1 (BSN 7)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 6, MCS-9): 07 80 01 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 90 18 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 02
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=21 block=5 data=07 80 01 02 08 05 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 90 18 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 30 04 1c b0 b2 02
+Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=3
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==8)
+- Sending new block at BSN 8, CS=MCS-9
+-- Chunk with length 1 is less than remaining space (74): add length header to to delimit LLC frame
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=6
+-- Empty chunk, added LLC dummy command of size 71, drained_since=5
+-- Chunk with length 71 is less than remaining space (72): add length header to to delimit LLC frame
+-- No space left, so we are done.
+Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=71
+data block (BSN 8, MCS-9): 02 8f 2b 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+- Restarting at BSN 0, because all blocks have been transmitted (FLOW).
+- Copying data unit 0 (BSN 8)
+- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent).
+Polling is already scheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)
+msg block (BSN 8, MCS-6): 07 00 02 80 c0 e3 ca 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=26 block=6 data=07 00 02 80 c0 e3 ca 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge
+- Final ACK received.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193.
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free
+TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193.
+PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000.
+Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS)
+Destroying MS object, TLLI = 0xffeeddcc
+********** TBF ends here **********
diff --git a/tests/tbf/TbfTest.ok b/tests/tbf/TbfTest.ok
index 0ad9ad4..441b444 100644
--- a/tests/tbf/TbfTest.ok
+++ b/tests/tbf/TbfTest.ok
@@ -1,5 +1,11 @@
=== start test_tbf_base ===
=== end test_tbf_base ===
+=== start test_tbf_tlli_update ===
+=== end test_tbf_tlli_update ===
+=== start test_tbf_final_ack ===
+=== end test_tbf_final_ack ===
+=== start test_tbf_final_ack ===
+=== end test_tbf_final_ack ===
=== start test_tbf_delayed_release ===
=== end test_tbf_delayed_release ===
=== start test_tbf_imsi ===
@@ -20,3 +26,20 @@
=== end test_tbf_dl_flow_and_rach_single_phase ===
=== start test_tbf_dl_reuse ===
=== end test_tbf_dl_reuse ===
+=== start test_tbf_gprs_egprs ===
+=== end test_tbf_gprs_egprs ===
+=== start test_tbf_ws ===
+=== end test_tbf_ws ===
+=== start test_tbf_egprs_two_phase ===
+=== end test_tbf_egprs_two_phase ===
+=== start test_tbf_egprs_dl ===
+Testing MCS-1
+Testing MCS-2
+Testing MCS-3
+Testing MCS-4
+Testing MCS-5
+Testing MCS-6
+Testing MCS-7
+Testing MCS-8
+Testing MCS-9
+=== end test_tbf_egprs_dl ===
diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp
index 776e051..c56b125 100644
--- a/tests/types/TypesTest.cpp
+++ b/tests/types/TypesTest.cpp
@@ -147,7 +147,7 @@ static void test_rlc_v_n()
static void test_rlc_dl_ul_basic()
{
{
- gprs_rlc_dl_window dl_win = { 0, };
+ gprs_rlc_dl_window dl_win;
OSMO_ASSERT(dl_win.window_empty());
OSMO_ASSERT(!dl_win.window_stalled());
OSMO_ASSERT(dl_win.distance() == 0);
@@ -192,7 +192,7 @@ static void test_rlc_dl_ul_basic()
}
{
- gprs_rlc_ul_window ul_win = { 0, };
+ gprs_rlc_ul_window ul_win;
int count;
const char *rbb;
char win_rbb[65];
@@ -327,8 +327,12 @@ static void test_rlc_dl_ul_basic()
{
uint16_t lost = 0, recv = 0;
char show_rbb[65];
+ uint8_t bits_data[8];
BTS dummy_bts;
- gprs_rlc_dl_window dl_win = { 0, };
+ gprs_rlc_dl_window dl_win;
+ bitvec bits;
+ int bsn_begin, bsn_end, num_blocks;
+ Ack_Nack_Description_t desc;
dl_win.m_v_b.reset();
@@ -348,13 +352,61 @@ static void test_rlc_dl_ul_basic()
}
uint8_t rbb_cmp[8] = { 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff };
- Decoding::extract_rbb(rbb_cmp, show_rbb);
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ memcpy(desc.RECEIVED_BLOCK_BITMAP, rbb_cmp,
+ sizeof(desc.RECEIVED_BLOCK_BITMAP));
+ desc.FINAL_ACK_INDICATION = 0;
+ desc.STARTING_SEQUENCE_NUMBER = 35;
+
+ num_blocks = Decoding::decode_gprs_acknack_bits(
+ &desc, &bits,
+ &bsn_begin, &bsn_end, &dl_win);
+ Decoding::extract_rbb(&bits, show_rbb);
printf("show_rbb: %s\n", show_rbb);
- dl_win.update(&dummy_bts, show_rbb, 35, &lost, &recv);
+ dl_win.update(&dummy_bts, &bits, 0, &lost, &recv);
OSMO_ASSERT(lost == 0);
OSMO_ASSERT(recv == 35);
+ OSMO_ASSERT(bsn_begin == 0);
+ OSMO_ASSERT(bsn_end == 35);
+ OSMO_ASSERT(num_blocks == 35);
+ dl_win.raise(dl_win.move_window());
+
+ for (int i = 0; i < 8; ++i) {
+ dl_win.increment_send();
+ OSMO_ASSERT(!dl_win.window_empty());
+ OSMO_ASSERT(dl_win.distance() == 2 + i);
+ }
+
+ uint8_t rbb_cmp2[8] = { 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x31 };
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ memcpy(desc.RECEIVED_BLOCK_BITMAP, rbb_cmp2,
+ sizeof(desc.RECEIVED_BLOCK_BITMAP));
+ desc.FINAL_ACK_INDICATION = 0;
+ desc.STARTING_SEQUENCE_NUMBER = 35 + 8;
+
+ num_blocks = Decoding::decode_gprs_acknack_bits(
+ &desc, &bits,
+ &bsn_begin, &bsn_end, &dl_win);
+ Decoding::extract_rbb(&bits, show_rbb);
+ printf("show_rbb: %s\n", show_rbb);
+
+ lost = recv = 0;
+ dl_win.update(&dummy_bts, &bits, 0, &lost, &recv);
+ OSMO_ASSERT(lost == 5);
+ OSMO_ASSERT(recv == 3);
+ OSMO_ASSERT(bitvec_get_bit_pos(&bits, 0) == 0);
+ OSMO_ASSERT(bitvec_get_bit_pos(&bits, 7) == 1);
+ OSMO_ASSERT(bsn_begin == 35);
+ OSMO_ASSERT(bsn_end == 43);
+ OSMO_ASSERT(num_blocks == 8);
}
}
diff --git a/tests/types/TypesTest.ok b/tests/types/TypesTest.ok
index 6ca2717..cb40d39 100644
--- a/tests/types/TypesTest.ok
+++ b/tests/types/TypesTest.ok
@@ -4,4 +4,5 @@ rbb: 00 00 00 00 00 00 00 01
rbb: 00 00 00 00 00 00 00 03
rbb: 00 00 00 00 00 00 00 31
rbb: 10 00 00 00 00 00 00 01
-show_rbb: IIIIIIIIIIIIIIIIIIIIIIIIIIIIIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+show_rbb: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+show_rbb: IIRRIIIR