diff --git a/src/tbf.cpp b/src/tbf.cpp index e3a441a7..9f873dc3 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -83,7 +83,8 @@ void gprs_rlcmac_tbf::assign_imsi(const char *imsi_) "%s the IMSI '%s' was already assigned to another " "MS object: TLLI = 0x%08x, that IMSI will be removed\n", name(), imsi_, old_ms->tlli()); - old_ms->set_imsi(""); + + merge_and_clear_ms(old_ms); } m_ms->set_imsi(imsi_); @@ -156,6 +157,49 @@ void gprs_rlcmac_tbf::set_ms(GprsMs *ms) m_ms->attach_tbf(this); } +void gprs_rlcmac_tbf::merge_and_clear_ms(GprsMs *old_ms) +{ + if (old_ms == ms()) + return; + + GprsMs::Guard guard_old(old_ms); + + if (strlen(ms()->imsi()) == 0 && strlen(old_ms->imsi()) != 0) { + ms()->set_imsi(old_ms->imsi()); + old_ms->set_imsi(""); + } + + if (!ms()->ms_class() && old_ms->ms_class()) + ms()->set_ms_class(old_ms->ms_class()); + + /* Clean up the old MS object */ + /* TODO: Use timer? */ + if (old_ms->ul_tbf() && old_ms->ul_tbf()->T == 0) { + if (old_ms->ul_tbf() == this) { + LOGP(DRLCMAC, LOGL_ERROR, + "%s is referred by the old MS " + "and will not be deleted\n", + name()); + set_ms(NULL); + } else { + tbf_free(old_ms->ul_tbf()); + } + } + if (old_ms->dl_tbf() && old_ms->dl_tbf()->T == 0) { + if (old_ms->dl_tbf() == this) { + LOGP(DRLCMAC, LOGL_ERROR, + "%s is referred by the old MS " + "and will not be deleted\n", + name()); + set_ms(NULL); + } else { + tbf_free(old_ms->dl_tbf()); + } + } + + old_ms->reset(); +} + void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir) { if (!ms()) @@ -164,6 +208,18 @@ void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction di if (!tlli) return; + /* TODO: When the TLLI does not match the ms, check if there is another + * MS object that belongs to that TLLI and if yes make sure one of them + * gets deleted. This is the same problem that can arise with + * assign_imsi() so there should be a unified solution */ + if (!ms()->check_tlli(tlli)) { + GprsMs *old_ms; + + old_ms = bts->ms_store().get_ms(tlli, 0, NULL); + if (old_ms) + merge_and_clear_ms(old_ms); + } + if (dir == GPRS_RLCMAC_UL_TBF) ms()->set_tlli(tlli); else diff --git a/src/tbf.h b/src/tbf.h index 5c198d3e..a596ad7e 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -226,6 +226,7 @@ protected: gprs_rlcmac_bts *bts_data() const; int extract_tlli(const uint8_t *data, const size_t len); + void merge_and_clear_ms(GprsMs *old_ms); static const char *tbf_state_name[6]; diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 80bc8188..19895add 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -388,18 +388,23 @@ static void test_tbf_imsi() OSMO_ASSERT(ms1 == ms2); /* use the same IMSI on TBF 2 */ - dl_tbf[1]->assign_imsi("001001000000002"); - ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002"); - OSMO_ASSERT(ms1 != NULL); - OSMO_ASSERT(ms1 != ms2); - OSMO_ASSERT(strcmp(ms1->imsi(), "001001000000002") == 0); - OSMO_ASSERT(strcmp(ms2->imsi(), "") == 0); + { + GprsMs::Guard guard(ms2); + dl_tbf[1]->assign_imsi("001001000000002"); + ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002"); + OSMO_ASSERT(ms1 != NULL); + OSMO_ASSERT(ms1 != ms2); + OSMO_ASSERT(strcmp(ms1->imsi(), "001001000000002") == 0); + OSMO_ASSERT(strcmp(ms2->imsi(), "") == 0); + } + + ms2 = the_bts.ms_store().get_ms(0xf1000001); + OSMO_ASSERT(ms2 == NULL); tbf_free(dl_tbf[1]); ms1 = the_bts.ms_store().get_ms(0, 0, "001001000000002"); OSMO_ASSERT(ms1 == NULL); - tbf_free(dl_tbf[0]); printf("=== end %s ===\n", __func__); } diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 099504f8..35245222 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -462,19 +462,20 @@ 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 -Modifying MS object, TLLI = 0xf1000001, IMSI '001001000000002' -> '' Modifying MS object, TLLI = 0xf1000002, IMSI '' -> '001001000000002' -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), 1 TBFs, USFs = 00, TFIs = 00000001. -Detaching TBF from MS object, TLLI = 0xf1000002, TBF = TBF(TFI=1 TLLI=0xf1000002 DIR=DL STATE=FLOW) -Destroying MS object, TLLI = 0xf1000002 -********** TBF ends here ********** +Modifying MS object, TLLI = 0xf1000001, IMSI '001001000000002' -> '' 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), 0 TBFs, USFs = 00, TFIs = 00000000. +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) -Destroying MS object, TLLI = 0xf1000001 +********** TBF ends here ********** +Clearing MS object, TLLI: 0xf1000001, IMSI: '' +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) +Destroying MS object, TLLI = 0xf1000002 ********** TBF ends here ********** ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45