From 939904672961fa7e28397e27f942a7d1fff4bbdf Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Fri, 15 May 2015 15:50:43 +0200 Subject: ms: Support new and old TLLIs According to the specification (GSM 04.08/24.008, 4.7.1.5) after a new P-TMSI has been assigned, the old P-TMSI must be kept basically until it has been used by both sides. Since the TLLI will be derived from the P-TMSI, the old TLLI must also be kept until the new TLLI has been used by both MS and SGSN. This commit modifies the TLLI handling of GprsMs accordingly. set_tlli() is only used with TLLIs derived from MS messages, confirm_tlli() is used with TLLIs derived from messages received from the SGSN. tlli() returns the value set by the MS. check_tlli() matches each of the TLLI used by either MS or SGSN as well as the old TLLI until it has been confirmed. Sponsored-by: On-Waves ehf --- src/gprs_bssgp_pcu.cpp | 16 ++++++++- src/gprs_ms.cpp | 46 ++++++++++++++++++++++-- src/gprs_ms.h | 17 ++++++++- src/gprs_ms_storage.cpp | 4 +-- src/tbf.cpp | 25 ++----------- src/tbf.h | 3 +- src/tbf_dl.cpp | 19 ++++++---- tests/ms/MsTest.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/ms/MsTest.err | 17 +++++++++ tests/ms/MsTest.ok | 2 ++ tests/tbf/TbfTest.cpp | 31 +++++++++++----- tests/tbf/TbfTest.err | 7 +++- 12 files changed, 235 insertions(+), 46 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index db271a5b..1c356670 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -118,6 +118,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) struct bssgp_ud_hdr *budh; uint32_t tlli; + uint32_t tlli_old = 0; uint8_t *data; uint16_t len; char imsi[16] = "000"; @@ -163,9 +164,22 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) LOGP(DBSSGP, LOGL_NOTICE, "BSSGP missing mandatory " "PDU_LIFETIME IE\n"); + /* get optional TLLI old */ + if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) + { + uint8_t tlli_len = TLVP_LEN(tp, BSSGP_IE_PDU_LIFETIME); + uint16_t *e_tlli_old = (uint16_t *) TLVP_VAL(tp, BSSGP_IE_TLLI); + if (tlli_len == 2) + tlli_old = ntohs(*e_tlli_old); + else + LOGP(DBSSGP, LOGL_NOTICE, "BSSGP invalid length of " + "TLLI (old) IE\n"); + } + LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len); - return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len); + return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, tlli_old, imsi, + ms_class, delay_csec, data, len); } int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp) diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index af9e834b..4c2f7cc0 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -58,6 +58,8 @@ GprsMs::GprsMs(uint32_t tlli) : m_ul_tbf(NULL), m_dl_tbf(NULL), m_tlli(tlli), + m_new_ul_tlli(0), + m_new_dl_tlli(0), m_is_idle(true), m_ref(0), m_list(this) @@ -185,12 +187,52 @@ void GprsMs::update_status() void GprsMs::set_tlli(uint32_t tlli) { - if (tlli == m_tlli) + if (tlli == m_tlli || tlli == m_new_ul_tlli) return; + if (tlli != m_new_dl_tlli) { + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, " + "not yet confirmed\n", + this->tlli(), tlli); + m_new_ul_tlli = tlli; + return; + } + LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI: 0x%08x -> 0x%08x\n", + "Modifying MS object, TLLI: 0x%08x -> 0x%08x, " + "already confirmed partly\n", m_tlli, tlli); m_tlli = tlli; + m_new_dl_tlli = 0; + m_new_ul_tlli = 0; +} + +bool GprsMs::confirm_tlli(uint32_t tlli) +{ + if (tlli == m_tlli || tlli == m_new_dl_tlli) + return false; + + if (tlli != m_new_ul_tlli) { + /* The MS has not sent a message with the new TLLI, which may + * happen according to the spec [TODO: add reference]. */ + + LOGP(DRLCMAC, LOGL_INFO, + "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, " + "partly confirmed\n", tlli); + /* Use the network's idea of TLLI as candidate, this does not + * change the result value of tlli() */ + m_new_dl_tlli = tlli; + return false; + } + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli); + + m_tlli = tlli; + m_new_dl_tlli = 0; + m_new_ul_tlli = 0; + + return true; } diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 3a8a2e17..ac1928e7 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -51,8 +51,10 @@ public: gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;} gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;} - uint32_t tlli() const {return m_tlli;} + uint32_t tlli() const; void set_tlli(uint32_t tlli); + bool confirm_tlli(uint32_t tlli); + bool check_tlli(uint32_t tlli); void attach_tbf(gprs_rlcmac_tbf *tbf); void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf); @@ -78,7 +80,20 @@ private: gprs_rlcmac_ul_tbf *m_ul_tbf; gprs_rlcmac_dl_tbf *m_dl_tbf; uint32_t m_tlli; + uint32_t m_new_ul_tlli; + uint32_t m_new_dl_tlli; bool m_is_idle; int m_ref; LListHead m_list; }; + +inline uint32_t GprsMs::tlli() const +{ + return m_new_ul_tlli ? m_new_ul_tlli : m_tlli; +} + +inline bool GprsMs::check_tlli(uint32_t tlli) +{ + return tlli != 0 && + (tlli == m_tlli || tlli == m_new_ul_tlli || tlli == m_new_dl_tlli); +} diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp index 7260f1bb..4f72c86f 100644 --- a/src/gprs_ms_storage.cpp +++ b/src/gprs_ms_storage.cpp @@ -58,9 +58,9 @@ GprsMs *GprsMsStorage::get_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi llist_for_each(pos, &m_list) { ms = pos->entry(); - if (tlli && ms->tlli() == tlli) + if (ms->check_tlli(tlli)) break; - if (old_tlli && ms->tlli() == old_tlli) + if (ms->check_tlli(old_tlli)) break; /* TODO: Check for IMSI */ diff --git a/src/tbf.cpp b/src/tbf.cpp index 799699ae..a3793638 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -95,8 +95,10 @@ void gprs_rlcmac_tbf::update_ms(uint32_t tlli) { if (!ms()) set_ms(bts->ms_store().get_or_create_ms(tlli)); - else + else if (direction == GPRS_RLCMAC_UL_TBF) ms()->set_tlli(tlli); + else + ms()->confirm_tlli(tlli); } gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, @@ -814,27 +816,6 @@ void gprs_rlcmac_tbf::update_tlli(uint32_t tlli) bool changedUl = false; - /* - * During a Routing Area Update (due the assignment of a new - * P-TMSI) the tlli can change. We notice this when receiving - * a PACKET CONTROL ACK. - * When we get a TLLI change on the DL we will look if there - * is a UL TBF and change the tlli there as well. - * - * TODO: There could be multiple DL and UL TBFs and we should - * have a proper way to link all the related TBFs so we can do - * a group update. - */ - if (m_tlli_valid && direction == GPRS_RLCMAC_DL_TBF) { - gprs_rlcmac_tbf *ul_tbf; - ul_tbf = bts->ul_tbf_by_tlli(m_tlli); - - if (ul_tbf) { - ul_tbf->m_tlli = tlli; - changedUl = true; - } - } - /* update the timing advance for the new tlli */ bts->timing_advance()->update(m_tlli, tlli, ta); diff --git a/src/tbf.h b/src/tbf.h index 43b0a271..a2f5bf72 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -328,7 +328,8 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { /* dispatch Unitdata.DL messages */ static int handle(struct gprs_rlcmac_bts *bts, - const uint32_t tlli, const char *imsi, const uint8_t ms_class, + const uint32_t tlli, const uint32_t old_tlli, + const char *imsi, const uint8_t ms_class, const uint16_t delay_csec, const uint8_t *data, const uint16_t len); int append_data(const uint8_t ms_class, diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 5cdac5f5..b258a3c8 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -135,9 +135,10 @@ int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class, } static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts, - const uint32_t tlli, const char *imsi) + const uint32_t tlli, const uint32_t tlli_old, + const char *imsi) { - GprsMs *ms = bts->ms_store().get_ms(tlli, 0, imsi); + GprsMs *ms = bts->ms_store().get_ms(tlli, tlli_old, imsi); if (!ms) return NULL; @@ -146,7 +147,8 @@ static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts, static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, const char *imsi, - const uint32_t tlli, const uint8_t ms_class, + const uint32_t tlli, const uint32_t tlli_old, + const uint8_t ms_class, const uint8_t *data, const uint16_t len) { uint8_t trx, ta, ss; @@ -160,7 +162,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, /* check for uplink data, so we copy our informations */ #warning "Do the same look up for IMSI, TLLI and OLD_TLLI" #warning "Refactor the below lines... into a new method" - ms = bts->bts->ms_store().get_ms(tlli, 0, imsi); + ms = bts->bts->ms_store().get_ms(tlli, tlli_old, imsi); if (ms) ul_tbf = ms->ul_tbf(); @@ -229,22 +231,25 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, * TODO: split into unit test-able parts... */ int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts, - const uint32_t tlli, const char *imsi, + const uint32_t tlli, const uint32_t tlli_old, const char *imsi, const uint8_t ms_class, const uint16_t delay_csec, const uint8_t *data, const uint16_t len) { struct gprs_rlcmac_dl_tbf *dl_tbf; /* check for existing TBF */ - dl_tbf = tbf_lookup_dl(bts->bts, tlli, imsi); + dl_tbf = tbf_lookup_dl(bts->bts, tlli, tlli_old, imsi); if (dl_tbf) { int rc = dl_tbf->append_data(ms_class, delay_csec, data, len); if (rc >= 0) dl_tbf->assign_imsi(imsi); + + if (dl_tbf->ms()) + dl_tbf->ms()->confirm_tlli(tlli); return rc; } - return tbf_new_dl_assignment(bts, imsi, tlli, ms_class, data, len); + return tbf_new_dl_assignment(bts, imsi, tlli, tlli_old, ms_class, data, len); } struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx) diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp index 0895e4db..01f26423 100644 --- a/tests/ms/MsTest.cpp +++ b/tests/ms/MsTest.cpp @@ -232,6 +232,99 @@ static void test_ms_replace_tbf() printf("=== end %s ===\n", __func__); } +static void test_ms_change_tlli() +{ + uint32_t start_tlli = 0xaa000000; + uint32_t new_ms_tlli = 0xff001111; + uint32_t other_sgsn_tlli = 0xff00eeee; + GprsMs *ms; + + printf("=== start %s ===\n", __func__); + + ms = new GprsMs(start_tlli); + + OSMO_ASSERT(ms->is_idle()); + + /* MS announces TLLI, SGSN uses it immediately */ + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->confirm_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(!ms->check_tlli(start_tlli)); + + /* MS announces TLLI, SGSN uses it later */ + ms->set_tlli(start_tlli); + ms->confirm_tlli(start_tlli); + + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->confirm_tlli(start_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->confirm_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(!ms->check_tlli(start_tlli)); + + /* MS announces TLLI, SGSN uses it later after another new TLLI */ + ms->set_tlli(start_tlli); + ms->confirm_tlli(start_tlli); + + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->confirm_tlli(other_sgsn_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli)); + + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli)); + + ms->confirm_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(!ms->check_tlli(start_tlli)); + OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli)); + + /* SGSN uses the new TLLI before it is announced by the MS (shouldn't + * happen in normal use) */ + ms->set_tlli(start_tlli); + ms->confirm_tlli(start_tlli); + + ms->confirm_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == start_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(ms->check_tlli(start_tlli)); + + ms->set_tlli(new_ms_tlli); + OSMO_ASSERT(ms->tlli() == new_ms_tlli); + OSMO_ASSERT(ms->check_tlli(new_ms_tlli)); + OSMO_ASSERT(!ms->check_tlli(start_tlli)); + + delete ms; + + printf("=== end %s ===\n", __func__); +} + static void test_ms_storage() { uint32_t tlli = 0xffeeddbb; @@ -320,6 +413,7 @@ int main(int argc, char **argv) test_ms_state(); test_ms_callback(); test_ms_replace_tbf(); + test_ms_change_tlli(); test_ms_storage(); if (getenv("TALLOC_REPORT_FULL")) diff --git a/tests/ms/MsTest.err b/tests/ms/MsTest.err index 091e0c85..bec98b98 100644 --- a/tests/ms/MsTest.err +++ b/tests/ms/MsTest.err @@ -18,6 +18,23 @@ Attaching TBF to MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 D Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) Destroying MS object, TLLI = 0xffeeddbb +Creating MS object, TLLI = 0xaa000000 +Modifying MS object, UL TLLI: 0xaa000000 -> 0xff001111, not yet confirmed +Modifying MS object, TLLI: 0xff001111 confirmed +Modifying MS object, UL TLLI: 0xff001111 -> 0xaa000000, not yet confirmed +Modifying MS object, TLLI: 0xaa000000 confirmed +Modifying MS object, UL TLLI: 0xaa000000 -> 0xff001111, not yet confirmed +Modifying MS object, TLLI: 0xff001111 confirmed +Modifying MS object, UL TLLI: 0xff001111 -> 0xaa000000, not yet confirmed +Modifying MS object, TLLI: 0xaa000000 confirmed +Modifying MS object, UL TLLI: 0xaa000000 -> 0xff001111, not yet confirmed +The MS object cannot fully confirm an unexpected TLLI: 0xff00eeee, partly confirmed +Modifying MS object, TLLI: 0xff001111 confirmed +Modifying MS object, UL TLLI: 0xff001111 -> 0xaa000000, not yet confirmed +Modifying MS object, TLLI: 0xaa000000 confirmed +The MS object cannot fully confirm an unexpected TLLI: 0xff001111, partly confirmed +Modifying MS object, TLLI: 0xaa000000 -> 0xff001111, already confirmed partly +Destroying MS object, TLLI = 0xff001111 Creating MS object, TLLI = 0xffeeddbb Creating MS object, TLLI = 0xffeeddbc Attaching TBF to MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) diff --git a/tests/ms/MsTest.ok b/tests/ms/MsTest.ok index 219eec1a..004b36d4 100644 --- a/tests/ms/MsTest.ok +++ b/tests/ms/MsTest.ok @@ -8,5 +8,7 @@ ms_active() was called ms_idle() was called === end test_ms_replace_tbf === +=== start test_ms_change_tlli === +=== end test_ms_change_tlli === === start test_ms_storage === === end test_ms_storage === diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index d5bcb674..2ec715bc 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -51,6 +51,8 @@ static void check_tbf(gprs_rlcmac_tbf *tbf) static void test_tbf_tlli_update() { BTS the_bts; + GprsMs *ms, *ms_new; + 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(); @@ -63,6 +65,7 @@ static void test_tbf_tlli_update() 0, 0, 0); dl_tbf->update_tlli(0x2342); dl_tbf->tlli_mark_valid(); + dl_tbf->update_ms(0x2342); dl_tbf->ta = 4; the_bts.timing_advance()->remember(0x2342, dl_tbf->ta); @@ -71,23 +74,33 @@ static void test_tbf_tlli_update() 0, 0, 0); ul_tbf->update_tlli(0x2342); ul_tbf->tlli_mark_valid(); - - OSMO_ASSERT(the_bts.dl_tbf_by_tlli(0x2342) == dl_tbf); - OSMO_ASSERT(the_bts.ul_tbf_by_tlli(0x2342) == ul_tbf); + ms = the_bts.ms_by_tlli(0x2342); + OSMO_ASSERT(ms != NULL); + OSMO_ASSERT(ms->dl_tbf() == dl_tbf); + OSMO_ASSERT(ms->ul_tbf() == ul_tbf); /* * Now check.. that DL changes and that the timing advance * has changed. */ dl_tbf->update_tlli(0x4232); - OSMO_ASSERT(!the_bts.dl_tbf_by_tlli(0x2342)); - OSMO_ASSERT(!the_bts.ul_tbf_by_tlli(0x2342)); + ms->confirm_tlli(0x4232); + + /* It is still there, since the new TLLI has not been used for UL yet */ + ms_new = the_bts.ms_by_tlli(0x2342); + OSMO_ASSERT(ms == ms_new); + + ms_new = the_bts.ms_by_tlli(0x4232); + OSMO_ASSERT(ms == ms_new); + OSMO_ASSERT(ms->dl_tbf() == dl_tbf); + OSMO_ASSERT(ms->ul_tbf() == ul_tbf); - - OSMO_ASSERT(the_bts.dl_tbf_by_tlli(0x4232) == dl_tbf); - OSMO_ASSERT(the_bts.ul_tbf_by_tlli(0x4232) == ul_tbf); + /* Now use the new TLLI for UL */ + ms->set_tlli(0x4232); + ms_new = the_bts.ms_by_tlli(0x2342); + OSMO_ASSERT(ms_new == NULL); OSMO_ASSERT(the_bts.timing_advance()->recall(0x4232) == 4); } @@ -318,7 +331,7 @@ static void test_tbf_exhaustion() snprintf(imsi, sizeof(imsi)-1, "001001%9d", i); - rc = gprs_rlcmac_dl_tbf::handle(bts, tlli, imsi, ms_class, + rc = gprs_rlcmac_dl_tbf::handle(bts, tlli, 0, imsi, ms_class, delay_csec, buf, sizeof(buf)); if (rc < 0) diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 3a58351e..32f9efc4 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -6,6 +6,8 @@ Slot Allocation (Algorithm A) for class 0 - Assign downlink TS=2 - Setting Control TS 2 TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changing tlli from TLLI=0x00000000 TLLI=0x00002342 ul_changed=0 +Creating MS object, TLLI = 0x00002342 +Attaching TBF to MS object, TLLI = 0x00002342, TBF = TBF(TFI=0 TLLI=0x00002342 DIR=DL STATE=NULL) ********** TBF starts here ********** Allocating UL TBF: TFI=0 TRX=0 MS_CLASS=0 Slot Allocation (Algorithm A) for class 0 @@ -13,8 +15,11 @@ Slot Allocation (Algorithm A) for class 0 - Skipping TS 1, because not enabled - Assign uplink TS=2 USF=0 - Setting Control TS 2 +Attaching TBF to MS object, TLLI = 0x00002342, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL) changing tlli from TLLI=0x00000000 TLLI=0x00002342 ul_changed=0 -TBF(TFI=0 TLLI=0x00002342 DIR=DL STATE=NULL) changing tlli from TLLI=0x00002342 TLLI=0x00004232 ul_changed=1 +TBF(TFI=0 TLLI=0x00002342 DIR=DL STATE=NULL) changing tlli from TLLI=0x00002342 TLLI=0x00004232 ul_changed=0 +The MS object cannot fully confirm an unexpected TLLI: 0x00004232, partly confirmed +Modifying MS object, TLLI: 0x00002342 -> 0x00004232, already confirmed partly Searching for first unallocated TFI: TRX=0 first TS=4 Found TFI=0. ********** TBF starts here ********** -- cgit v1.2.3