aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-02-22 09:44:39 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-02-22 09:44:39 +0100
commit4f8438a6cd0f34bb22493b13154e382983bbda01 (patch)
treea9fc520166cbe207245358640824bfe9c435d4aa
parent7f4841b3ac7d27cd6840729f0c4be77bec0c1b27 (diff)
parent7f28c97fcc87d2ce773a2ae91579a84b40d12539 (diff)
Merge remote-tracking branch 'origin/jerlbeck/master'
This adds EDGE support and at the same time is changing a lot of code on GPRS support as well. Due my business decision of completing as much as possible during the time we had the unit test coverage is not as extensive as I had hoped for. This is just the beginning. We do not support mixed GPRS/EDGE support and have plenty of things to improve throughput. Thanks to On-Waves for supporting a project with so many unknowns and uncertainty and Jacob for leading the effort at sysmocom.
-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 43feebc5..10284073 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 36bdbaba..b14d2040 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 d1d738c6..715fb515 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -52,11 +52,14 @@ static BTS s_bts;
static const struct rate_ctr_desc bts_ctr_description[] = {
{ "tbf.dl.alloc", "TBF DL Allocated "},
{ "tbf.dl.freed", "TBF DL Freed "},
+ { "tbf.dl.aborted", "TBF DL Aborted "},
{ "tbf.ul.alloc", "TBF UL Allocated "},
{ "tbf.ul.freed", "TBF UL Freed "},
+ { "tbf.ul.aborted", "TBF UL Aborted "},
{ "tbf.reused", "TBF Reused "},
{ "tbf.alloc.algo-a", "TBF Alloc Algo A "},
{ "tbf.alloc.algo-b", "TBF Alloc Algo B "},
+ { "tbf.failed.egprs-only", "TBF Failed EGPRS-only"},
{ "rlc.sent", "RLC Sent "},
{ "rlc.resent", "RLC Resent "},
{ "rlc.restarted", "RLC Restarted "},
@@ -127,8 +130,6 @@ BTS::BTS()
, m_ms_store(this)
{
memset(&m_bts, 0, sizeof(m_bts));
- INIT_LLIST_HEAD(&m_bts.ul_tbfs);
- INIT_LLIST_HEAD(&m_bts.dl_tbfs);
m_bts.bts = this;
/* initialize back pointers */
@@ -214,14 +215,14 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
{
uint8_t l, trx, ts, any_tbf = 0;
struct gprs_rlcmac_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
struct gprs_rlcmac_paging *pag;
uint8_t slot_mask[8];
int8_t first_ts; /* must be signed */
- llist_head *tbfs_lists[] = {
- &m_bts.ul_tbfs,
- &m_bts.dl_tbfs,
+ LListHead<gprs_rlcmac_tbf> *tbfs_lists[] = {
+ &m_ul_tbfs,
+ &m_dl_tbfs,
NULL
};
@@ -235,7 +236,8 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
* Don't mark, if TBF uses a different slot that is already marked. */
memset(slot_mask, 0, sizeof(slot_mask));
for (l = 0; tbfs_lists[l]; l++) {
- llist_pods_for_each_entry(tbf, tbfs_lists[l], list, lpods) {
+ llist_for_each(pos, tbfs_lists[l]) {
+ tbf = pos->entry();
first_ts = -1;
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
@@ -296,16 +298,17 @@ int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{
struct gprs_rlcmac_dl_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
/* only one TBF can poll on specific TS/FN, because scheduler can only
* schedule one downlink control block (with polling) at a FN per TS */
- llist_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) {
+ llist_for_each(pos, &m_dl_tbfs) {
+ tbf = as_dl_tbf(pos->entry());
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
- && tbf->control_ts == ts) {
- return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
+ && tbf->poll_ts == ts) {
+ return tbf;
}
}
return NULL;
@@ -313,16 +316,17 @@ gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{
struct gprs_rlcmac_ul_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
/* only one TBF can poll on specific TS/FN, because scheduler can only
* schedule one downlink control block (with polling) at a FN per TS */
- llist_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) {
+ llist_for_each(pos, &m_ul_tbfs) {
+ tbf = as_ul_tbf(pos->entry());
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
- && tbf->control_ts == ts) {
- return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ && tbf->poll_ts == ts) {
+ return tbf;
}
}
return NULL;
@@ -462,7 +466,10 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
uint8_t sb = 0;
uint32_t sb_fn = 0;
int rc;
- uint8_t plen;
+ int plen;
+ uint8_t usf = 7;
+ uint8_t tsc;
+ uint16_t ta;
rach_frame();
@@ -481,8 +488,11 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
qta = 0;
if (qta > 252)
qta = 252;
+
+ ta = qta >> 2;
+
if (sb) {
- rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, qta >> 2);
+ rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, ta);
if (rc < 0)
return rc;
LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d "
@@ -492,6 +502,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
sb_fn);
LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink "
"(AGCH)\n");
+ tsc = m_bts.trx[trx_no].pdch[ts_no].tsc;
} else {
// Create new TBF
#warning "Copy and pate with other routines.."
@@ -502,7 +513,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
/* FIXME: send reject */
return -EBUSY;
}
- tbf->set_ta(qta >> 2);
+ tbf->set_ta(ta);
tbf->set_state(GPRS_RLCMAC_FLOW);
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
tbf_timer_start(tbf, 3169, m_bts.t3169, 0);
@@ -514,21 +525,31 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26);
LOGP(DRLCMAC, LOGL_INFO, "%s TX: START Immediate "
"Assignment Uplink (AGCH)\n", tbf_name(tbf));
+ trx_no = tbf->trx->trx_no;
+ ts_no = tbf->first_ts;
+ usf = tbf->m_usf[ts_no];
+ tsc = tbf->tsc();
}
bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
bitvec_unhex(immediate_assignment,
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- if (sb)
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra,
- Fn, qta >> 2, m_bts.trx[trx_no].arfcn, ts_no,
- m_bts.trx[trx_no].pdch[ts_no].tsc, 0, 0, 0, 0, sb_fn, 1,
- m_bts.alpha, m_bts.gamma, -1);
- else
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra,
- Fn, tbf->ta(), tbf->trx->arfcn, tbf->first_ts, tbf->tsc(),
- tbf->tfi(), tbf->m_usf[tbf->first_ts], 0, 0, 0, 0,
- m_bts.alpha, m_bts.gamma, -1);
- pcu_l1if_tx_agch(immediate_assignment, plen);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ " - TRX=%d (%d) TS=%d TA=%d TSC=%d TFI=%d USF=%d\n",
+ trx_no, m_bts.trx[trx_no].arfcn, ts_no, ta, tsc,
+ tbf ? tbf->tfi() : -1, usf);
+
+ plen = Encoding::write_immediate_assignment(
+ tbf, immediate_assignment, 0, ra, Fn, ta,
+ m_bts.trx[trx_no].arfcn, ts_no, tsc, usf, 0, sb_fn,
+ m_bts.alpha, m_bts.gamma, -1);
+
+ if (plen >= 0) {
+ pcu_l1if_tx_agch(immediate_assignment, plen);
+ if (tbf)
+ tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
+ }
+
bitvec_free(immediate_assignment);
return 0;
@@ -552,7 +573,8 @@ void BTS::trigger_dl_ass(
/* change state */
dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
- dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
+ dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
/* start timer */
tbf_timer_start(dl_tbf, 0, Tassign_pacch);
} else {
@@ -570,17 +592,24 @@ void BTS::trigger_dl_ass(
void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi)
{
int plen;
+ unsigned int ts = tbf->first_ts;
LOGP(DRLCMAC, LOGL_INFO, "TX: START %s Immediate Assignment Downlink (PCH)\n", tbf_name(tbf));
bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
/* use request reference that has maximum distance to current time,
* so the assignment will not conflict with possible RACH requests. */
- plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 1, 125,
- (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta(),
- tbf->trx->arfcn, tbf->first_ts, tbf->tsc(), tbf->tfi(), 0, tbf->tlli(), poll,
- tbf->poll_fn, 0, m_bts.alpha, m_bts.gamma, -1);
- pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
+ LOGP(DRLCMAC, LOGL_DEBUG, " - TRX=%d (%d) TS=%d TA=%d pollFN=%d\n",
+ tbf->trx->trx_no, tbf->trx->arfcn,
+ ts, tbf->ta(), poll ? tbf->poll_fn : -1);
+ plen = Encoding::write_immediate_assignment(tbf, immediate_assignment, 1, 125,
+ (tbf->pdch[ts]->last_rts_fn + 21216) % 2715648, tbf->ta(),
+ tbf->trx->arfcn, ts, tbf->tsc(), 7, poll,
+ tbf->poll_fn, m_bts.alpha, m_bts.gamma, -1);
+ if (plen >= 0) {
+ pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
+ tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
+ }
bitvec_free(immediate_assignment);
}
@@ -775,9 +804,19 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+ tbf->direction == new_tbf->direction)
tbf_free(tbf);
+ if ((new_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
+ /* We now know that the PACCH really existed */
+ LOGP(DRLCMAC, LOGL_INFO,
+ "The TBF has been confirmed on the PACCH, "
+ "changed type from CCCH to PACCH for %s\n",
+ tbf_name(new_tbf));
+ new_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+ new_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ }
new_tbf->set_state(GPRS_RLCMAC_FLOW);
/* stop pending assignment timer */
new_tbf->stop_timer();
@@ -803,7 +842,8 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+ tbf->direction == new_tbf->direction)
tbf_free(tbf);
new_tbf->set_state(GPRS_RLCMAC_FLOW);
@@ -891,6 +931,11 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
struct pcu_l1_meas meas;
+ int num_blocks;
+ uint8_t bits_data[RLC_GPRS_WS/8];
+ bitvec bits;
+ int bsn_begin, bsn_end;
+ char show_bits[RLC_GPRS_WS + 1];
tfi = ack_nack->DOWNLINK_TFI;
tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
@@ -917,10 +962,24 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf));
tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ num_blocks = Decoding::decode_gprs_acknack_bits(
+ &ack_nack->Ack_Nack_Description, &bits,
+ &bsn_begin, &bsn_end, &tbf->m_window);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Got GPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+ "\"%s\"\n",
+ ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
+ bsn_begin, bsn_end, num_blocks,
+ (Decoding::extract_rbb(&bits, show_bits), show_bits));
+
rc = tbf->rcvd_dl_ack(
ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION,
- ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
- ack_nack->Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
+ bsn_begin, &bits);
if (rc == 1) {
tbf_free(tbf);
return;
@@ -945,6 +1004,112 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
}
}
+void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nack, uint32_t fn)
+{
+ int8_t tfi = 0; /* must be signed */
+ struct gprs_rlcmac_dl_tbf *tbf;
+ struct pcu_l1_meas meas;
+ int rc;
+ int num_blocks;
+ uint8_t bits_data[RLC_EGPRS_MAX_WS/8];
+ char show_bits[RLC_EGPRS_MAX_WS + 1];
+ bitvec bits;
+ int bsn_begin, bsn_end;
+
+ tfi = ack_nack->DOWNLINK_TFI;
+ tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+ "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
+ fn, tfi, trx_no(), ts_no);
+ return;
+ }
+ if (tbf->tfi() != tfi) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+ "wrong TFI=%d, ignoring!\n", tfi);
+ return;
+ }
+ tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
+ if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
+ tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+ LOGP(DRLCMAC, LOGL_NOTICE, "Recovered EGPRS downlink ack "
+ "for %s\n", tbf_name(tbf));
+ }
+ /* reset N3105 */
+ tbf->n3105 = 0;
+ tbf->stop_t3191();
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "RX: [PCU <- BTS] %s EGPRS Packet Downlink Ack/Nack\n",
+ tbf_name(tbf));
+ tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+ LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS ACK/NACK: "
+ "ut: %d, final: %d, bow: %d, eow: %d, ssn: %d, have_crbb: %d, "
+ "urbb_len:%d, %p, %p, %d, %d, win: %d-%d, urbb: %s\n",
+ (int)ack_nack->EGPRS_AckNack.UnionType,
+ (int)ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+ (int)ack_nack->EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW,
+ (int)ack_nack->EGPRS_AckNack.Desc.END_OF_WINDOW,
+ (int)ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+ (int)ack_nack->EGPRS_AckNack.Desc.Exist_CRBB,
+ (int)ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH,
+ (void *)&ack_nack->EGPRS_AckNack.UnionType,
+ (void *)&ack_nack->EGPRS_AckNack.Desc,
+ (int)offsetof(EGPRS_AckNack_t, Desc),
+ (int)offsetof(EGPRS_AckNack_w_len_t, Desc),
+ tbf->m_window.v_a(),
+ tbf->m_window.v_s(),
+ osmo_hexdump((const uint8_t *)&ack_nack->EGPRS_AckNack.Desc.URBB,
+ sizeof(ack_nack->EGPRS_AckNack.Desc.URBB)));
+
+ bits.data = bits_data;
+ bits.data_len = sizeof(bits_data);
+ bits.cur_bit = 0;
+
+ num_blocks = Decoding::decode_egprs_acknack_bits(
+ &ack_nack->EGPRS_AckNack.Desc, &bits,
+ &bsn_begin, &bsn_end, &tbf->m_window);
+
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "Got EGPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+ "\"%s\"\n",
+ ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+ bsn_begin, bsn_end, num_blocks,
+ (Decoding::extract_rbb(&bits, show_bits), show_bits)
+ );
+
+ rc = tbf->rcvd_dl_ack(
+ ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+ bsn_begin, &bits);
+ if (rc == 1) {
+ tbf_free(tbf);
+ return;
+ }
+
+ /* check for channel request */
+ if (ack_nack->Exist_ChannelRequestDescription) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we provide one:\n");
+
+ /* This call will register the new TBF with the MS on success */
+ tbf_alloc_ul(bts_data(), tbf->trx->trx_no,
+ tbf->ms_class(), tbf->ms()->egprs_ms_class(),
+ tbf->tlli(), tbf->ta(), tbf->ms());
+
+ /* schedule uplink assignment */
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ }
+
+ /* get measurements */
+ if (tbf->ms()) {
+ /* TODO: Implement Measurements parsing for EGPRS */
+ /*
+ get_meas(&meas, &ack_nack->Channel_Quality_Report);
+ tbf->ms()->update_l1_meas(&meas);
+ */
+ }
+}
+
void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn)
{
struct gprs_rlcmac_sba *sba;
@@ -968,28 +1133,24 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request,
ta = ms->ta();
}
+ /* We got a RACH so the MS was in packet idle mode and thus
+ * didn't have any active TBFs */
if (ul_tbf) {
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still "
"exists. Killing pending UL TBF\n",
tlli, tbf_name(ul_tbf));
- /* The MS will not use the old TBF again, so we can
- * safely throw it away immediately */
tbf_free(ul_tbf);
ul_tbf = NULL;
}
if (dl_tbf) {
- /* TODO: There a chance that releasing dl_tbf can be
- * avoided if this PDCH is the control TS of dl_tbf,
- * but this needs to be checked with the spec. If an MS
- * losed the DL TBF because of PDCH mismatches only,
- * this check would make sense. */
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
"TLLI=0x%08x while %s still exists. "
"Release pending DL TBF\n", tlli,
tbf_name(dl_tbf));
- dl_tbf->release();
+ tbf_free(dl_tbf);
+ dl_tbf = NULL;
}
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
"in packet resource request of single "
@@ -1104,6 +1265,9 @@ int gprs_rlcmac_pdch::rcv_control_block(
case MT_PACKET_DOWNLINK_ACK_NACK:
rcv_control_dl_ack_nack(&ul_control_block->u.Packet_Downlink_Ack_Nack, fn);
break;
+ case MT_EGPRS_PACKET_DOWNLINK_ACK_NACK:
+ rcv_control_egprs_dl_ack_nack(&ul_control_block->u.Egprs_Packet_Downlink_Ack_Nack, fn);
+ break;
case MT_PACKET_RESOURCE_REQUEST:
rcv_resource_request(&ul_control_block->u.Packet_Resource_Request, fn);
break;
@@ -1137,7 +1301,7 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
}
LOGP(DRLCMACUL, LOGL_DEBUG, "Got RLC block, coding scheme: %s, "
- "length: %d (%d))\n", cs.name(), len, cs.maxBytesUL());
+ "length: %d (%d))\n", cs.name(), len, cs.usedSizeUL());
if (cs.isGprs())
return rcv_block_gprs(data, fn, meas, cs);
@@ -1155,9 +1319,9 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
struct pcu_l1_meas *meas, GprsCodingScheme cs)
{
int rc;
- struct gprs_rlc_ul_header_egprs rlc_dec;
+ struct gprs_rlc_data_info rlc_dec;
struct gprs_rlcmac_ul_tbf *tbf;
- unsigned len = cs.maxBytesUL();
+ unsigned len = cs.sizeUL();
/* These are always data blocks, since EGPRS still uses CS-1 for
* control blocks (see 44.060, section 10.3, 1st par.)
@@ -1180,6 +1344,8 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
}
}
+ LOGP(DRLCMACUL, LOGL_DEBUG, " UL data: %s\n", osmo_hexdump(data, len));
+
rc = Decoding::rlc_parse_ul_data_header(&rlc_dec, data, cs);
if (rc < 0) {
LOGP(DRLCMACUL, LOGL_ERROR,
@@ -1205,7 +1371,7 @@ int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
return 0;
}
- return tbf->rcv_data_block_acknowledged(&rlc_dec, data, len, meas);
+ return tbf->rcv_data_block_acknowledged(&rlc_dec, data, meas);
}
int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
@@ -1239,13 +1405,15 @@ int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
return rc;
}
-gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi,
+gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(
+ LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi,
enum gprs_rlcmac_tbf_direction dir)
{
gprs_rlcmac_tbf *tbf;
- struct llist_pods *lpods;
+ LListHead<gprs_rlcmac_tbf> *pos;
- llist_pods_for_each_entry(tbf, tbf_list, list, lpods) {
+ llist_for_each(pos, tbf_list) {
+ tbf = pos->entry();
if (tbf->tfi() != tfi)
continue;
if (!tbf->pdch[ts_no])
@@ -1257,14 +1425,12 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l
gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi)
{
- return static_cast<gprs_rlcmac_ul_tbf *>(
- tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF));
+ return as_ul_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF));
}
gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi)
{
- return static_cast<gprs_rlcmac_dl_tbf *>(
- tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF));
+ return as_dl_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF));
}
/* lookup TBF Entity (by TFI) */
@@ -1300,7 +1466,7 @@ void gprs_rlcmac_pdch::attach_tbf(gprs_rlcmac_tbf *tbf)
m_num_tbfs[tbf->direction] += 1;
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ ul_tbf = as_ul_tbf(tbf);
m_assigned_usf |= 1 << ul_tbf->m_usf[ts_no];
}
m_assigned_tfi[tbf->direction] |= 1UL << tbf->tfi();
@@ -1320,7 +1486,7 @@ void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf)
m_num_tbfs[tbf->direction] -= 1;
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
+ ul_tbf = as_ul_tbf(tbf);
m_assigned_usf &= ~(1 << ul_tbf->m_usf[ts_no]);
}
m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi());
diff --git a/src/bts.h b/src/bts.h
index 45432eaa..119f6b2c 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 377c50f4..54cc411c 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 abaa97f4..f2b548c1 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 1cda7b42..58ecd18e 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 7f4bf797..6c50abe3 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 ac66838d..94e9a02f 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 838c667d..da1d26c1 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 04eb3b6f..8601d4f5 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 a91d1bde..aec37623 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 76fe47c2..78f03f84 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 f9b63f26..b07f1757 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 b4db88ce..313e23f4 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 0daeaf5c..57197b22 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 44bc5e13..6b43aa6d 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 017b3112..8f4039c5 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 96dc6d7b..8eb7441a 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 5ca234a4..d6644462 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 aa29b4c6..58fea993 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 ce2a006a..166b15eb 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 1f4ad916..35acf64c 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 8108f742..54e3bc76 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 227fa362..79d8f48a 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 f2acb98a..54f28dfd 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 556f6e83..69b9e3a0 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 a3a2eeba..ad8ad4c2 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 70194f7c..7540d1b3 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 a133d3e7..9e763f4c 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 d338b786..c3efd4d9 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 31150546..96ea0c12 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 6597f07e..9554df35 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 344b0b4a..0930354d 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 66fa9825..e1be8448 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 27c5fe31..77966595 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 0ad9ad47..441b4440 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 776e051e..c56b125a 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 6ca2717c..cb40d398 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